Permalink
Browse files

Add two test cases, point-on-segment and point-on-vertex.

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
  • Loading branch information...
1 parent 25eea88 commit 7196b9a2e5a3ebc393a1810f6c7d841a00b50844 @mloskot mloskot committed Dec 5, 2014
Showing with 154 additions and 0 deletions.
  1. +64 −0 tests/unit/algorithm/RobustLineIntersectorTest.cpp
  2. +90 −0 tests/unit/capi/GEOSPreparedGeometryTest.cpp
@@ -3,6 +3,7 @@
#include <tut.hpp>
// geos
+#include <geos/io/WKBReader.h>
#include <geos/io/WKTReader.h>
#include <geos/algorithm/LineIntersector.h>
#include <geos/algorithm/CGAlgorithms.h>
@@ -251,5 +252,68 @@ namespace tut
}
+ // Test intersects: point on segment with FLOAT PM
+ // X coordinate of 3rd and 4th vertises of the line are not
+ // float-point exact with X coordinate of the point.
+ // The X values differ after 14th decimal place:
+ // POINT (-23.1094689600055080 50.5195368635957180)
+ // --------------------^^^^^^^------------^^^^^^^^
+ // LINESTRING 3rd and 4th points
+ // -23.1094689600055150 50.5223376452201340,
+ // -23.1094689600055010 50.5169177629559480,
+ // --------------------^^^^^^^------------^^^^^^^^
+ // So, in float-point precision model, the point does DOES NOT intersect the segment.
+ template<>
+ template<>
+ void object::test<14>()
+ {
+ geos::io::WKBReader reader;
+
+ // POINT located between 3rd and 4th vertex of LINESTRING
+ // POINT(-23.1094689600055080 50.5195368635957180)
+ std::string point("01010000009a266328061c37c0e21a172f80424940");
+ // LINESTRING(-23.122057005539 50.5201976774794,-23.1153476966995 50.5133404815199,-23.1094689600055150 50.5223376452201340,-23.1094689600055010 50.5169177629559480,-23.0961967920942 50.5330464848094,-23.0887991006034 50.5258515213185,-23.0852302622362 50.5264582238409)
+ std::string line("0102000000070000009909bf203f1f37c05c1d66d6954249404afe386d871d37c0a7eb1124b54149409c266328061c37c056d8bff5db42494098266328061c37c0034f7b5c2a42494060065c5aa01837c08ac001de3a4449408401b189bb1637c0b04e471a4f43494014ef84a6d11537c0b20dabfb62434940");
+ std::stringstream sPoint(point);
+ GeomPtr gPoint(reader.readHEX(sPoint));
+ std::stringstream sLine(line);
+ GeomPtr gLine(reader.readHEX(sLine));
+ int ret = gLine->intersects(gPoint.get());
+ ensure_equals(ret, 0);
+ }
+
+ // Test intersects: point on segment with FIXED PM
+ // X coordinate of 3rd and 4th vertises of the line are not
+ // float-point exact with X coordinate of the point.
+ // The X values differ after 14th decimal place:
+ // POINT (-23.1094689600055080 50.5195368635957180)
+ // --------------------^^^^^^^------------^^^^^^^^
+ // LINESTRING 3rd and 4th points
+ // -23.1094689600055150 50.5223376452201340,
+ // -23.1094689600055010 50.5169177629559480,
+ // --------------------^^^^^^^------------^^^^^^^^
+ // So, if float-point values are trimmed up to 14 decimal digits, the point DOES intersect the segment.
+
+ template<>
+ template<>
+ void object::test<15>()
+ {
+ geos::geom::PrecisionModel pm(1e+13);
+ geos::geom::GeometryFactory factory(&pm);
+ geos::io::WKBReader reader(factory);
+
+ // POINT located between 3rd and 4th vertex of LINESTRING
+ // POINT(-23.1094689600055080 50.5195368635957180)
+ std::string point("01010000009a266328061c37c0e21a172f80424940");
+ // LINESTRING(-23.122057005539 50.5201976774794,-23.1153476966995 50.5133404815199,-23.1094689600055150 50.5223376452201340,-23.1094689600055010 50.5169177629559480,-23.0961967920942 50.5330464848094,-23.0887991006034 50.5258515213185,-23.0852302622362 50.5264582238409)
+ std::string line("0102000000070000009909bf203f1f37c05c1d66d6954249404afe386d871d37c0a7eb1124b54149409c266328061c37c056d8bff5db42494098266328061c37c0034f7b5c2a42494060065c5aa01837c08ac001de3a4449408401b189bb1637c0b04e471a4f43494014ef84a6d11537c0b20dabfb62434940");
+ std::stringstream sPoint(point);
+ GeomPtr gPoint(reader.readHEX(sPoint));
+ std::stringstream sLine(line);
+ GeomPtr gLine(reader.readHEX(sLine));
+ int ret = gLine->intersects(gPoint.get());
+ ensure_equals(ret, 1);
+ }
+
} // namespace tut
@@ -4,6 +4,7 @@
#include <tut.hpp>
// geos
#include <geos_c.h>
+#include <geos.h>
@strk
strk Apr 15, 2015 Member

