[geos-commits] [SCM] GEOS branch main updated. a96e6703d8beba0344a9c9cd90692c13aca8b3a7

git at osgeo.org git at osgeo.org
Thu Aug 22 14:48:35 PDT 2024


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GEOS".

The branch, main has been updated
       via  a96e6703d8beba0344a9c9cd90692c13aca8b3a7 (commit)
       via  78895f0e7f619339f6859197e561f67e64580898 (commit)
      from  5ab1b4bba604f770ae1b2acec502a74169227c7f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a96e6703d8beba0344a9c9cd90692c13aca8b3a7
Merge: 78895f0e7 5ab1b4bba
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Thu Aug 22 14:48:05 2024 -0700

    Merge branch 'main' of github.com:libgeos/geos


commit 78895f0e7f619339f6859197e561f67e64580898
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Thu Aug 22 14:47:50 2024 -0700

    Port JTS-1069, fixes GH-1148, RelateNG Equals regression;

diff --git a/include/geos/operation/relateng/RelateGeometry.h b/include/geos/operation/relateng/RelateGeometry.h
index fa3fd812f..53adf01b1 100644
--- a/include/geos/operation/relateng/RelateGeometry.h
+++ b/include/geos/operation/relateng/RelateGeometry.h
@@ -185,7 +185,7 @@ public:
 
     bool isNodeInArea(const CoordinateXY* nodePt, const Geometry* parentPolygonal);
 
-    Location locateLineEnd(const CoordinateXY* p) ;
+    int locateLineEndWithDim(const CoordinateXY* p);
 
     /**
      * Locates a vertex of a polygon.
diff --git a/include/geos/operation/relateng/RelateNG.h b/include/geos/operation/relateng/RelateNG.h
index 524c75085..b55f2ddfc 100644
--- a/include/geos/operation/relateng/RelateNG.h
+++ b/include/geos/operation/relateng/RelateNG.h
@@ -124,6 +124,19 @@ private:
 
     bool computeLineEnds(RelateGeometry& geom, bool isA, RelateGeometry& geomTarget, TopologyComputer& topoComputer);
 
+
+    /**
+     * Compute the topology of a line endpoint.
+     * Also reports if the line end is in the exterior of the target geometry,
+     * to optimize testing multiple exterior endpoints.
+     *
+     * @param geom
+     * @param isA
+     * @param pt
+     * @param geomTarget
+     * @param topoComputer
+     * @return true if the line endpoint is in the exterior of the target
+     */
     bool computeLineEnd(RelateGeometry& geom, bool isA, const CoordinateXY* pt, RelateGeometry& geomTarget, TopologyComputer& topoComputer);
 
     bool computeAreaVertex(RelateGeometry& geom, bool isA, RelateGeometry& geomTarget, TopologyComputer& topoComputer);
diff --git a/include/geos/operation/relateng/RelatePointLocator.h b/include/geos/operation/relateng/RelatePointLocator.h
index aab269c5a..3ac03da64 100644
--- a/include/geos/operation/relateng/RelatePointLocator.h
+++ b/include/geos/operation/relateng/RelatePointLocator.h
@@ -131,11 +131,11 @@ public:
 
     Location locate(const CoordinateXY* p);
 
