Turfjs / turf

A modular geospatial engine written in JavaScript and TypeScript
https://turfjs.org/
MIT License
9.2k stars 934 forks source link

Linear Interpolation #1034

Open dbauszus-glx opened 6 years ago

dbauszus-glx commented 6 years ago

Is there any turf method which allows for linear interpolation? IDW works great but isn't ideal for working with the sample data.

stebogit commented 6 years ago

@dbauszus-glx have you tried @turf/interpolate?

dbauszus-glx commented 6 years ago

Yes, that's the function which I tested. According to the documentation this fx() is using an IDW algorithm.

I set the weight to 0 but this doesn't give me a linear interpolation. I need a linear interpolation between sample points (black circles). Temperature and rain fall for example are not expected to drop at a distance to the sample point.

image

dbauszus-glx commented 6 years ago

I solved the problem with a workaround, using the turf/tin algorithm to create a tin and then assign the values to a grid using turf/planepoint. This gives me a linear interpolation.

    // create a tin from the points
    let tin = turfTIN(points, 'v');
    // console.log(JSON.stringify(tin));

    // assign IDs to the tin features
    for (let i = 0; i < tin.features.length; i++) {
        tin.features[i].properties.i = i;
    }

    // create a convex hull of the tin features
    let convex = turfConvex(points);
    // console.log(JSON.stringify(convex));

    // create a pointgrid on the extent of the tin convex hull
    let pg = turfPG(convex, 1, 'kilometers', true, false);
    //console.log(JSON.stringify(pg));

    // tag the pointgrid points with the tin id
    let tag = turfTag(pg, tin, 'i', 'tin');
    //console.log(JSON.stringify(tag));

    // use planepoint to assign values to the pointgrid points that fall on tin features
    // for (let i = 0; i < tag.features.length; i++) {
    //    tag.features[i].properties.v = tag.features[i].properties.tin?
    //        turfPlanePoint(tag.features[i], tin.features[tag.features[i].properties.tin]) :
    //        data.distance * 1.5;
    //}
    // above function is for reference only. please use arrow functions if your work in node es6 environment.
    tag.features.map(f => f.properties.v = f.properties.tin ?
            turfPlanePoint(f, tin.features[f.properties.tin]) :
            data.distance * 1.5);
    // console.log(JSON.stringify(tag));

From here I can create iso bands which reflect the results which I expect.

image

stebogit commented 6 years ago

Sorry @dbauszus-glx I don't really know the difference between the two interpolations. Would this be the right function here?

@DenisCarriere wouldn't it be nice adding linear interpolation to Turf? We could have different interpolation modules like @turf/interpolate-idw and @turf/interpolate-linear or add a type='idw'|'linear' parameter, default to 'idw' maybe, to @turf/interpolate. This would also allow an easy addition for https://github.com/Turfjs/turf/issues/41, whenever somebody would implement that.

BTW, I just found out that @turf/tin would actually belong to the group, like @turf/interpolate-tin, no?

dbauszus-glx commented 6 years ago

Bilinear interpolation would be an amazing addition to turf. This would be even better than a linear tin interpolation for my use case. Likewise, having a linear tin interpolation out of the box without the need to construct the tin and filter points through would make this functionality more accessible to users.

DenisCarriere commented 6 years ago

We could have different interpolation modules like @turf/interpolate-idw and @turf/interpolate-linear

Yes we should group these modules into interpolate categories that way it's easier to find all the Interpolation modules, I also agree we should add @turf/tin in the same category.

Same thing we did for clusters-kmeans & clusters-dbscan, it's a lot easier and cleaner to make the test cases if the modules have their own repo.

DenisCarriere commented 6 years ago

Bilinear interpolation would be an amazing addition to turf.

@dbauszus-glx Agreed 👍 Feel free to make a PR to Turf with the proposed module, we can discuss more on a PR and work out the details there.

dbauszus-glx commented 6 years ago

@DenisCarriere I would like to do this after I finish my current project. I will need to learn more about the specifics of the turf structure as a whole. For example, I have never used roll-up since I am using webpack in my projects.

DenisCarriere commented 6 years ago

@dbauszus-glx No worries, take your time. Thanks for taking the time to contribute and feel free to ask any questions if you are unsure about something. Hopefully we can update our CONTRIBUTING guide a bit more with all the latest things to do for new modules, it's currently a bit outdated.

dbauszus-glx commented 6 years ago

I just read through the mapbox-isochrone code. Same problem better solution. Here a CONREC contour algorithm is applied. Are you aware of a CONREC implementation in turf.js?

stebogit commented 6 years ago

@dbauszus-glx the previous version of @turf/isolines used to use conrec.js but for some reason it was not working properly (https://github.com/Turfjs/turf/issues/390). I implemented a new version (together with @turf/isobands) based on MarchingSquareJS.

However, MarchingSquareJS has some issues, and does not support ES6, so I mean to work on the Turf modules as soon as I have some time, probably early next year, to fix their issues likely using some other contouring library.

Of course @dbauszus-glx feel free to send a fixing PR if you want! 👍

smalldemon commented 6 years ago

@DenisCarriere Hello, How to use isolines() to draw the equivalent line of random coordinates The poiontGrid parameter is a fixed point grid

smalldemon commented 6 years ago

@dbauszus-glx

   tag.features.map(f => f.properties.v = f.properties.tin ?
            turfPlanePoint(f, tin.features[f.properties.tin]) :
            data.distance * 1.5);

what the "data.distance * 1.5" meaning?

smalldemon commented 6 years ago

@dbauszus-glx I need your demo very much,help me,thank you

dbauszus-glx commented 6 years ago

@smalldemon data.distance is the maximum value in my dataset. I set the values outside the extent of the tin to 1.5 the maximum. This allows me to ignore these values when I draw the contours.

smalldemon commented 6 years ago

@dbauszus-glx Well, I understand thx

smalldemon commented 6 years ago

@DenisCarriere @stebogit you see, use pointgrid and tin make the work complicated! This makes me have to use the old version of the method turf.isolines(points,'v',10,breaks), But after the new version, it doesn't support. And now I'm not sure about the accuracy of it. So what should I do.

andressr-netmind commented 5 years ago

Any news?