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

Apply equidistance @turf/buffer to polygons #660

Closed
flightsurvey opened this issue Apr 11, 2017 · 12 comments
Closed

Apply equidistance @turf/buffer to polygons #660

flightsurvey opened this issue Apr 11, 2017 · 12 comments
Assignees
Labels
Milestone

Comments

@flightsurvey
Copy link

Please see attached screen shot of a buffer created around a polygon. It appears that the north and south extents are further away than they should be.
buffer

@DenisCarriere
Copy link
Member

Please provide a GeoJSON of the input & output.

Have you tried measuring the buffer distances using http://geojson.io?

Also there might be some distance distortions the higher/lower you are in latitudes since the buffer distance units are calculated in Degrees and not in metric/imperial units.

An example of two points up north (Resolute Bay).
image

Ref: #283 #88 #656

@flightsurvey
Copy link
Author

flightsurvey commented Apr 11, 2017

Thanks for getting back.

I put the following into geojson.io:

[http://bl.ocks.org/anonymous/raw/a8a2f66eb676b01a40676077d8ebd7fe/]

and it appears that the problem is with the other way around:

Zipped geoJSON: map.zip

Code:

var definedAreaCoordinates = {"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-0.16513824462890625,51.14605198694671],[-0.1667207479476929,51.14550680517377],[-0.16554594039916992,51.14412026449063],[-0.16442477703094482,51.144598154575476],[-0.16513824462890625,51.14605198694671]]]}};

definedAreaBuffer = turf.buffer(definedAreaCoordinates, 0.05, 'kilometers');

@DenisCarriere
Copy link
Member

Note: Instead of zipping, you could simply share your URL as a Gist:

https://gist.github.com/f66c382ee9ee9d8e0894b9e61f2af3d1

@flightsurvey
Copy link
Author

Good tip (took me a while to absorb it).

@DenisCarriere DenisCarriere added this to the 5.0.0 milestone Apr 16, 2017
@DenisCarriere DenisCarriere self-assigned this Apr 16, 2017
@DenisCarriere
Copy link
Member

@flightsurvey To extend my answer, the issue is because the radius param is being converted from degrees to distance (miles/kilometers).

Solution:
Looks like we would need to apply the @turf/buffer operations on coordinates using the Mercator projection (then converted back to degrees WGS84), this would create an equi-distance buffer around the geometry (left, right, top & bottom should all have the same buffer distance).

Issue - Polygon in northern latitude

  • Red: Input Polygon
  • Blue: Buffer with 15 miles radius
  • Top & Bottom buffer distance (~15 miles)
  • Left & Right buffer distance (~4 miles)
    image

@DenisCarriere DenisCarriere changed the title How accurate is buffer? Apply equi-distance @turf/buffer to polygons Apr 16, 2017
@flightsurvey
Copy link
Author

Thanks for taking time to look at it

@DenisCarriere DenisCarriere changed the title Apply equi-distance @turf/buffer to polygons Apply equidistance @turf/buffer to polygons Apr 16, 2017
@w8r
Copy link

w8r commented May 2, 2017

I took this challenge before here https://github.com/w8r/moscow-rings, maybe you'll find it useful.
Basically, I extracted the equidistant projection calculation from d3, and adjusted it to have its center in the middle of the buffered shape. It doesn't completely remove the distortions, but at least makes sense in practical cases.

@DenisCarriere
Copy link
Member

DenisCarriere commented May 2, 2017

👍 Awesome stuff! The visual map looks are pretty darn good!

Useful reference from moscow-rings:

Any reason why you didn't use your polygon-offset library vs. jsts?

I've briefly discussed this in other posts, however i'll go over the ideal buffer workflow:

  • Reproject GeoJSON from degrees to EPSG:3857 (Web Mercator) using BBox/Center of GeoJSON (can be done with d3-geo using projection.center)
  • Apply buffer operations using jsts or polygon-offset (helpers would need a conversation table for units > meters).
  • Unproject GeoJSON (EPGS:3857 to EPSG:4326 "WGS84")

@w8r Sounds about right? Correct me if anything seems off.

@mourner @morganherlocker : By no means we should support reprojections (only internally). This seems like this is the only accurate option for equi-distance buffers. As for performance, I believe the heavy lifting is the buffer operations and not the reprojection.

@w8r
Copy link

w8r commented May 2, 2017

Oh, I forgot how shitty that code is)) Didn't use polygon offset, cause it was a very naive implementation before I stumbled upon martinez algorithm, and there was no proper settings to make the contour smooth, nor did it support holes in polygons.

As for the algorithm outline - why to mercator? The most important point is that you have to do the geometrical calculations in the R2 space where they make sense, so abstract equidistant does the trick. This is what I do there, EPSG:3857 is only used to get the distances in meters and project back onto the leaflet map.

Useful parts are actually here and here

Your note about performance is right, offsetting is much heavier than reprojection

@DenisCarriere
Copy link
Member

👍 Thanks @w8r for the feedback, I'll have a look at it further and i'll CC you whenever I do a PR on Turf.

@DenisCarriere
Copy link
Member

This is fixed in PR #718
Thanks @w8r & @flightsurvey for the feedback

@YanCallier
Copy link

Hi, I experienced the same issue in the 6.5 version :
image

The circle has the same diameter used on :
const test = buffer(poly, 50, { units: 'kilometers' });

Yan

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

No branches or pull requests

4 participants