-    Location locateLineEnd(const CoordinateXY* p) const;
+    int locateLineEndWithDim(const CoordinateXY* p);
 
     /*
     * Locates a point which is known to be a node of the geometry
-    * (i.e. a point or on an edge).
+    * (i.e. a vertex or on an edge).
     *
     * @param p the node point to locate
     * @param parentPolygonal the polygon the point is a node of
diff --git a/include/geos/operation/relateng/TopologyComputer.h b/include/geos/operation/relateng/TopologyComputer.h
index 92f382c0c..4b52598b3 100644
--- a/include/geos/operation/relateng/TopologyComputer.h
+++ b/include/geos/operation/relateng/TopologyComputer.h
@@ -106,8 +106,6 @@ private:
 
     void addNodeSections(NodeSection* ns0, NodeSection* ns1);
 
-    void addLineEndOnPoint(bool isLineA, Location locLineEnd, Location locPoint, const CoordinateXY* pt);
-
     void addLineEndOnLine(bool isLineA, Location locLineEnd, Location locLine, const CoordinateXY* pt);
 
     void addLineEndOnArea(bool isLineA, Location locLineEnd, Location locArea, const CoordinateXY* pt);
@@ -186,6 +184,18 @@ public:
 
     void addPointOnGeometry(bool isA, Location locTarget, int dimTarget, const CoordinateXY* pt);
 
+    /**
+     * Add topology for a line end.
+     * The line end point must be "significant";
+     * i.e. not contained in an area if the source is a mixed-dimension GC.
+     *
+     * @param isLineA the input containing the line end
+     * @param locLineEnd the location of the line end (Interior or Boundary)
+     * @param locTarget the location on the target geometry
+     * @param dimTarget the dimension of the interacting target geometry element,
+     *    (if any), or the dimension of the target
+     * @param pt the line end coordinate
+     */
     void addLineEndOnGeometry(bool isLineA, Location locLineEnd, Location locTarget, int dimTarget, const CoordinateXY* pt);
 
     /**
diff --git a/src/operation/relateng/RelateGeometry.cpp b/src/operation/relateng/RelateGeometry.cpp
index d7d1b0116..668968eff 100644
--- a/src/operation/relateng/RelateGeometry.cpp
+++ b/src/operation/relateng/RelateGeometry.cpp
@@ -197,10 +197,10 @@ RelateGeometry::isNodeInArea(const CoordinateXY* nodePt, const Geometry* parentP
 
 
 /* public */
-Location
-RelateGeometry::locateLineEnd(const CoordinateXY* p)
+int
+RelateGeometry::locateLineEndWithDim(const CoordinateXY* p)
 {
-    return getLocator()->locateLineEnd(p);
+    return getLocator()->locateLineEndWithDim(p);
 }
 
 
