Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New module @turf/interpolate (proposal) #832

Merged
merged 19 commits into from
Jul 11, 2017
Merged

Conversation

stebogit
Copy link
Collaborator

@stebogit stebogit commented Jul 8, 2017

Implements #24

JSDocs

/**
 * Takes a set of points and estimates their 'property' values on a grid using the Inverse [Distance Weighting (IDW) method.](https://en.wikipedia.org/wiki/Inverse_distance_weighting).
 *
 * @name interpolate
 * @param {FeatureCollection<Point>} points with known value
 * @param {number} cellSize the distance across each grid point
 * @param {string} [gridType='square'] defines the output format based on a Grid Type (options: 'square' | 'point' | 'hex' | 'triangle')
 * @param {string} [property='elevation'] the property name in `points` from which z-values will be pulled
 * @param {string} [units=kilometers] used in calculating cellSize, can be degrees, radians, miles, or kilometers
 * @param {number} [weight=1] exponent regulating the distance-decay weighting
 * @returns {FeatureCollection<Point>} grid of points with 'property'
 */
module.exports = function (points, cellSize, property, units, weight) {

Example

var points = turf.random('points', 15, {
    bbox: [-75.9221, 39.11, -75.05, 39.987]
});
turf.featureEach(points, function(point) {
    point.properties.elevation = Math.random() * 50;
});
var cellSize = 5;
var grid = turf.interpolate(points, cellSize);

screen shot 2017-07-08 at 12 40 20 am

  • add zValue as 3rd coordinate if property is not defined.
  • add tests
  • add all other grid types to library.
  • might replace/integrate @turf/idw ?

@DenisCarriere following #829 I thought maybe it would make sense to implement this module with the IDW method. In fact I don't really know any other interpolation methods, but I'm open to suggestions.
However, this differs from @turf/idw only in outputting a pointGrid instead of a squareGrid. Does it make sense to have two modules here?
If not I would rather merge the two in a single turf-interpolate (I think is more clear to an average user like me, who ignored the meaning of IDW since this morning...) and add to the module an outputType parameter (default to one of the two).

@bakerac4 maybe you want to try this module out and see if it fits your needs.

@stebogit stebogit self-assigned this Jul 8, 2017
@stebogit stebogit changed the title New module @turf/interpolate New module @turf/interpolate (proposal) Jul 8, 2017
@stebogit
Copy link
Collaborator Author

stebogit commented Jul 8, 2017

@DenisCarriere I don't know why the test pass in my computer, but not in Travis... 😞

@DenisCarriere
Copy link
Member

I'll comment more later on this weekend, however for the Travis build fail, I'm guessing it's a decimal precision error, even using Node 6 vs. 7 you could have slight differences. Solution would be to use the @turf/truncate module on the result test/out.

Quick glance, this looks like an awesome module!

const {property, cellSize, units, weight} = geojson.properties;

const grid = interpolate(geojson, cellSize, property, units, weight);
const result = colorize(grid, property);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added @turf/truncate to results (reduce coordinates to 6 decimals).

Node 7 & 8 were passing, but Node 6 was failing (0.0000001 of a difference).

@@ -0,0 +1,10 @@
/// <reference types="geojson" />

import {Points} from '@turf/helpers';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since @turf/helpers is not required in the main package.json, it might be better to include the Full GeoJSON typescript definition instead of importing it (in case the dependencies wouldn't include @turf/helpers).

type Point = GeoJSON.FeatureCollection<GeoJSON.Point>;

/**
* http://turfjs.org/docs/#interpolate
*/
declare function interpolate(points: Points, cellSize: number, property?: number, units?: string, weight?:number): Points;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

property?: number should be a string

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Contradicts my previous comment, but units?: string could use Units instead of string.

import {Units} from '@turf/helpers'

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah! nice to know, I didn't noticed the types in @turf/helpers 👍

- truncate coordinate decimals
- Update Typescript definition
if (!points) throw new Error('points is required');
collectionOf(points, 'Point', 'input must contain Points');
if (!cellSize) throw new Error('cellSize is required');
if (cellSize === undefined || cellSize === null) throw new Error('cellWidth is required');
Copy link
Member

@DenisCarriere DenisCarriere Jul 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to assume this is a duplicate of cellSize.

CellSize cannot be 0, correct?

    if (!cellSize) throw new Error('cellSize is required');
    if (cellSize === undefined || cellSize === null) throw new Error('cellWidth is required');

@DenisCarriere
Copy link
Member

Question: Should we add a round/precision property? That way the elevation properties can be rounded to a specific precision (starting to have a lot of options).

CC: @stebogit

@@ -0,0 +1,16 @@
import * as linearc from '../index'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦‍♂️ Looks like this file came from the previous repo 🤣

I've been putting types.ts at the root directory that way we don't forget it.

One day... all modules will have types.ts to test for the Typescript definitions.

So far this one looks like this:

import * as interpolate from './';
import {point, featureCollection} from '@turf/helpers';

const cellSize = 1;
const property = 'pressure';
const weight = 0.5;
const units = 'miles';
const points = featureCollection([
  point([1, 2]),
  point([12, 13]),
  point([23, 22]),
]);

const grid = interpolate(points, cellSize, property, units, weight);
grid.features[0].properties.pressure;

Copy link
Member

@DenisCarriere DenisCarriere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Looks good to me!

@DenisCarriere
Copy link
Member

DenisCarriere commented Jul 10, 2017

@DenisCarriere
Copy link
Member

DenisCarriere commented Jul 10, 2017

might replace/integrate @turf/idw ?

Agreed, however the only difference with @turf/idw is the output is a FeatureCollection<Polygon>, if we can manage to have interpolate do both or simply integrate this library into idw but keep the output as polygons.

CC: @stebogit

@stebogit
Copy link
Collaborator Author

Should we add a round/precision property?

@DenisCarriere I don't see the number of decimals as an issue, the user can simply round it, if necessary, to the desired precision when using the interpolated value(s)

@DenisCarriere
Copy link
Member

DenisCarriere commented Jul 10, 2017

I don't see the number of decimals as an issue

👍 That works, yea it's not really an issue.

@DenisCarriere
Copy link
Member

@stebogit Have a quick glance at it before we merge, I'm done with any edits.

@DenisCarriere
Copy link
Member

DenisCarriere commented Jul 10, 2017

If not I would rather merge the two in a single turf-interpolate (I think is more clear to an average user like me, who ignored the meaning of IDW since this morning...) and add to the module an outputType parameter (default to one of the two).

👍 Agreed, maybe once we bump up to a major release v5.0 we could do that.

I also prefer the term interpolate vs. IDW (even though this term is commonly used in GIS).

CC: @morganherlocker Thoughts?

@stebogit
Copy link
Collaborator Author

stebogit commented Jul 10, 2017

Agreed, however the only difference with @turf/idw is the output is a FeatureCollection<Polygon>, if we can manage to have interpolate do both or simply integrate this library into idw but keep the output as polygons.

@DenisCarriere yes, having this module doing both is really easy (I'll implement that).

I also prefer the term interpolate vs. IDW (even though this term is commonly used in GIS).

👍 we could add an outputType = 'squares'|'points' parameter , defaulting to 'polygon'.
This module should also be faster than the current implementation of idw.

When I implemented this I was wondering if @morganherlocker had actually a different idea/algorithm of interpolation in mind when suggesting this module

@stebogit
Copy link
Collaborator Author

BTW anybody knows if there is a more appropriate default value for weight?

@stebogit
Copy link
Collaborator Author

@DenisCarriere I added the outputType parameter.
I thought to define it as required, so the user has to consciously choose the output; also if we wanted to extend it to hexGrids or triangleGrid we could easily.

@DenisCarriere
Copy link
Member

👍 I like the option of defining the different outputType, we could call it gridType and the avaible options should be exactly the same singular name as the Grid module (point instead of points).

Defining a default param should be fine, we can use square as the default since it's the default for idw and if we replace that module with interpolate then it wouldn't be such a drastic change.

/**
 * @param {string} [gridType='square'] defines the output format based on a Grid Type (options: 'square' | 'point')

@DenisCarriere DenisCarriere added this to the 4.6.0 milestone Jul 10, 2017
@DenisCarriere
Copy link
Member

DenisCarriere commented Jul 10, 2017

Last edits before we merge:

  • Add all other grid types to library.

updated docs, yarn.lock, bench, index.d.ts;
added tests;
@stebogit
Copy link
Collaborator Author

@DenisCarriere good to merge I believe.
Nice and colorful module, particularly handy in combo with isobands and isolines! 😃

@DenisCarriere
Copy link
Member

Love it!! Super excited to release this module in the next minor release!

image

@DenisCarriere DenisCarriere merged commit 926836a into master Jul 11, 2017
@DenisCarriere DenisCarriere deleted the turf-interpolate branch July 11, 2017 17:48
@stebogit stebogit mentioned this pull request Aug 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants