-
Notifications
You must be signed in to change notification settings - Fork 199
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
Conversation
Co-authored-by: Corey Farwell <coreyf@rwell.org>
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? |
There was a problem hiding this 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) { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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:
-
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.
-
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 callinggeodesic_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 toexterior().geodesic_length()
?
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!). |
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.
Passing now — Thanks!
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 bors try |
tryBuild failed: |
Correct
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.
Yay! I've now run bors try |
🔒 Permission denied Existing reviewers: click here to make phayes a reviewer |
bors try |
tryBuild succeeded: |
There was a problem hiding this 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
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. |
Co-authored-by: Corey Farwell <coreyf@rwell.org>
bors r+ |
Build succeeded: |
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