diff --git a/src/operation/relateng/RelateNG.cpp b/src/operation/relateng/RelateNG.cpp
index 283f6ff19..9338123ff 100644
--- a/src/operation/relateng/RelateNG.cpp
+++ b/src/operation/relateng/RelateNG.cpp
@@ -560,7 +560,12 @@ bool
 RelateNG::computeLineEnd(RelateGeometry& geom, bool isA, const CoordinateXY* pt,
       RelateGeometry& geomTarget, TopologyComputer& topoComputer)
 {
-    Location locLineEnd = geom.locateLineEnd(pt);
+    int locDimLineEnd = geom.locateLineEndWithDim(pt);
+    int dimLineEnd = DimensionLocation::dimension(locDimLineEnd, topoComputer.getDimension(isA));
+    //-- skip line ends which are in a GC area
+    if (dimLineEnd != Dimension::L)
+        return false;
+    Location locLineEnd = DimensionLocation::location(locDimLineEnd);
     int locDimTarget = geomTarget.locateWithDim(pt);
     Location locTarget = DimensionLocation::location(locDimTarget);
     int dimTarget = DimensionLocation::dimension(locDimTarget, topoComputer.getDimension(! isA));
@@ -568,7 +573,6 @@ RelateNG::computeLineEnd(RelateGeometry& geom, bool isA, const CoordinateXY* pt,
     return locTarget == Location::EXTERIOR;
 }
 
-
 /* private */
 bool
 RelateNG::computeAreaVertex(RelateGeometry& geom, bool isA, RelateGeometry& geomTarget, TopologyComputer& topoComputer)
diff --git a/src/operation/relateng/RelatePointLocator.cpp b/src/operation/relateng/RelatePointLocator.cpp
index cca69d8ec..f727bc089 100644
--- a/src/operation/relateng/RelatePointLocator.cpp
+++ b/src/operation/relateng/RelatePointLocator.cpp
@@ -132,10 +132,17 @@ RelatePointLocator::locate(const CoordinateXY* p)
 
 
 /* public */
-Location
-RelatePointLocator::locateLineEnd(const CoordinateXY* p) const
+int
+RelatePointLocator::locateLineEndWithDim(const CoordinateXY* p)
 {
-    return lineBoundary->isBoundary(p) ? Location::BOUNDARY : Location::INTERIOR;
+    if (!polygons.empty()) {
+        Location locPoly = locateOnPolygons(p, false, nullptr);
+        if (locPoly != Location::EXTERIOR)
+            return DimensionLocation::locationArea(locPoly);
+    }
+    return lineBoundary->isBoundary(p)
+        ? DimensionLocation::LINE_BOUNDARY
+        : DimensionLocation::LINE_INTERIOR;
 }
 
 
diff --git a/src/operation/relateng/TopologyComputer.cpp b/src/operation/relateng/TopologyComputer.cpp
index bcfdcbc62..1e1c64683 100644
--- a/src/operation/relateng/TopologyComputer.cpp
+++ b/src/operation/relateng/TopologyComputer.cpp
@@ -335,9 +335,13 @@ void
 TopologyComputer::addLineEndOnGeometry(bool isLineA, Location locLineEnd, Location locTarget, int dimTarget, const CoordinateXY* pt)
 {
     (void)pt;
+
+    //-- record topology at line end point
+    updateDim(isLineA, locLineEnd, locTarget, Dimension::P);
+
+    //-- Line and Area targets may have additional topology
     switch (dimTarget) {
     case Dimension::P:
-        addLineEndOnPoint(isLineA, locLineEnd, locTarget, pt);
         return;
     case Dimension::L:
         addLineEndOnLine(isLineA, locLineEnd, locTarget, pt);
@@ -349,43 +353,41 @@ TopologyComputer::addLineEndOnGeometry(bool isLineA, Location locLineEnd, Locati
     throw IllegalStateException("Unknown target dimension: " + std::to_string(dimTarget));
 }
 
-/* private */
-void
-TopologyComputer::addLineEndOnPoint(bool isLineA, Location locLineEnd, Location locPoint, const CoordinateXY* pt)
-{
-    (void)pt;
-    updateDim(isLineA, locLineEnd, locPoint, Dimension::P);
-}
 
 /* private */
 void
 TopologyComputer::addLineEndOnLine(bool isLineA, Location locLineEnd, Location locLine, const CoordinateXY* pt)
 {
     (void)pt;
-    updateDim(isLineA, locLineEnd, locLine, Dimension::P);
+    (void)locLineEnd;
     /**
-     * When a line end is in the exterior, some length of the line interior
-     * must also be in the exterior.
+     * When a line end is in the EXTERIOR of a Line,
+     * some length of the source Line INTERIOR
+     * is also in the target Line EXTERIOR.
      * This works for zero-length lines as well.
      */
-
     if (locLine == Location::EXTERIOR) {
         updateDim(isLineA, Location::INTERIOR, Location::EXTERIOR, Dimension::L);
     }
 }
 
+
 /* private */
 void
 TopologyComputer::addLineEndOnArea(bool isLineA, Location locLineEnd, Location locArea, const CoordinateXY* pt)
 {
     (void)pt;
-    if (locArea == Location::BOUNDARY) {
-        updateDim(isLineA, locLineEnd, locArea, Dimension::P);
-    }
-    else {
+    (void)locLineEnd;
+    if (locArea != Location::BOUNDARY) {
+        /**
+         * When a line end is in an Area INTERIOR or EXTERIOR
+         * some length of the source Line Interior
+         * AND the Exterior of the line
+         * is also in that location of the target.
+         * NOTE: this assumes the line end is NOT also in an Area of a mixed-dim GC
+         */
         //TODO: handle zero-length lines?
         updateDim(isLineA, Location::INTERIOR, locArea, Dimension::L);
-        updateDim(isLineA, locLineEnd, locArea, Dimension::P);
         updateDim(isLineA, Location::EXTERIOR, locArea, Dimension::A);
     }
 }
diff --git a/tests/unit/operation/relateng/RelateNGGCTest.cpp b/tests/unit/operation/relateng/RelateNGGCTest.cpp
index 9db445229..c8405328a 100644
--- a/tests/unit/operation/relateng/RelateNGGCTest.cpp
+++ b/tests/unit/operation/relateng/RelateNGGCTest.cpp
@@ -334,14 +334,15 @@ void object::test<24> ()
 }
 
 
-// template<>
-// template<>
-// void object::test<25> ()
-// {
-//     std::string a = "POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))";
-//     std::string b = "GEOMETRYCOLLECTION (POLYGON((0 0, 10 0, 10 10, 0 10, 0 0)),LINESTRING(0 2, 0 5, 5 5))";
-//     checkEquals(a, b, true);
-// }
+template<>
+template<>
+void object::test<25> ()
+{
+    std::string a = "POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))";
+    std::string b = "GEOMETRYCOLLECTION (POLYGON((0 0, 10 0, 10 10, 0 10, 0 0)),LINESTRING(0 2, 0 5, 5 5))";
+    checkEquals(a, b, true);
+}
+
 
 
 } // namespace tut
diff --git a/tests/unit/operation/relateng/RelatePointLocatorTest.cpp b/tests/unit/operation/relateng/RelatePointLocatorTest.cpp
index 5947216bf..fb78765f2 100644
--- a/tests/unit/operation/relateng/RelatePointLocatorTest.cpp
+++ b/tests/unit/operation/relateng/RelatePointLocatorTest.cpp
@@ -51,7 +51,16 @@ struct test_relatepointlocator_data {
         RelatePointLocator locator(geom.get());
         CoordinateXY c(i, j);
         int actual = locator.locateWithDim(&c);
-        ensure_equals("checkLocation", expected, actual);
+        ensure_equals("checkLocation", actual, expected);
+    }
+
+    void checkLineEndDimLocation(const std::string& wkt, double x, double y, int expectedDimLoc)
+    {
+        std::unique_ptr<Geometry> geom = r.read(wkt);
+        RelatePointLocator locator(geom.get());
+        CoordinateXY c(x, y);
+        int actual = locator.locateLineEndWithDim(&c);
+        ensure_equals("checkLineEndDimLocation", actual, expectedDimLoc);
     }
 
     void checkNodeLocation(const std::string& wkt, double i, double j, Location expected)
@@ -60,7 +69,7 @@ struct test_relatepointlocator_data {
         RelatePointLocator locator(geom.get());
         CoordinateXY c(i, j);
         Location actual = locator.locateNode(&c, nullptr);
-        ensure_equals("checkNodeLocation", expected, actual);
+        ensure_equals("checkNodeLocation", actual, expected);
     }
 
 };
@@ -146,4 +155,6 @@ void object::test<8> ()
 
 
 
+
+
 } // namespace tut
