diff --git a/benchmarks/geom/CMakeLists.txt b/benchmarks/geom/CMakeLists.txt index 63a25ed05a..2d68291f77 100644 --- a/benchmarks/geom/CMakeLists.txt +++ b/benchmarks/geom/CMakeLists.txt @@ -32,8 +32,8 @@ IF(benchmark_FOUND) benchmark::benchmark geos_cxx_flags) endif() -add_executable(perf_prepared_polygon_intersects - PreparedPolygonIntersectsPerfTest.cpp) -target_include_directories(perf_prepared_polygon_intersects PUBLIC +add_executable(perf_topo_predicate + TopologyPredicatePerfTest.cpp) +target_include_directories(perf_topo_predicate PUBLIC $) -target_link_libraries(perf_prepared_polygon_intersects PRIVATE geos) +target_link_libraries(perf_topo_predicate PRIVATE geos) diff --git a/benchmarks/geom/PreparedPolygonIntersectsPerfTest.cpp b/benchmarks/geom/TopologyPredicatePerfTest.cpp similarity index 69% rename from benchmarks/geom/PreparedPolygonIntersectsPerfTest.cpp rename to benchmarks/geom/TopologyPredicatePerfTest.cpp index 4af6637691..05c9ae6947 100644 --- a/benchmarks/geom/PreparedPolygonIntersectsPerfTest.cpp +++ b/benchmarks/geom/TopologyPredicatePerfTest.cpp @@ -1,7 +1,7 @@ /****************************************************** - * Performance tests for spatial predicates + * Performance tests for topological predicates * - * Usage: perf_prepared_polygon_intersects [ intersects | contains ] + * Usage: perf_topo_predicate [ intersects | contains ] ******************************************************/ #include @@ -25,7 +25,9 @@ std::size_t NUM_LINES_PTS = 100; #define INTERSECTS 0 #define CONTAINS 1 #define COVERS 2 +#define TOUCHES 3 +std::string predicateName{"intersects"}; int predicateOp = INTERSECTS; int testRelateOpIntersects(const Geometry& g, const std::vector>& geoms) { @@ -55,6 +57,15 @@ int testRelateOpCovers(const Geometry& g, const std::vector>& geoms) { + int count = 0; + for (const auto& geom : geoms) { + auto im = g.relate(geom.get()); + count += im->isTouches(g.getDimension(), geom.get()->getDimension()); + } + return count; +} + int testGeometryIntersects(const Geometry& g, const std::vector>& geoms) { int count = 0; for (const auto& geom : geoms) { @@ -79,6 +90,14 @@ int testGeometryCovers(const Geometry& g, const std::vector>& geoms) { + int count = 0; + for (const auto& geom : geoms) { + count += g.touches(geom.get()); + } + return count; +} + int testPrepGeomIntersects(const Geometry& g, const std::vector>& geoms) { int count = 0; auto prep = prep::PreparedGeometryFactory::prepare(&g); @@ -133,10 +152,19 @@ int testRelateNGPreparedCovers(const Geometry& g, const std::vector>& geoms) { + int count = 0; + auto prep = geos::operation::relateng::RelateNG::prepare(&g); + for (const auto& line : geoms) { + count += prep->evaluate(line.get(), *geos::operation::relateng::RelatePredicate::touches()); + } + return count; +} + template double test(const Geometry& g, const std::vector>& geoms, const std::string& method, F&& fun, double baseTime) { - geos::util::Profile sw("PreparedPolygonIntersects"); + geos::util::Profile sw("TopologuyPredicatePerf"); sw.start(); int count = 0; @@ -152,9 +180,10 @@ double test(const Geometry& g, const std::vector>& geo << MAX_ITER * geoms.size() << "," << count << "," << geoms[0]->getGeometryType() << "," << geoms[0]->getNumPoints() << "," - << method << "," - << tot << "," - << timesFaster + << method << " - " << predicateName << "," + << tot << ","; + std::cout << std::fixed << std::setprecision(1); + std::cout << timesFaster << std::endl; return tot; } @@ -177,22 +206,28 @@ void test(int dim, std::size_t npts) { double baseTime; switch (predicateOp) { case INTERSECTS: - baseTime = test(*target, geoms, "RelateOp intersects", testRelateOpIntersects, 0); - test(*target, geoms, "Geometry::intersects", testGeometryIntersects, baseTime); + baseTime = test(*target, geoms, "RelateOp", testRelateOpIntersects, 0); + test(*target, geoms, "Geometry", testGeometryIntersects, baseTime); test(*target, geoms, "PreparedGeom", testPrepGeomIntersects, baseTime); test(*target, geoms, "RelateNGPrepared", testRelateNGPreparedIntersects, baseTime); break; case CONTAINS: - baseTime = test(*target, geoms, "RelateOp contains", testRelateOpIntersects, 0); - test(*target, geoms, "Geometry::contains", testGeometryIntersects, baseTime); - test(*target, geoms, "PreparedGeom contains", testPrepGeomContains, baseTime); - test(*target, geoms, "RelateNGPrepared contains", testRelateNGPreparedContains, baseTime); + baseTime = test(*target, geoms, "RelateOp", testRelateOpIntersects, 0); + test(*target, geoms, "Geometry", testGeometryIntersects, baseTime); + test(*target, geoms, "PreparedGeom", testPrepGeomContains, baseTime); + test(*target, geoms, "RelateNGPrepared", testRelateNGPreparedContains, baseTime); break; case COVERS: - baseTime = test(*target, geoms, "RelateOp covers", testRelateOpCovers, 0); - test(*target, geoms, "Geometry::covers", testGeometryCovers, baseTime); - test(*target, geoms, "PreparedGeom covers", testPrepGeomCovers, baseTime); - test(*target, geoms, "RelateNGPrepared covers", testRelateNGPreparedCovers, baseTime); + baseTime = test(*target, geoms, "RelateOp", testRelateOpCovers, 0); + test(*target, geoms, "Geometry", testGeometryCovers, baseTime); + test(*target, geoms, "PreparedGeom", testPrepGeomCovers, baseTime); + test(*target, geoms, "RelateNGPrepared", testRelateNGPreparedCovers, baseTime); + break; + case TOUCHES: + baseTime = test(*target, geoms, "RelateOp", testRelateOpTouches, 0); + test(*target, geoms, "Geometry", testGeometryTouches, baseTime); + test(*target, geoms, "RelateNGPrepared", testRelateNGPreparedTouches, baseTime); + break; } } @@ -209,15 +244,19 @@ void testAll(int dim) } int main(int argc, char** argv) { - predicateOp = INTERSECTS; + predicateName = "intersects"; if (argc >= 2) { - std::string op{argv[1]}; - if (op == "contains") { - predicateOp = CONTAINS; - } - else if (op == "covers") { - predicateOp = COVERS; - } + predicateName = argv[1]; + } + predicateOp = INTERSECTS; + if (predicateName == "contains") { + predicateOp = CONTAINS; + } + else if (predicateName == "covers") { + predicateOp = COVERS; + } + else if (predicateName == "touches") { + predicateOp = TOUCHES; } std::cout << "target_points,num_tests,num_hits,test_type,pts_in_test,method,time,factor" << std::endl; diff --git a/tests/unit/operation/relateng/RelateNGRobustnessTest.cpp b/tests/unit/operation/relateng/RelateNGRobustnessTest.cpp index 879329073d..6761655f47 100644 --- a/tests/unit/operation/relateng/RelateNGRobustnessTest.cpp +++ b/tests/unit/operation/relateng/RelateNGRobustnessTest.cpp @@ -266,6 +266,17 @@ void object::test<19> () checkIntersectsDisjoint(a, b, true); } - +//https://gis.stackexchange.com/questions/484691/topologyexception-side-location-conflict-while-intersects-on-valid-polygons +//testGISSE_484691 +template<> +template<> +void object::test<20> () +{ + std::string a = "POLYGON ((1.839012980156925 43.169860517728324, 1.838983490127865 43.169860200336274, 1.838898525601717 43.169868281549725, 1.838918565176068 43.1699719478626, 1.838920733577112 43.16998636433192, 1.838978629555589 43.16997979090823, 1.838982586839382 43.169966339940714, 1.838974943184281 43.169918580432174, 1.839020497362873 43.169914572864634, 1.839012980156925 43.169860517728324))"; + std::string b = "POLYGON ((1.8391355300979277 43.16987802887805, 1.83913336164737 43.16986361241434, 1.8390129801569248 43.169860517728324, 1.8390790978572837 43.16987292371998, 1.8390909520103162 43.16995581178317, 1.8391377530291442 43.16995091801345, 1.8391293863398452 43.16987796276235, 1.8391355300979277 43.16987802887805))"; + checkRelate(a, b, "2F2101212"); + checkIntersectsDisjoint(a, b, true); +} + } // namespace tut