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
(supposed) improvements to dateline handling #84
Conversation
In recent RandomizedTesting versions, atLeast() will go up to Integer.MAX_VALUE, which is not what I thought it would do.
…n with published algorithm. See locationtech#80.
I really appreciate what you've done here! I think it's totally fine that you moved the code to a utility class. I was already thinking it deserved a separate class since there is so much logic to it, plus it's possibly re-usable outside Spatial4j. I did a quick review right now and the code appears very good but I'll want to do a more detailed comparison later. Can you tell me how you are using this, and if there was a particular geometry that failed? It would be good to add test failures. This dateline wrapping code is not tested as much as I'd like. |
I've just been playing with this, along with natural earth countries. My main goals were to handle multi-geometries and arbitrary bounds. The operations appear to (now) work with all of the countries except Antarctica -- I'm still not quite sure what to do about Antarctica. The best automation I can think of is to not process rings in which By the way, a few of the tests I've added cover new functionality (i.e. they'd previously fail): |
As a kind-of proof of concept, I've added logic to undo some detected failures (i.e. for Antarctica). A relatively inexpensive By the way, I've managed to clobber some of your formatting :( On the other hand, I've added some tests. I'm not sure which direction, if any, you'd like to go with this -- some of these changes definitely affect the readability of the code, and so I'm not sure whether they'd be worth it in the end. Though perhaps most importantly, there's still an outstanding bug in the original repo for direct instances of |
After working with you more on this, the "direction" I'd like to go with this is get it back into Spatial4j as a separate class, as you've done. Regarding Antarctica, it occurred to me that the dateline cross tracking that is currently done would result in an one extra cross that isn't balanced by a cross from the other direction. I haven't yet worked out how to leverage that information to produce an appropriate clipped polygon. This scheme would unlikely work for a LinearRing that encloses both poles, but I'm quite willing to dismiss that as a limitation. |
Regarding handling direct instances of GeometryCollection, that class doesn't handle some of the relation operations -- I forget which. It's critical for how Spatial4j is typically used. So in Spatial4j I skirted that once ShapeCollection came into existence, which is a substitute for a multi-anything. Spatial4j has it's "Shape" abstraction whereas JTS has its "Geometry". FYI Spatial4j has it's own shape abstraction distinct from JTS for two reasons:
|
I looked at this some more and pushed some minor changes to a new sttawm-dateline branch. I'm not really convinced that this ShiftHistory thing is the right solution to a pole wrapping (aka spherical ring) LinearRing. What I envision is an algorithm that works something like this:
|
I was thinking a little more about my proposed algorithm after a good night's rest. By the way, the extreme latitude tracking's purpose is to ensure you can pick a point that can be modified to take a turn to go directly to the pole, without in doing so intersect the LinearRing, which could theoretically change direction at times -- a protruding peninsula poking in an east-west direction (vs north-south). That's why the algorithm picks this particular point versus an arbitrary one. I think there needs to be more to the algorithm. Have this extreme coordinate, the point where we (eventually) take the detour, have it be the new start of the new rewritten coordinate sequence. Note that CoordinateSequence.java is not expandable so we need to create a new one. So rotate all the points so that the sequence "starts" (and ultimately ends) here. Don't add the duplicated former start/end coordinate. Before adding the final coordinate to join end to beginning, do the coordinate insertions as previously described at the end, and go the direction needed to complete shiftXPage to 0. In the end you have something that has been unwrapped but needs to be sliced up an union'ed -- an actual union since we want to merge the vertical seam we create between the lowest coordinate and the pole. Also, the coordinates that are between the extreme one where we take the detour to the pole, up until the next dateline cross, need to be paged to the other side of the unwrapping. This is confusing to write about; maybe I'll code it up if you don't beat me to it but I'm quite busy these days. |
Note that much of this code is copied from
https://github.com/spatial4j/spatial4j/blob/185132fae6897f57faacdac91c0a98a92e380bfc/src/main/java/com/spatial4j/core/shape/jts/JtsGeometry.java.
Note that I have (somewhat arbitrarily and regrettably) removed the Date-Line operations from JtsGeometry.
A few modifications have been made:
TODO
-- Negative pages are handled bypageGeom()
(AKAcutUnwrappedGeomInto360
), which allows for the removal of redundant shifting.work with generic projections).
collect()
. )Perhaps I've missed something here and the use of union is actually crucial in some cases)unwrapDateline()
tohandle coordinates outside of the bounds.
unwrapDateline
that invokes
Geometry.geometryChanged()
for instances ofGeometryCollection
, which gave rise to another bug in thatGeometryCollection.intersects()
is an illegal operation, and so...Otherwise, some assertions have been removed (sorry), and the style is probably not quite on.
Let me know if you'd like to see some of these changes in with the actual code (as of now, this class is entirely independent, for the purpose of demonstration).