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

Adding support geodesic area and perimeter calculations from geographlib-rs #988

Merged
merged 11 commits into from
Mar 6, 2023

Conversation

phayes
Copy link
Contributor

@phayes phayes commented Feb 27, 2023

  • I agree to follow the project's code of conduct.
  • I added an entry to CHANGES.md if knowledge of this change could be valuable to users.

This is a PR for adding a GeodesicArea trait for highly accurate geodesic area and perimeter calculations.

See georust/geographiclib-rs#49

@phayes phayes marked this pull request as draft February 27, 2023 20:49
Co-authored-by: Corey Farwell <coreyf@rwell.org>
@michaelkirk michaelkirk self-requested a review March 1, 2023 03:14
@phayes phayes marked this pull request as ready for review March 2, 2023 16:09
@phayes
Copy link
Contributor Author

phayes commented Mar 2, 2023

This is now ready for merging / review.

An open question is whether we like what I've done with having a bunch of different methods for getting area, perimeter or both. Maybe we want to ignore perimeter and only focus on area? Maybe we always want to get both together since they're computed together?

Copy link
Member

@michaelkirk michaelkirk left a comment

Choose a reason for hiding this comment

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

Thanks for another great PR!

The overall direction I feel good about, but I had some questions/comments.

}
}

fn geodesic_area(poly: &Polygon, sign: bool, reverse: bool, exterior_only: bool) -> (f64, f64) {
Copy link
Member

Choose a reason for hiding this comment

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

reverse and exterior_only seems to always be false. Do you want to get rid of them? Or if you want to keep them, can you comment as to their future purpose?

Copy link
Contributor Author

@phayes phayes Mar 2, 2023

Choose a reason for hiding this comment

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

Originally I was planning on more features, but decided to reign it in a bit. So I guess some open questions:

  1. Do we want to fully support clockwise-wounded geometries? The Documentation (https://docs.rs/geo/latest/geo/#semantics) states "The geospatial types provided here aim to adhere to the OpenGIS Simple feature access standards." This suggests to me that we don't really need to actually support reverse-wound geometries other than on a minimal "best effort" basis. If this is true, I'll remove the "reverse" option here to only fully support counterclockwise-wound geometries as per the Simple Feature spec.

  2. Is it useful to have an option to only get the perimeter of the exterior? Originally I thought this might be useful, but in retrospect just calling geodesic_length() on the exterior ring does the same thing. The only trickly thing here is that sometimes I've seen polygons constructed where the first point of the exterior ring and the last point of the exterior ring are not the same (there's an implicit closure of the ring, instead of an explicit closure by duplicating the origin point). If this case calling geodesic_length() on the exterior-ring would result in an incorrect result, but we could correct for that here knowing that the exterior-rings and interior-rings should always close, even if only implicitly. Do we want to support these non-compliant polygons here, or just leave it to exterior().geodesic_length() ?

geo/src/algorithm/geodesic_area.rs Show resolved Hide resolved
geo/src/algorithm/geodesic_area.rs Outdated Show resolved Hide resolved
@phayes
Copy link
Contributor Author

phayes commented Mar 3, 2023

I've added a bunch more tests to confirm that my "winding correction logic" is good and adjusted the epsilons. I would appreciate another test run on your local to confirm that my epsilons are good (I still think it's really weird that there's a difference in behavior between our machines!).

@michaelkirk
Copy link
Member

I've added a bunch more tests to confirm that my "winding correction logic" is good and adjusted the epsilons.

Without the "winding correction logic" you added, the mis-wound holes would add to rather than subtract from the area, right?

That logic seems like it would be helpful for most people, and the tests give me confidence that you've implemented it correctly.

As devil's advocate, I'm trying to imagine if there's a world where people would intentionally wind their polygons this way, where the existing computation would be meaningful, and now we've inadvertently broken some special use case that these people might have... but I'm having a hard time imagining such a thing.

On balance, I think what you've done makes sense, and is a nice guard rail, so we should merge it.

I would appreciate another test run on your local to confirm that my epsilons are good

Passing now — Thanks!

(I still think it's really weird that there's a difference in behavior between our machines!).

I'm no expert on floating point implementations, but it's my understanding that there are small discrepancies across architectures and compilers. Some operations are encompassed by the IEEE754 spec, and should perform uniformly, but some operations (e.g. trigonometric functions) are not and might diverge.

I don't know if that's what's going on here, but it's common enough that if the divergence is very small, I've chosen to add a small epsilon for testing and spend my time elsewhere.


Overall, this LGTM, but I'll wait a couple days before merging in case anyone else wants to chime in.

(Though I think it needs a cargo fmt before we can merge)

bors try

bors bot added a commit that referenced this pull request Mar 3, 2023
@bors
Copy link
Contributor

bors bot commented Mar 3, 2023

try

Build failed:

@phayes
Copy link
Contributor Author

phayes commented Mar 3, 2023

Without the "winding correction logic" you added, the mis-wound holes would add to rather than subtract from the area, right?

Correct

As devil's advocate, I'm trying to imagine if there's a world where people would intentionally wind their polygons this way, where the existing computation would be meaningful, and now we've inadvertently broken some special use case that these people might have... but I'm having a hard time imagining such a thing.

There is prior art for always considering the interior rings to reduce the area. I've been using QGIS to double-check my numbers in my tests, and QGIS always calculates interior-rings as reducing the magnitude of the area. So what we have here matches QGIS at the very least.

On balance, I think what you've done makes sense, and is a nice guard rail, so we should merge it.

Yay!

I've now run cargo fmt

bors try

@bors
Copy link
Contributor

bors bot commented Mar 3, 2023

🔒 Permission denied

Existing reviewers: click here to make phayes a reviewer

@michaelkirk
Copy link
Member

bors try

bors bot added a commit that referenced this pull request Mar 3, 2023
@bors
Copy link
Contributor

bors bot commented Mar 3, 2023

try

Build succeeded:

Copy link
Member

@frewsxcv frewsxcv left a comment

Choose a reason for hiding this comment

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

lgtm! thank you for adding this 🌻

will leave this open in case michael kirk or someone else has comments

geo/src/algorithm/geodesic_area.rs Outdated Show resolved Hide resolved
@urschrei
Copy link
Member

urschrei commented Mar 5, 2023

I think the area calculation you've got now is the correct approach – I don't think we have to cater to what would be a fundamental divergence from the spec and convention on the part of a user.

phayes and others added 2 commits March 5, 2023 09:52
@michaelkirk
Copy link
Member

bors r+

@bors
Copy link
Contributor

bors bot commented Mar 6, 2023

Build succeeded:

@bors bors bot merged commit bc16e13 into georust:main Mar 6, 2023
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.

4 participants