diff --git a/tests/unit/operation/relateng/RelatePredicateTest.cpp b/tests/unit/operation/relateng/RelatePredicateTest.cpp
index 7408f3275..b1614f471 100644
--- a/tests/unit/operation/relateng/RelatePredicateTest.cpp
+++ b/tests/unit/operation/relateng/RelatePredicateTest.cpp
@@ -47,7 +47,7 @@ struct test_relatepredicate_data {
     {
         pred.finish();
         bool actual = pred.value();
-        ensure_equals(expected, actual);
+        ensure_equals("checkPred", actual, expected);
     }
 
     static void
@@ -79,10 +79,9 @@ struct test_relatepredicate_data {
 
     const std::string A_EXT_B_INT = "***.***.1**";
     const std::string A_INT_B_INT = "1**.***.***";
-
-
 };
 
+
 typedef test_group<test_relatepredicate_data> group;
 typedef group::object object;
 
diff --git a/tests/xmltester/tests/general/TestRelateGC.xml b/tests/xmltester/tests/general/TestRelateGC.xml
index 5f7869909..f67b789a0 100644
--- a/tests/xmltester/tests/general/TestRelateGC.xml
+++ b/tests/xmltester/tests/general/TestRelateGC.xml
@@ -1,7 +1,28 @@
 <run>
 
 <case>
-  <desc>A/GC-mP</desc>
+  <desc>GC:L/GC:PL - a line with the same line in a collection with an empty polygon</desc>
+  <a>
+    LINESTRING(0 0, 1 1)
+  </a>
+  <b>
+    GEOMETRYCOLLECTION(POLYGON EMPTY, LINESTRING(0 0, 1 1))
+  </b>
+  <test><op name="relate" arg3="1FFF0FFF2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> true </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> true </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> true </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> true </op></test>
+</case>
+
+<case>
+  <desc>A/GC:mP</desc>
   <a>
     POLYGON((-60 -50,-70 -50,-60 -40,-60 -50))
   </a>
@@ -21,4 +42,560 @@
   <test><op name="within"     arg1="A" arg2="B"> false </op></test>
 </case>
 
+<case>
+  <desc>A/GC:mP with empty MultiPoint elements</desc>
+  <a>
+    POLYGON ((3 7, 7 7, 7 3, 3 3, 3 7))
+  </a>
+  <b>
+    GEOMETRYCOLLECTION (MULTIPOINT (EMPTY, (5 5)), LINESTRING (1 9, 4 9))
+  </b>
+  <test><op name="relate" arg3="0F2FF1102" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> false </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> true </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>mA/GC:PL</desc>
+  <a>
+    MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0)))
+  </a>
+  <b>
+    GEOMETRYCOLLECTION ( LINESTRING (1 2, 1 1), POINT (0 0))
+  </b>
+  <test><op name="relate" arg3="1020F1FF2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> true </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> false </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> true </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>GC:PL/A</desc>
+  <a>
+    GEOMETRYCOLLECTION (POINT (7 1), LINESTRING (6 5, 6 4))
+  </a>
+  <b>
+    POLYGON ((7 1, 1 3, 3 9, 7 1))
+  </b>
+  <test><op name="relate" arg3="F01FF0212" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> false </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> true </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>P/GC:PL - point on boundary of GC with line and point</desc>
+  <a>
+    POINT(0 0)
+  </a>
+  <b>
+    GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0, 1 0))
+  </b>
+  <test><op name="relate" arg3="F0FFFF102" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> true </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+
+<case>
+  <desc>L/GC:A - line in interior of GC of overlapping polygons</desc>
+  <a>
+    LINESTRING (3 7, 7 3)
+  </a>
+  <b>
+    GEOMETRYCOLLECTION (POLYGON ((1 9, 7 9, 7 3, 1 3, 1 9)), POLYGON ((9 1, 3 1, 3 7, 9 7, 9 1)))
+  </b>
+  <test><op name="relate" arg3="1FF0FF212" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> true </op></test>
+</case>
+
+<case>
+  <desc>P/GC:A - point on common boundaries of 2 adjacent polygons</desc>
+  <a>
+    POINT (4 3)
+  </a>
+  <b>
+    GEOMETRYCOLLECTION (POLYGON ((1 1, 1 6, 4 6, 4 1, 1 1)), POLYGON ((9 1, 4 1, 4 6, 9 6, 9 1)))
+  </b>
+  <test><op name="relate" arg3="0FFFFF212" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> true </op></test>
+</case>
+
+<case>
+  <desc>P/GC:A - point on common node of 3 adjacent polygons</desc>
+  <a>
+    POINT (5 4)
+  </a>
+  <b>
+    GEOMETRYCOLLECTION (POLYGON ((1 6, 5 4, 4 1, 1 6)), POLYGON ((4 1, 5 4, 9 6, 4 1)), POLYGON ((1 6, 9 6, 5 4, 1 6)))
+  </b>
+  <test><op name="relate" arg3="0FFFFF212" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> true </op></test>
+</case>
+
+<case>
+  <desc>P/GC:A - point on common node of 6 adjacent polygons, with holes at node</desc>
+  <a>
+    POINT (6 6)
+  </a>
+  <b>
+GEOMETRYCOLLECTION (POLYGON ((1 9, 5 9, 6 6, 1 5, 1 9), (2 6, 4 8, 6 6, 2 6)), POLYGON ((2 6, 4 8, 6 6, 2 6)), POLYGON ((9 9, 9 5, 6 6, 5 9, 9 9)), POLYGON ((9 1, 5 1, 6 6, 9 5, 9 1), (7 2, 6 6, 8 3, 7 2)), POLYGON ((7 2, 6 6, 8 3, 7 2)), POLYGON ((1 1, 1 5, 6 6, 5 1, 1 1)))
+  </b>
+  <test><op name="relate" arg3="0FFFFF212" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> true </op></test>
+</case>
+
+<case>
+  <desc>P/GC:A - point on common node of 5 adjacent polygons, with holes at node and one not filled</desc>
+  <a>
+    POINT (6 6)
+  </a>
+  <b>
+GEOMETRYCOLLECTION (POLYGON ((1 9, 5 9, 6 6, 1 5, 1 9), (2 6, 4 8, 6 6, 2 6)), POLYGON ((2 6, 4 8, 6 6, 2 6)), POLYGON ((9 9, 9 5, 6 6, 5 9, 9 9)), POLYGON ((9 1, 5 1, 6 6, 9 5, 9 1), (7 2, 6 6, 8 3, 7 2)), POLYGON ((1 1, 1 5, 6 6, 5 1, 1 1)))
+  </b>
+  <test><op name="relate" arg3="F0FFFF212" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> true </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>L/GC:A - line on common boundaries of adjacent polygons</desc>
+  <a>
+    LINESTRING (4 5, 4 2)
+  </a>
+  <b>
+    GEOMETRYCOLLECTION (POLYGON ((1 1, 1 6, 4 6, 4 1, 1 1)), POLYGON ((9 1, 4 1, 4 6, 9 6, 9 1)))
+  </b>
+  <test><op name="relate" arg3="1FF0FF212" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> true </op></test>
+</case>
+
+<case>
+  <desc>L/GC:A - line on exterior boundaries of GC of overlapping polygons</desc>
+  <a>
+    LINESTRING (2 6, 8 6)
+  </a>
+  <b>
+    GEOMETRYCOLLECTION (POLYGON ((1 1, 1 6, 6 6, 6 1, 1 1)), POLYGON ((9 1, 4 1, 4 6, 9 6, 9 1)))
+  </b>
+  <test><op name="relate" arg3="F1FF0F212" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> true </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>GC:L/GC:A - lines covers boundaries of overlapping polygons</desc>
+  <a>
+    GEOMETRYCOLLECTION (LINESTRING (2 6, 9 6, 9 1, 7 1), LINESTRING (8 1, 1 1, 1 6, 7 6))
+  </a>
+  <b>
+    GEOMETRYCOLLECTION (POLYGON ((1 1, 1 6, 6 6, 6 1, 1 1)), POLYGON ((9 1, 4 1, 4 6, 9 6, 9 1)))
+  </b>
+  <test><op name="relate" arg3="F1FF0F2F2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> true </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>GC:A/GC:A - adjacent polygons contained by adjacent polygons</desc>
+  <a>
+    GEOMETRYCOLLECTION (POLYGON ((2 2, 2 5, 4 5, 4 2, 2 2)), POLYGON ((8 2, 4 3, 4 4, 8 5, 8 2)))
+  </a>
+  <b>
+    GEOMETRYCOLLECTION (POLYGON ((1 1, 1 6, 4 6, 4 1, 1 1)), POLYGON ((9 1, 4 1, 4 6, 9 6, 9 1)))
+  </b>
+  <test><op name="relate" arg3="2FF1FF212" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> true </op></test>
+</case>
+
+<case>
+  <desc>GC:A/P - adjacent polygons contain point at interior node</desc>
+  <a>
+    GEOMETRYCOLLECTION (POLYGON ((5 5, 2 9, 9 9, 9 5, 5 5)), POLYGON ((3 1, 5 5, 9 5, 9 1, 3 1)), POLYGON ((1 9, 2 9, 5 5, 3 1, 1 1, 1 9)))
+  </a>
+  <b>
+    POINT (5 5)
+  </b>
+  <test><op name="relate" arg3="0F2FF1FF2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> true </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> false </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> true </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>GC:A/P - adjacent polygons contain point on interior edge</desc>
+  <a>
+    GEOMETRYCOLLECTION (POLYGON ((5 5, 2 9, 9 9, 9 5, 5 5)), POLYGON ((3 1, 5 5, 9 5, 9 1, 3 1)), POLYGON ((1 9, 2 9, 5 5, 3 1, 1 1, 1 9)))
+  </a>
+  <b>
+    POINT (7 5)
+  </b>
+  <test><op name="relate" arg3="0F2FF1FF2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> true </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> false </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> true </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>GC:A/P - adjacent polygons cover point on exterior node</desc>
+  <a>
+    GEOMETRYCOLLECTION (POLYGON ((5 5, 2 9, 9 9, 9 5, 5 5)), POLYGON ((3 1, 5 5, 9 5, 9 1, 3 1)), POLYGON ((1 9, 2 9, 5 5, 3 1, 1 1, 1 9)))
+  </a>
+  <b>
+    POINT (9 5)
+  </b>
+  <test><op name="relate" arg3="FF20F1FF2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> false </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> true </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> true </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>GC:A/L - adjacent polygons contain line touching interior node</desc>
+  <a>
+    GEOMETRYCOLLECTION (POLYGON ((5 5, 2 9, 9 9, 9 5, 5 5)), POLYGON ((3 1, 5 5, 9 5, 9 1, 3 1)), POLYGON ((1 9, 2 9, 5 5, 3 1, 1 1, 1 9)))
+  </a>
+  <b>
+    LINESTRING (5 5, 7 7)
+  </b>
+  <test><op name="relate" arg3="102FF1FF2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> true </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> false </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> true </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>GC:A/L - adjacent polygons contain line along interior edge to boundary</desc>
+  <a>
+    GEOMETRYCOLLECTION (POLYGON ((5 5, 2 9, 9 9, 9 5, 5 5)), POLYGON ((3 1, 5 5, 9 5, 9 1, 3 1)), POLYGON ((1 9, 2 9, 5 5, 3 1, 1 1, 1 9)))
+  </a>
+  <b>
+    LINESTRING (5 5, 9 5)
+  </b>
+  <test><op name="relate" arg3="102F01FF2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> true </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> false </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> true </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>GC:A/GC:PL - adjacent polygons contain line and point</desc>
+  <a>
+    GEOMETRYCOLLECTION (POLYGON ((5 5, 2 9, 9 9, 9 5, 5 5)), POLYGON ((3 1, 5 5, 9 5, 9 1, 3 1)), POLYGON ((1 9, 2 9, 5 5, 3 1, 1 1, 1 9)))
+  </a>
+  <b>
+    GEOMETRYCOLLECTION (POINT (5 5), LINESTRING (5 7, 7 7))
+  </b>
+  <test><op name="relate" arg3="102FF1FF2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> true </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> false </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> true </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>GC:A/A - adjacent polygons containing polygon with endpoint inside</desc>
+  <a>
+    GEOMETRYCOLLECTION (POLYGON ((5 5, 2 9, 9 9, 9 5, 5 5)), POLYGON ((3 1, 5 5, 9 5, 9 1, 3 1)), POLYGON ((1 9, 2 9, 5 5, 3 1, 1 1, 1 9)))
+  </a>
+  <b>
+    POLYGON ((3 7, 7 7, 7 3, 3 3, 3 7))
+  </b>
+  <test><op name="relate" arg3="212FF1FF2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> true </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> false </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> true </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>GC:A/A - adjacent polygons overlapping polygon with shell outside and hole inside</desc>
+  <a>
+    GEOMETRYCOLLECTION (POLYGON ((5 5, 2 9, 9 9, 9 5, 5 5)), POLYGON ((3 1, 5 5, 9 5, 9 1, 3 1)), POLYGON ((1 9, 2 9, 5 5, 3 1, 1 1, 1 9)))
+  </a>
+  <b>
+    POLYGON ((0 10, 10 10, 10 0, 0 0, 0 10), (2 8, 8 8, 8 2, 2 2, 2 8))
+  </b>
+  <test><op name="relate" arg3="2121FF212" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> false </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> true </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> false </op></test>
+</case>
+
+<case>
+  <desc>GC:A/GC:A - overlapping polygons equal to overlapping polygons</desc>
+  <a>
+    GEOMETRYCOLLECTION (POLYGON ((1 6, 9 6, 9 2, 1 2, 1 6)), POLYGON ((9 1, 1 1, 1 5, 9 5, 9 1)))
+  </a>
+  <b>
+    GEOMETRYCOLLECTION (POLYGON ((1 1, 1 6, 6 6, 6 1, 1 1)), POLYGON ((9 1, 4 1, 4 6, 9 6, 9 1)))
+  </b>
+  <test><op name="relate" arg3="2FFF1FFF2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> true </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> true </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> true </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> true </op></test>
+</case>
+
+<case>
+  <desc>GC:A/GC:A - overlapping polygons contained by overlapping polygons</desc>
+  <a>
+    GEOMETRYCOLLECTION (POLYGON ((4 4, 6 4, 6 3, 4 3, 4 4)), POLYGON ((2 5, 8 5, 8 2, 2 2, 2 5)))
+  </a>
+  <b>
+    GEOMETRYCOLLECTION (POLYGON ((1 1, 1 6, 6 6, 6 1, 1 1)), POLYGON ((9 1, 4 1, 4 6, 9 6, 9 1)))
+  </b>
+  <test><op name="relate" arg3="2FF1FF212" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> false </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> false </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> true </op></test>
+</case>
+
+
+<case>
+  <desc>A/GC:A - polygon equal to nested overlapping polygons</desc>
+  <a>
+    POLYGON ((1 9, 9 9, 9 1, 1 1, 1 9))
+  </a>
+  <b>
+    GEOMETRYCOLLECTION (
+      POLYGON ((1 1, 1 5, 5 5, 5 1, 1 1)), 
+      GEOMETRYCOLLECTION( 
+          POLYGON ((1 5, 5 9, 9 9, 9 5, 5 1, 1 5)),
+          MULTIPOLYGON (((1 9, 5 9, 5 5, 1 5, 1 9)), ((9 1, 5 1, 5 5, 9 5, 9 1)))
+      )
+    )
+  </b>
+  <test><op name="relate" arg3="2FFF1FFF2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> true </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> true </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> true </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> true </op></test>
+</case>
+
+<case>
+  <desc>GC:AmP/A - polygon with overlapping points equal to polygon </desc>
+  <a>
+    GEOMETRYCOLLECTION (POLYGON((0 0, 10 0, 10 10, 0 10, 0 0)),
+      MULTIPOINT(0 2, 0 5))
+  </a>
+  <b>
+    POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))
+  </b>
+  <test><op name="relate" arg3="2FFF1FFF2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> true </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> true </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> true </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> true </op></test>
+</case>
+
+<case>
+  <desc>GC:AL/A - polygon with overlapping line equal to polygon </desc>
+  <a>
+    GEOMETRYCOLLECTION (POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0)), 
+      LINESTRING (0 2, 0 5, 5 5))
+  </a>
+  <b>
+    POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))
+  </b>
+  <test><op name="relate" arg3="2FFF1FFF2" arg1="A" arg2="B"> true </op></test>
+  <test><op name="contains"   arg1="A" arg2="B"> true </op></test>
+  <test><op name="coveredBy"  arg1="A" arg2="B"> true </op></test>
+  <test><op name="covers"     arg1="A" arg2="B"> true </op></test>
+  <test><op name="crosses"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="disjoint"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="equalsTopo" arg1="A" arg2="B"> true </op></test>
+  <test><op name="intersects" arg1="A" arg2="B"> true </op></test>
+  <test><op name="overlaps"   arg1="A" arg2="B"> false </op></test>
+  <test><op name="touches"    arg1="A" arg2="B"> false </op></test>
+  <test><op name="within"     arg1="A" arg2="B"> true </op></test>
+</case>
+
 </run>

-----------------------------------------------------------------------

Summary of changes:
 include/geos/operation/relateng/RelateGeometry.h   |   2 +-
 include/geos/operation/relateng/RelateNG.h         |  13 +
 .../geos/operation/relateng/RelatePointLocator.h   |   4 +-
 include/geos/operation/relateng/TopologyComputer.h |  14 +-
 src/operation/relateng/RelateGeometry.cpp          |   6 +-
 src/operation/relateng/RelateNG.cpp                |   8 +-
 src/operation/relateng/RelatePointLocator.cpp      |  13 +-
 src/operation/relateng/TopologyComputer.cpp        |  36 +-
 tests/unit/operation/relateng/RelateNGGCTest.cpp   |  17 +-
 .../operation/relateng/RelatePointLocatorTest.cpp  |  15 +-
 .../operation/relateng/RelatePredicateTest.cpp     |   5 +-
 tests/xmltester/tests/general/TestRelateGC.xml     | 579 ++++++++++++++++++++-
 12 files changed, 668 insertions(+), 44 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list