-
Notifications
You must be signed in to change notification settings - Fork 361
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
Port DoubleDouble and CGAlgorithmsDD support #40
Conversation
Configure ttmath with CMake. ttmath is header-only library, but for Visual C++ 64-bit compiler requires compilation of ttmathuint_x86_64_msvc.asm file (Microsoft doesn't provide the inline assembler in its 64bit compiler). ttmath will be used as Java/JTS DoubleDouble analog of quadruple precision float-point.
…ouble/doubledouble.html NOTE: doubledouble is GPL Apply number of changes and fixes to doubledouble 2.2: 1. Rename .cc file extension to .cpp Add drand48() and srand48(long) for non-POSIX platforms from https://gist.github.com/mortennobel/8665258, based on Freebsd http://fxr.watson.org/fxr/ident?v=FREEBSD-LIBC;im=bigexcerpts;i=_dorand48 2. Correct names of C++ std library headers. 3. Add missing std:: namespace qualifier. 4. Visual C++ does not provide nan.h header.
Two methods have been added orientationIndex and orientationIndexFilter. The implementation uses either ttmath or doubledouble libraries as the JTS DoubleDouble implementation analog. In CGAlgorithmsDD.cpp, two defines provided to control which one is used: GEOS_ENABLE_DD_TMNATH and GEOS_ENABLE_DD_DOUBLEDOUBLE. (Uncomment one or the other and rebuild GEOS.) Change CGalgorithms::orientationIndex to call CGAlgorithmsDD (Note, previous calculations have been kept for comparison and testing purposes, see TODO comments.)
The test case comes from comment in JTS r626 file jts/java/src/com/vividsolutions/jts/algorithm/RobustDeterminant.java (see http://sourceforge.net/p/jts-topo-suite/code/626/) IMPORTANT: Both, JTS as well as GEOS with CGAlgorithmsDD support (through either ttmath or doubledouble), pass this orientationIndex test case. See test<3> in computeOrientationTest.cpp.
Both tests have been added in two forms: 1) C++ version based on geometries in binary (WKB) format. 2) XML version based on geometry in textual (WKT) format. IMPORTANT: Both, JTS 1.14 and GEOS with DD support (either through ttmath, or doubledouble), fail on the point on segment test case, but pass on the point on vertex test case. The quadruple precision float-point support (DD) does not help in the point on segment test case, so both, JTS and GEOS, seem to have robustness issues algorithmically.
It's hard to see what the precise issue is. I assume there is some problem with the testPointOnSegment and/or the testPointOnVertex cases? First of all, the tests use LineStrings with many points - is it possible to reduce the cases to a point against a single segment? |
@dr-jts I meant to write to you directly with clearer explanation. First thing I'd like to confirm is how to interpret the point on segment test case results I've got:
So, the JTS test performs the same operations on the same geometries (different though at very far right precision places, after 13th digit), but depending on input format, WKT or WKB, the results are very different. Martin, thanks for getting in touch about this. |
In the XML test the 3rd segment of the LineString is vertical (identical X ordinates). The test point has the same Y ordinate, so it obviously lies on the segment, as the test reports. It looks to me like the problem is that in the WKB geometry the 3rd segment is NOT vertical. The X ordinates are slightly different: LINESTRING (-23.122057005538952 50.520197677479445, Obviously the point POINT(-23.1094689600055 50.5195368635957) can't lie on that segment, as the test reports. So the question is: where did the WKB come from, and why do you think it exactly represents the WKT in the comment? |
That is indeed what I tried to point out in my previous comment.
Use of the textual representation does not preserve the complete bits patters and doesn't help to make the tests predictable either, does it? I'd argue that the coordinates in WKT are equally precise as the ones in WKB, so the 3 points are equally collinear in both. The differences you point out seem significant(ish), but I was surprised the algorithm doesn't trim at 15th and later decimal place really. It seems, that GEOS with DoubleDouble detects the point/segment above intersect is by a flux. |
There's quite a few issues being raised here, so I'm going to try and dissect them. First of all, the discussion of whether the point-on-segment algorithm is correct is not the issue here, as far as I can see. In the JTS WKT test, the test reports correctly that the point lies exactly on a vertical segment with the same Y ordinates (in FP representation). In general, JTS algorithms work with FP representations of numbers. These are assumed to be stable during copying, so there's no need to round the numbers internally, because they produce consistent results. So the real issue is the question of how stable the conversion from WKT and WKB to FP is. In JTS at least I believe both the WKT parser and the WKB parsers are stable, in the sense that identical text numbers produce identical FP bit patterns. Perhaps this isn't the case in GEOS (at least on some machines) ? If you are faced with parsers that aren't stable, or if you would like input ordinates to be rounded to a lower precision, then you need to implement this by processing the geometries read from parsers. JTS provides the GeometryPrecisionReducer class to do this. Or, you can set the PrecisionModel on the parsers. |
To put this issue another way, in the WKB for the LineString in the testPointOnSegment method has the 3rd and 4th X ordinate values are slightly different in the 15th least significant hex digit: 3: 9c266328061c37c0 56d8bff5db424940 So the line segment is not vertical, and thus the point with WKB: 9c266328061c37c0 56d8bff5db424940 obviously does not lie exactly on the segment. So no issue there - everything is working as it is supposed to. So not sure what the actual issue is, if there is one? |
On 2 December 2014 at 19:39, Martin Davis notifications@github.com wrote:
That is the difference I was pointing at as well and explained that I'd |
On 2 December 2014 at 18:31, Martin Davis notifications@github.com wrote:
OK, good.
Yes, this is an important aspect of the issue as well.
Sounds like a viable alternative. I will give it a try. Martin, thank you for your feedback, much appreciated. Regardless all the precision issues we've discussed here, this patch with |
Does the DD code help fixing any case that would fail otherwise ? |
I haven't checked the code, why were external libraries needed ? Doesn't JTS implement the "doubledouble" concept internally ? How can we ensure JTS and GEOS implementations are the same ? Does JTS have unit tests for the DoubleDouble class ? About the double dependency, is that a compile-time option to use one or the other ? |
On 3 December 2014 at 17:31, Sandro Santilli notifications@github.com
AFAIU, JTS DoubleDouble is port of C++ doubledouble I linked above. About the double dependency, is that a compile-time option to use one or
Perhaps there are other libraries that could be tried out and even simpler |
I'm happy to see this in trunk if you're up to take care of the automake part. |
@dr-jts: would it make sense to re-test existing known robustness cases filed on trac with the new DD code ? |
On 3 December 2014 at 17:50, Sandro Santilli notifications@github.com
|
Well, more testing is always good. That said, I'm pretty sure that DD doesn't help all that much with large-scale robustness (e.g.robustness due to issues in overlaying polygons). That's because overlay robustness failures are often due to the limited precision of computed points, which the DD tests don't help with. The motivation in introducing DD is to finally eliminate robustness issues from core low-level predicates. This is obviously necessary to attain robustness in higher-order algorithms - but unfortunately it's not sufficient for many algorithms (such as overlay). |
This is actually a very good summary and useful documentation from users' point. Apart from testing and curiosity drive, my main motivation to for trying out the DD support was: it's in JTS, it should be in GEOS, for completeness of the port. |
Curious detail of the tests is that points of interest have nearly exact X of tested points, the values differ after 14th decimal place. The tests provided test geometries for intersection with and without coordinates trimming after the 14th place (as per Martin Davis suggestion). It has been extensively discussed in Ticket #591 and #40 with Martin Davis' input. git-svn-id: http://svn.osgeo.org/geos/trunk@4038 5242fede-7e19-0410-aef8-94bd7d2200fb
The (in)famous point-on-segment and point-on-vertext test cases have been corrected according to @dr-jts suggestions and added to the GEOS tests suite, see http://trac.osgeo.org/geos/changeset/4038 |
See also #42 as it contains a testcase that might be fixed by this work |
This is a prototype of DoubleDouble support for GEOS, as an analog to JTS DoubleDouble.
The PR includes:
CGAlgorithmsDD
classorientationIndex
method for orientation vs inverse (see comment inRobustDeterminant.java/RobustDeterminant.orienationIndex; JTS r931 added this test in jts/algorithm/CGAlgorithmsTest.java)
.
This PR is directly related to the problems discussed in this GEOS ticket http://trac.osgeo.org/geos/ticket/591
Next, I'm going to contact @dr-jts if he would be willing to comment on the JTS results obtained for the test on segment case.