this include results in a WARNING when building with GCC, it would be better to only include the required headers (WKBReader, PrecisionModel etc.).

I think you only need to go to the C++ interface for PrecisionModel in this specific case, to trim those hexwkb specified geoms in test 8...

@mloskot
mloskot Apr 16, 2015 Member

Cleared up in f6eda2c

// std
#include <cstdarg>
#include <cstdio>
@@ -170,6 +171,95 @@ namespace tut
}
+ // Test PreparedIntersects: point on segment with FLOAT PM
+ // X coordinate of 3rd and 4th vertises of the line are not
+ // float-point exact with X coordinate of the point.
+ // The X values differ after 14th decimal place:
+ // POINT (-23.1094689600055080 50.5195368635957180)
+ // --------------------^^^^^^^------------^^^^^^^^
+ // LINESTRING 3rd and 4th points
+ // -23.1094689600055150 50.5223376452201340,
+ // -23.1094689600055010 50.5169177629559480,
+ // --------------------^^^^^^^------------^^^^^^^^
+ // So, in float-point precision model, the point does DOES NOT intersect the segment.
+ // See RobustLineIntersectorTest.cpp for similar test cases.
+ template<>
+ template<>
+ void object::test<7>()
+ {
+ geos::io::WKBReader reader;
+
+ // POINT located between 3rd and 4th vertex of LINESTRING
+ // POINT(-23.1094689600055080 50.5195368635957180)
+ std::string point("01010000009a266328061c37c0e21a172f80424940");
+ // LINESTRING(-23.122057005539 50.5201976774794,-23.1153476966995 50.5133404815199,-23.1094689600055150 50.5223376452201340,-23.1094689600055010 50.5169177629559480,-23.0961967920942 50.5330464848094,-23.0887991006034 50.5258515213185,-23.0852302622362 50.5264582238409)
+ std::string line("0102000000070000009909bf203f1f37c05c1d66d6954249404afe386d871d37c0a7eb1124b54149409c266328061c37c056d8bff5db42494098266328061c37c0034f7b5c2a42494060065c5aa01837c08ac001de3a4449408401b189bb1637c0b04e471a4f43494014ef84a6d11537c0b20dabfb62434940");
+ std::stringstream sPoint(point);
+ geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sPoint));
+ std::stringstream sLine(line);
+ geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sLine));
+
+ prepGeom1_ = GEOSPrepare(geom1_);
+ ensure(0 != prepGeom1_);
+ int ret = GEOSPreparedIntersects(prepGeom1_, geom2_);
+ ensure_equals(ret, 0);
+ }
+
+ // Test PreparedIntersects: point on segment with FIXED PM
+ // X coordinate of 3rd and 4th vertises of the line are not
+ // float-point exact with X coordinate of the point.
+ // The X values differ after 14th decimal place:
+ // POINT (-23.1094689600055080 50.5195368635957180)
+ // --------------------^^^^^^^------------^^^^^^^^
+ // LINESTRING 3rd and 4th points
+ // -23.1094689600055150 50.5223376452201340,
+ // -23.1094689600055010 50.5169177629559480,
+ // --------------------^^^^^^^------------^^^^^^^^
+ // So, if float-point values are trimmed up to 14 decimal digits, the point DOES intersect the segment.
+ // See RobustLineIntersectorTest.cpp for similar test cases.
+ template<>
+ template<>
+ void object::test<8>()
+ {
+ geos::geom::PrecisionModel pm(1e+13);
+ geos::geom::GeometryFactory factory(&pm);
+ geos::io::WKBReader reader(factory);
+
+ // POINT located between 3rd and 4th vertex of LINESTRING
+ // POINT(-23.1094689600055080 50.5195368635957180)
+ std::string point("01010000009a266328061c37c0e21a172f80424940");
+ // LINESTRING(-23.122057005539 50.5201976774794,-23.1153476966995 50.5133404815199,-23.1094689600055150 50.5223376452201340,-23.1094689600055010 50.5169177629559480,-23.0961967920942 50.5330464848094,-23.0887991006034 50.5258515213185,-23.0852302622362 50.5264582238409)
+ std::string line("0102000000070000009909bf203f1f37c05c1d66d6954249404afe386d871d37c0a7eb1124b54149409c266328061c37c056d8bff5db42494098266328061c37c0034f7b5c2a42494060065c5aa01837c08ac001de3a4449408401b189bb1637c0b04e471a4f43494014ef84a6d11537c0b20dabfb62434940");
+ std::stringstream sPoint(point);
+ geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sPoint));
+ std::stringstream sLine(line);
+ geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sLine));
+
+ prepGeom1_ = GEOSPrepare(geom1_);
+ ensure(0 != prepGeom1_);
+ int ret = GEOSPreparedIntersects(prepGeom1_, geom2_);
+ ensure_equals(ret, 1);
+ }
+
+ // Test PreparedIntersects: point on vertex (default FLOAT PM)
+ template<>
+ template<>
+ void object::test<9>()
+ {
+ // POINT located on the 3rd vertex of LINESTRING
+ // POINT(-23.1094689600055 50.5223376452201)
+ std::string point("01010000009c266328061c37c056d8bff5db424940");
+ // LINESTRING(-23.122057005539 50.5201976774794,-23.1153476966995 50.5133404815199,-23.1094689600055 50.5223376452201,-23.1094689600055 50.5169177629559,-23.0961967920942 50.5330464848094,-23.0887991006034 50.5258515213185,-23.0852302622362 50.5264582238409)
+ std::string line("0102000000070000009909bf203f1f37c05c1d66d6954249404afe386d871d37c0a7eb1124b54149409c266328061c37c056d8bff5db42494098266328061c37c0034f7b5c2a42494060065c5aa01837c08ac001de3a4449408401b189bb1637c0b04e471a4f43494014ef84a6d11537c0b20dabfb62434940");
+ geom1_ = GEOSGeomFromHEX_buf(reinterpret_cast<const unsigned char*>(line.data()), line.size());
+ geom2_ = GEOSGeomFromHEX_buf(reinterpret_cast<const unsigned char*>(point.data()), point.size());
+ prepGeom1_ = GEOSPrepare(geom1_);
+ ensure(0 != prepGeom1_);
+
+ int ret = GEOSPreparedIntersects(prepGeom1_, geom2_);
+ ensure_equals(ret, 1);
+ }
+
// TODO: add lots of more tests
} // namespace tut

0 comments on commit 7196b9a

Please sign in to comment.