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

Buffer fixes #938

Merged
merged 9 commits into from
Sep 12, 2017
Merged

Buffer fixes #938

merged 9 commits into from
Sep 12, 2017

Conversation

stebogit
Copy link
Collaborator

I was working on solving #900, and I fixed it simply using the new @turf/projection, but then find out that seems to fix also #815 and #916. 😃

Still for some reason the actual size of the buffer is slightly off, i.e. smaller than the expected one.

cc: @sc-keyzo @ArtCodeKarine @stephanbogner

@stebogit stebogit self-assigned this Sep 11, 2017
@DenisCarriere
Copy link
Member

@stebogit Wow 🎉 Really cool! The @turf/projection module is going to be VERY useful! (we all knew that 😉 )

var needsTransverseMercator = bbox[1] > 50 && bbox[3] > 50;

if (needsTransverseMercator) {
var projection = defineProjection(geometry);
Copy link
Member

Choose a reason for hiding this comment

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

@stebogit Did you want to move over this defineProjection to @turf/projection (as define).

/**
 * Define Transverse Mercator projection
 *
 * @private
 * @param {Geometry|Feature<any>} geojson Base projection on center of GeoJSON
 * @returns {GeoProjection} D3 Geo Transverse Mercator Projection
 */
function defineProjection(geojson) {
    var coords = center(geojson).geometry.coordinates.reverse();
    var rotate = coords.map(function (coord) { return -coord; });
    var projection = d3.geoTransverseMercator()
        .center(coords)
        .rotate(rotate)
        .scale(6373000);

    return projection;
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@DenisCarriere wouldn't it be even more useful having a @turf/projection.toTransverse method for the actual conversion? I mean, why would you define the (Transverse in this case) projection but for converting the coordinates?

In that regard, at this point we might need to re-think the structure of the projection module to leave it open to accept maybe other projections in the future, if ever needed, like:

  • @turf/projection.toMercator
  • @turf/projection.fromMercator
  • @turf/projection.toTransverse
  • @turf/projection.fromTransverse
  • ...

knowing the base projection for Turf is WGS84

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.

👍

@stebogit
Copy link
Collaborator Author

Ooops... 😨 I was convinced this branch had been merged already... 😅

@DenisCarriere
Copy link
Member

Lol it can be, I only looked at it real quick, when I have more time I'll dive into it more, unless you feel it's good to merge.

@stebogit
Copy link
Collaborator Author

At this point I guess we could merge since all tests pass and they actually look better (less distortion); we can always reopen any issue if necessary.
May I have the honor? 😃

@DenisCarriere
Copy link
Member

@stebogit merge away! 👍

@stebogit stebogit merged commit 08b9604 into master Sep 12, 2017
@stebogit
Copy link
Collaborator Author

Woo-hoo!! :bowtie:

@ArtCodeKarine
Copy link

Hello @stebogit,
I try to install your new module with "npm install @turf/turf", but it doesn't work. Your module isn't display in my project.
So is it normal that your package is not in the file : turf/packages/turf/package.json ?
Thank's for your answer.

@stebogit
Copy link
Collaborator Author

@ArtCodeKarine what module are you talking about? Do you mean the updated @turf/buffer code?
@DenisCarriere is going to publish a new patch release (I guess v4.7.4) with those changes as soon as possible, so stay tuned! 😜

@DenisCarriere DenisCarriere deleted the buffer-line-fix branch September 18, 2017 06:10
DenisCarriere added a commit that referenced this pull request Sep 18, 2017
@DenisCarriere
Copy link
Member

DenisCarriere commented Sep 18, 2017

@ArtCodeKarine Just published a patch release for @turf/buffer, try out:

$ npm install --save @turf/[email protected]

@ArtCodeKarine
Copy link

@DenisCarriere @stebogit thanks, I will try it :D

@ArtCodeKarine
Copy link

I think i have to wait the new version of turf because my application is running with nodejs and bower. Bower uses the @turf/turf folder and this doesn't contain the patch version of the buffer.

dyakovlev added a commit to dyakovlev/turf that referenced this pull request Oct 12, 2020
The existing buffer code has three problems:
- it uses two different projections depending on the latitude of the
  input geometry. This results in an error discontinuity at 50N.
- it switches projections only for the northern hemisphere.
- it mistakenly reverses the lonlat center, which has the eventual
  result of rotating the projection to a skewed center.

The third problem is one of the causes of `buffer`'s size issues. At
latitudes above 50N, the projection distorts input distances due to not
being rotated to the correct input geometry center. At latitudes below
50N, the Mercator projection does not receive a correction for the input
distance. If using the Mercator projection, the actual distance used
as an input to JSTS BufferOp should be distance / cos((lat * π) / 180). [1]

As recommended in the original[2] exploration that prompted the fix
introduced in Turfjs#938, this patch switches the buffer prep code to
consistently using the Azimuthal Equidistant projection rather than
switching between Mercator and Transverse Mercator. When centered on the
input geometry, this projection should produce less distortion in all
directions for input geometries of reasonable size compared to a
cylindrical one.

I took the opportunity to optimize slightly; buffering now calls
`center` only once, and we don't need to `bbox` the input geom at all.

[1] https://gis.stackexchange.com/a/347573
[2] https://github.com/w8r/moscow-rings#solution
mfedderly added a commit that referenced this pull request Dec 8, 2020
)

The existing buffer code has three problems:
- it uses two different projections depending on the latitude of the
  input geometry. This results in an error discontinuity at 50N.
- it switches projections only for the northern hemisphere.
- it mistakenly reverses the lonlat center, which has the eventual
  result of rotating the projection to a skewed center.

The third problem is one of the causes of `buffer`'s size issues. At
latitudes above 50N, the projection distorts input distances due to not
being rotated to the correct input geometry center. At latitudes below
50N, the Mercator projection does not receive a correction for the input
distance. If using the Mercator projection, the actual distance used
as an input to JSTS BufferOp should be distance / cos((lat * π) / 180). [1]

As recommended in the original[2] exploration that prompted the fix
introduced in #938, this patch switches the buffer prep code to
consistently using the Azimuthal Equidistant projection rather than
switching between Mercator and Transverse Mercator. When centered on the
input geometry, this projection should produce less distortion in all
directions for input geometries of reasonable size compared to a
cylindrical one.

I took the opportunity to optimize slightly; buffering now calls
`center` only once, and we don't need to `bbox` the input geom at all.

[1] https://gis.stackexchange.com/a/347573
[2] https://github.com/w8r/moscow-rings#solution

Co-authored-by: Rowan Winsemius <[email protected]>
Co-authored-by: mfedderly <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants