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

Testing turf.buffer accuracy #1246

Open
SteveCline opened this issue Feb 2, 2018 · 10 comments
Open

Testing turf.buffer accuracy #1246

SteveCline opened this issue Feb 2, 2018 · 10 comments

Comments

@SteveCline
Copy link

I am getting a rather large difference comparing turf.buffer to the result of a buffer generated in GIS software. The GIS buffer was projected in MD state plane, then queried to a geoJson feature using SR 4326 via esri's REST api. Using a leaflet measure tool to ground truth, the GIS buffer was accurate. Does anyone have a good explanation?

var point = turf.point([-76.675801, 38.935749]);
var buffered = turf.buffer(point, 10, {units: 'miles'});

turf

@rowanwins
Copy link
Member

Hi @SteveCline

I've just run the operation and opened the result in QGIS, the width measured in QGIS comes in at 20 miles as expected however the height comes in around 15miles.

Under the hood turf/buffer projects input geometries to a transverse mercator projection, I suspect this is the cause of the discrepancy between the results you're getting. It's not documented that it's happening and I wonder if we'd be better off providing an option allowing people to pass in a chosen projection?

Projections are one of those complicated things and Turf generally tries to avoid providing options around them to users, we generally go for a 'just works as expected' philosophy, although buffering is one are in particular where I think we could perhaps provide some more options for educated users.

Hope that helps explain things
Cheers
Rowan

@SteveCline
Copy link
Author

Thanks @rowanwins

I think passing a spatial reference code as an option would be very helpful for the buffer and probably some other methods too. I would argue, if turf's philosophy is to 'just work as expected', using proper spatial reference is vitally important to that expectation of working.

Mid latitude buffers will be off by 25% and running turf.circle will give a more accurate result in these parts of the globe.

If turf has the goal of being the geoprocessing engine of the future, which I hope it does, it can't have inaccuracies this large and be used in serious GIS applications. Thanks again for your help and good work with Turf!

@rowanwins
Copy link
Member

No worries @SteveCline - we'll have a think about the best way we can expose that functionality.

Re your comment: I'm not sure Turf necessarily aims to be the "geoprocessing engine of the future" (although it's a great slogan - someone should adopt that!). One of the challenges is with Turf is that we don't really have the benefits that you can get with more complete geoprocessing engines like JTS which gets to leverage things like geometry classes. We deal with geojson in and geojson out which puts in place a bunch of limitations. For example we try and leverage spatial indexing where it makes sense for particular operations but we can't easily bake it into featurecollections because we don't know if people will tamper with those feature collections etc.

That said I do wonder if we could develop a geojson-like powered library that had things like geometry classes and observers in place, eg if a geometry is changed then the bounding box is nulled. You could keep a geojson-like structure but make it smarter.... but that's just me dreaming and won't happen unless someone invested some $$$ in Turf unfortunately :(

Anyway dreaming aside we still want Turf to be a super-awesome piece of kit that people can pick up and use. It'll probably never compete with things like PostGIS for some operations but hopefully it has that sweet-spot of performant enough operations in the browser without the need for DB's and network calls etc,

@craiggoldstone
Copy link

I've also encountered this problem where buffers are created too small by about 15%. I guess we will just use JSTS directly until there's a solution with Turf. I think it should at least be documented that this occurs because of reprojection!

image

@ruben-grossmann
Copy link

ruben-grossmann commented Apr 20, 2018

I'm having the same Problem.
I created a 30 meters buffer in PostGIS (yellow) and the same buffer in turf (blue).

image

@jo-me
Copy link

jo-me commented May 29, 2018

Hi,
I'm also in the same boat.
As far as I understand from this thread turf buffers in general are very inaccurate and therefore basically unusable.

A couple of questions:

  • Is there a workaround for this? Maybe switching projections, moving everything to 0,0 before calculating or some other trick?
  • Does it matter where (on earth) the polygon is located or is it inaccurate everywhere?
  • Are other geometries / calculations affected as well by the underlying problem?

Thanks

@ZacLiveEarth
Copy link

ZacLiveEarth commented Jun 25, 2018

Taking a look at the buffer code, it appears there is also a bug where Mercator instead of TransverseMercator is incorrectly chosen when the polygon is near the south pole.

See line 100 of turf-buffer/index.js -
var needsTransverseMercator = bbox[1] > 50 && bbox[3] > 50;

I think this should read
var needsTransverseMercator = (bbox[1] > 50 && bbox[3] > 50) || (bbox[1] < -50 && bbox[3] < -50);
(I don't write Javascript and don't use TurfJS - so please double-check that code)

I'm posting this here instead of as a separate issue because it may be exaggerating some of the inaccuracies being seen here, and also because hopefully the actual code that this replaces may fix this bug along the way.

@rowanwins
Copy link
Member

rowanwins commented Jun 26, 2018

Thanks for the comment @ZacLiveEarth , I think you've correctly identified a bug there although I suspect that's only having an impact on a few occassions and we're in need a broader overhaul.

Doing a bit of googling as to how other libraries are tackling this

PostGIS
from here

It first determines the best SRID that fits the bounding box of the geography object (favoring UTM, Lambert Azimuthal Equal Area (LAEA) north/south pole, and falling back on mercator in worst case scenario) and then buffers in that planar spatial ref and retransforms back to WGS84 geography.

ArcMap
Some useful info here

Will try and do some more hunting

@beaero
Copy link

beaero commented Oct 21, 2021

One thing which i tried and helped is calculate buffer, find the inaccuracy and rebuffer with a factor of that inaccuracy. e.g if i try line.offset(line, distance). i calculate the distance between the original line and the new line and then increase the distance by a factor of that inaccuracy and redraw the line. Comes way more accurate. At least a work around even if not preferable. I could provide a working example of this if someone needs it. I was able to reach accuracies of almost 99.9 percent easily.

@chrispahm
Copy link
Contributor

@SteveCline @JamesLMilner
Trying to help clean up some older issues here: Similar to issues #1470, #1484, #1547 this issue has been fixed with Turf >v6.2.0.

Here's a small notebook showcasing Turf's buffer operation on the point and 10 mile buffer radius presented in @SteveCline's original question for both Turf v6.5.0 and v5.1.6. The buffer is compared to a buffer calculated using GeoPandas (link to Jupyter notebook used for the calculation.

https://observablehq.com/@chrispahm/turf-issue-1246
image

Since the difference is arguably small, I guess this issue can be closed as well!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants