[geos-commits] [SCM] GEOS branch master updated. 8e340a77322445669bbffc5d6b9bf4d01b676a5a

git at osgeo.org git at osgeo.org
Fri Aug 7 16:29:36 PDT 2020


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, master has been updated
       via  8e340a77322445669bbffc5d6b9bf4d01b676a5a (commit)
      from  b3cea2a7aa690b277cdf000a2b04e8f6ac0ca523 (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 8e340a77322445669bbffc5d6b9bf4d01b676a5a
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Fri Aug 7 16:20:51 2020 -0700

    Port https://github.com/dr-jts/jts/commit/ea13dc32415a7cf6e38279354f7a06e5e2aff1ea Switch to outputting all components for intersection op

diff --git a/include/geos/operation/overlayng/LineBuilder.h b/include/geos/operation/overlayng/LineBuilder.h
index 9e8e1bb..63039b8 100644
--- a/include/geos/operation/overlayng/LineBuilder.h
+++ b/include/geos/operation/overlayng/LineBuilder.h
@@ -81,12 +81,6 @@ private:
     void markResultLines();
 
     /**
-    * If the edge linework is already in the result,
-    * this edge does not need to be included as a line.
-    */
-    bool isInResult(OverlayEdge* edge) const;
-
-    /**
     * Checks if the topology indicated by an edge label
     * determines that this edge should be part of a result line.
     *
@@ -106,7 +100,7 @@ private:
     * (For instance, the intersection of line edge and a collapsed boundary
     * is included in the result).
     */
-    geom::Location effectiveLocation(int geomIndex, const OverlayLabel* lbl) const;
+    geom::Location effectiveLocation(const OverlayLabel* lbl, int geomIndex) const;
 
     void addResultLines();
     void addResultLinesMerged();
@@ -162,8 +156,6 @@ public:
 
     std::vector<std::unique_ptr<geom::LineString>> getLines();
 
-
-
 };
 
 
diff --git a/include/geos/operation/overlayng/OverlayEdge.h b/include/geos/operation/overlayng/OverlayEdge.h
index 34ea2a9..3d4882f 100644
--- a/include/geos/operation/overlayng/OverlayEdge.h
+++ b/include/geos/operation/overlayng/OverlayEdge.h
@@ -135,6 +135,8 @@ public:
 
     bool isInResult() const;
 
+    bool isInResultEither() const;
+
     void setNextResult(OverlayEdge* e);
 
     OverlayEdge* nextResult() const;
diff --git a/include/geos/operation/overlayng/OverlayLabel.h b/include/geos/operation/overlayng/OverlayLabel.h
index 275afe2..dc33cb9 100644
--- a/include/geos/operation/overlayng/OverlayLabel.h
+++ b/include/geos/operation/overlayng/OverlayLabel.h
@@ -43,50 +43,43 @@ namespace overlayng { // geos.operation.overlayng
 * of the originating ring (which allows
 * determination of the edge role in collapse cases).
 *
-* For each input geometry, the label indicates that an edge is in one of the following states
-* (denoted by the <code>dim</code> field).
+* For each input geometry, the label indicates that an edge
+* is in one of the following states (identified by the "dim" field).
 * Each state has some additional information about the edge.
 *
-* <li>A <b>Boundary</b> edge of an input Area (polygon)
-*   <ul>
-*   <li><code>dim</code> = DIM_BOUNDARY</li>
-*   <li><code>locLeft, locRight</code> : the locations of the edge sides for the input Area</li>
-*   <li><code>isHole</code> : whether the
-* edge was in a shell or a hole</li>
-*   </ul>
-* </li>
-* <li>A <b>Collapsed</b> edge of an input Area
-* (which had two or more parent edges)
-*   <ul>
-*   <li><code>dim</code> = DIM_COLLAPSE</li>
-*   <li><code>locLine</code> : the location of the
-* edge relative to the input Area</li>
-*   <li><code>isHole</code> : whether some
-* contributing edge was in a shell (<code>false</code>),
-* or otherwise that all were in holes</li> (<code>true</code>)
-*   </ul>
-* </li>
-* <li>An edge from an input <b>Line</b>
-*   <ul>
-*   <li><code>dim</code> = DIM_LINE</li>
-*   <li><code>locLine</code> : initialized to LOC_UNKNOWN,
-*          to simplify logic.</li>
-*   </ul>
-* </li>
-* <li>An edge which is <b>Not Part</b> of an input geometry
-* (and thus must be part of the other geometry).
-*   <ul>
-*   <li><code>dim</code> = NOT_PART</li>
-*   </ul>
-* </li>
-* </ul>
+* * A Boundary edge of an input Area (polygon)
+*
+*   * dim = DIM_BOUNDARY
+*   * locLeft, locRight : the locations of the edge sides for the input Area
+*   * isHole : whether the edge was in a shell or a hole
+*
+* * A Collapsed edge of an input Area
+*   (which had two or more parent edges)
+*
+*   * dim = DIM_COLLAPSE
+*   * locLine : the location of the
+*     edge relative to the input Area
+*   * isHole : whether some
+*     contributing edge was in a shell (false),
+*     or otherwise that all were in holes (true)
+*
+* * An edge from an input Line
+*
+*   * dim = DIM_LINE
+*   * locLine : initialized to LOC_UNKNOWN, to simplify logic.
+*
+* * An edge which is Not Part of an input geometry
+*   (and thus must be part of the other geometry).
+*
+*   * dim = NOT_PART
+*
 * Note that:
-* <ul>
-* <li>an edge cannot be both a Collapse edge and a Line edge in the same input geometry,
-* because each input geometry must be homogeneous.
-* <li>an edge may be an Boundary edge in one input geometry
-* and a Line or Collapse edge in the other input.
-* </ul>
+*
+* * an edge cannot be both a Collapse edge and a Line edge in the same input geometry,
+*   because each input geometry must be homogeneous.
+* * an edge may be an Boundary edge in one input geometry
+*   and a Line or Collapse edge in the other input.
+*
 * @author Martin Davis
 */
 
@@ -191,6 +184,12 @@ public:
     * @return true if the label is for a collapse coincident with a boundary
     */
     bool isBoundaryCollapse() const;
+
+    /**
+    * Tests if a label is for an edge where two
+    * area touch along their boundary.
+    */
+    bool isBoundaryTouch() const;
     bool isBoundary(int index) const;
     bool isLineLocationUnknown(int index) const;
 
diff --git a/include/geos/operation/overlayng/OverlayNG.h b/include/geos/operation/overlayng/OverlayNG.h
index 31eb87d..d09485d 100644
--- a/include/geos/operation/overlayng/OverlayNG.h
+++ b/include/geos/operation/overlayng/OverlayNG.h
@@ -87,6 +87,7 @@ public:
     static constexpr int UNION          = overlay::OverlayOp::opUNION;
     static constexpr int DIFFERENCE     = overlay::OverlayOp::opDIFFERENCE;
     static constexpr int SYMDIFFERENCE  = overlay::OverlayOp::opSYMDIFFERENCE;
+    static constexpr bool ALLOW_INT_MIXED_INT_RESULT = true;
 
     /**
     * Creates an overlay operation on the given geometries,
diff --git a/src/operation/overlayng/LineBuilder.cpp b/src/operation/overlayng/LineBuilder.cpp
index ac5cf68..e24602d 100644
--- a/src/operation/overlayng/LineBuilder.cpp
+++ b/src/operation/overlayng/LineBuilder.cpp
@@ -47,34 +47,41 @@ LineBuilder::markResultLines()
 {
     std::vector<OverlayEdge*>& edges = graph->getEdges();
     for (OverlayEdge* edge : edges) {
-        if (isInResult(edge))
+              /**
+        * If the edge linework is already marked as in the result,
+        * it is not included as a line.
+        * This occurs when an edge either is in a result area
+        * or has already been included as a line.
+        */
+        if (edge->isInResultEither()) {
             continue;
+        }
         if (isResultLine(edge->getLabel())) {
             edge->markInResultLine();
         }
     }
 }
 
-/*private*/
-bool
-LineBuilder::isInResult(OverlayEdge* edge) const
-{
-    return edge->isInResult() || edge->symOE()->isInResult();
-}
 
 /*private*/
 bool
 LineBuilder::isResultLine(const OverlayLabel* lbl) const
 {
     /**
-    * Edges which are just collapses along boundaries
-    * are not output.
-    * In other words, an edge must be from a source line
-    * or two (coincident) area boundaries.
+    * Edges which are collapses along boundaries are not output.
+    * I.e a result line edge must be from a input line
+    * or two coincident area boundaries.
     */
     if (lbl->isBoundaryCollapse())
         return false;
 
+
+    if (OverlayNG::ALLOW_INT_MIXED_INT_RESULT &&
+        opCode == OverlayNG::INTERSECTION &&
+        lbl->isBoundaryTouch()) {
+        return true;
+    }
+
     /**
     * Skip edges that are inside result area, if there is one.
     * It is sufficient to check against an input area rather
@@ -88,8 +95,8 @@ LineBuilder::isResultLine(const OverlayLabel* lbl) const
     if (hasResultArea && lbl->isLineInArea(inputAreaIndex))
         return false;
 
-    Location aLoc = effectiveLocation(0, lbl);
-    Location bLoc = effectiveLocation(1, lbl);
+    Location aLoc = effectiveLocation(lbl, 0);
+    Location bLoc = effectiveLocation(lbl, 1);
 
     bool inResult = OverlayNG::isResultOfOp(opCode, aLoc, bLoc);
     return inResult;
@@ -97,7 +104,7 @@ LineBuilder::isResultLine(const OverlayLabel* lbl) const
 
 /*private*/
 Location
-LineBuilder::effectiveLocation(int geomIndex, const OverlayLabel* lbl) const
+LineBuilder::effectiveLocation(const OverlayLabel* lbl, int geomIndex) const
 {
     if (lbl->isCollapse(geomIndex)) {
         return Location::INTERIOR;
@@ -108,6 +115,7 @@ LineBuilder::effectiveLocation(int geomIndex, const OverlayLabel* lbl) const
     return lbl->getLineLocation(geomIndex);
 }
 
+
 /*private*/
 void
 LineBuilder::addResultLinesMerged()
diff --git a/src/operation/overlayng/OverlayEdge.cpp b/src/operation/overlayng/OverlayEdge.cpp
index a93eb84..3566bf7 100644
--- a/src/operation/overlayng/OverlayEdge.cpp
+++ b/src/operation/overlayng/OverlayEdge.cpp
@@ -152,6 +152,13 @@ OverlayEdge::isInResultAreaBoth() const
 }
 
 /*public*/
+bool
+OverlayEdge::isInResultEither() const
+{
+    return isInResult() || symOE()->isInResult();
+}
+
+/*public*/
 void
 OverlayEdge::unmarkFromResultAreaBoth()
 {
diff --git a/src/operation/overlayng/OverlayLabel.cpp b/src/operation/overlayng/OverlayLabel.cpp
index 7fb8fe8..c3ce312 100644
--- a/src/operation/overlayng/OverlayLabel.cpp
+++ b/src/operation/overlayng/OverlayLabel.cpp
@@ -188,6 +188,14 @@ OverlayLabel::isBoundaryCollapse() const
 
 /*public*/
 bool
+OverlayLabel::isBoundaryTouch() const
+{
+    return isBoundaryBoth() &&
+        getLocation(0, Position::RIGHT, true) != getLocation(1, Position::RIGHT, true);
+}
+
+/*public*/
+bool
 OverlayLabel::isBoundary(int index) const
 {
     if (index == 0) {
diff --git a/src/operation/overlayng/OverlayNG.cpp b/src/operation/overlayng/OverlayNG.cpp
index ba5ee3f..c7f398b 100644
--- a/src/operation/overlayng/OverlayNG.cpp
+++ b/src/operation/overlayng/OverlayNG.cpp
@@ -229,19 +229,22 @@ OverlayNG::extractResult(int p_opCode, OverlayGraph* graph)
     bool hasResultComponents = resultPolyList.size() > 0;
 
     //--- Build lines
+    bool allowMixedIntResult = ! hasResultComponents || ALLOW_INT_MIXED_INT_RESULT;
     std::vector<std::unique_ptr<LineString>> resultLineList;
-    if (p_opCode != INTERSECTION || ! hasResultComponents) {
+    if (p_opCode != INTERSECTION || allowMixedIntResult) {
         LineBuilder lineBuilder(&inputGeom, graph, hasResultComponents, p_opCode, geomFact);
         resultLineList = lineBuilder.getLines();
-        hasResultComponents = resultLineList.size() > 0;
     }
+
+    hasResultComponents = hasResultComponents || resultLineList.size() > 0;
     /**
      * Since operations with point inputs are handled elsewhere,
      * this only handles the case where non-point inputs
-     * intersect in points ONLY.
+     * intersect in points.
      */
     std::vector<std::unique_ptr<Point>> resultPointList;
-    if (opCode == INTERSECTION && ! hasResultComponents) {
+    allowMixedIntResult = ! hasResultComponents || ALLOW_INT_MIXED_INT_RESULT;
+    if (opCode == INTERSECTION && allowMixedIntResult) {
         IntersectionPointBuilder pointBuilder(graph, geomFact);
         resultPointList = pointBuilder.getPoints();
     }
diff --git a/tests/unit/operation/overlayng/OverlayNGTest.cpp b/tests/unit/operation/overlayng/OverlayNGTest.cpp
index 8a2f0a7..e4d1f08 100644
--- a/tests/unit/operation/overlayng/OverlayNGTest.cpp
+++ b/tests/unit/operation/overlayng/OverlayNGTest.cpp
@@ -195,14 +195,15 @@ void object::test<12> ()
     testOverlay(a, b, exp, OverlayNG::INTERSECTION, 1);
 }
 
-//  testPolygoPolygonWithLineTouchIntersection
+//  testAreaLineIntersection
 template<>
 template<>
 void object::test<13> ()
 {
     std::string a = "POLYGON ((360 200, 220 200, 220 180, 300 180, 300 160, 300 140, 360 200))";
     std::string b = "MULTIPOLYGON (((280 180, 280 160, 300 160, 300 180, 280 180)), ((220 230, 240 230, 240 180, 220 180, 220 230)))";
-    std::string exp = "POLYGON ((220 200, 240 200, 240 180, 220 180, 220 200))";
+    // std::string exp = "POLYGON ((220 200, 240 200, 240 180, 220 180, 220 200))";
+    std::string exp = "GEOMETRYCOLLECTION (LINESTRING (280 180, 300 180), LINESTRING (300 160, 300 180), POLYGON ((220 180, 220 200, 240 200, 240 180, 220 180)))";
     testOverlay(a, b, exp, OverlayNG::INTERSECTION, 1);
 }
 
@@ -471,17 +472,29 @@ void object::test<37> ()
     testOverlay(a, b, exp, OverlayNG::INTERSECTION, 1);
 }
 
-// infiniteLoop
+// testAreaLinePointIntersection
 template<>
 template<>
 void object::test<38> ()
 {
-    std::string a = "MULTIPOLYGON (((0 7, 9 7, 9 0, 0 0, 0 7), (1 6, 8 6, 8 1, 1 1, 1 6)), ((1.5 5.7, 3.9 1.2, 7 1.3, 5.5 5.5, 1.5 5.7)))";
-    std::string b = "POLYGON ((0 7, 10 7, 10 0, 0 0, 0 7), (7.8 5, 7.5 2, 9.5 2, 10 5, 7.8 5))";
-    std::string exp = "POLYGON ((0 7, 9 7, 9 5, 8 5, 8 6, 6 6, 7 1, 8 1, 8 2, 9 2, 9 0, 0 0, 0 7), (1 6, 1 1, 4 1, 2 6, 1 6))";
+    std::string a = "POLYGON ((100 100, 200 100, 200 150, 250 100, 300 100, 300 150, 350 100, 350 200, 100 200, 100 100))";
+    std::string b = "POLYGON ((100 140, 170 140, 200 100, 400 100, 400 30, 100 30, 100 140))";
+    std::string exp = "GEOMETRYCOLLECTION (POINT (350 100), LINESTRING (250 100, 300 100), POLYGON ((100 100, 100 140, 170 140, 200 100, 100 100)))";
     testOverlay(a, b, exp, OverlayNG::INTERSECTION, 1);
 }
 
+// testPolyPolyTouchIntersection
+template<>
+template<>
+void object::test<39> ()
+{
+    std::string a = "POLYGON ((300 0, 100 0, 100 100, 300 100, 300 0))";
+    std::string b = "POLYGON ((100 200, 300 200, 300 100, 200 100, 200 0, 100 0, 100 200))";
+    std::string exp = "GEOMETRYCOLLECTION (LINESTRING (200 100, 300 100), POLYGON ((200 0, 100 0, 100 100, 200 100, 200 0)))";
+    testOverlay(a, b, exp, OverlayNG::INTERSECTION, 1);
+}
+
+
 
 
 } // namespace tut
diff --git a/tests/xmltester/tests/general/TestNGOverlayA.xml b/tests/xmltester/tests/general/TestNGOverlayA.xml
index fc41537..3d981d4 100644
--- a/tests/xmltester/tests/general/TestNGOverlayA.xml
+++ b/tests/xmltester/tests/general/TestNGOverlayA.xml
@@ -133,7 +133,7 @@ Uses a floating precision model.
   </b>
 <test>
   <op name="intersectionNG" arg1="A" arg2="B">
-    LINESTRING (30 25, 30 20)
+    GEOMETRYCOLLECTION (LINESTRING (30 25, 30 20), POINT (30 15))
   </op>
 </test>
 <test>
@@ -163,7 +163,8 @@ Uses a floating precision model.
   </b>
 <test>
   <op name="intersectionNG" arg1="A" arg2="B">
-    POLYGON ((30 25, 30 20, 25 25, 30 25))
+    GEOMETRYCOLLECTION (POLYGON ((25 25, 30 25, 30 20, 25 25)),
+    LINESTRING (30 15, 30 10))
   </op>
 </test>
 <test>
@@ -400,7 +401,7 @@ POLYGON ((135 176, 180 176, 180 130, 135 130, 135 176))
   <op name="symdifferenceNG" arg1="A" arg2="B">
     MULTIPOLYGON(
       (
-        (20 340, 330 380, 50 40, 28 260, 140 220, 210 320, 140 270, 27 270, 20 340)), 
+        (20 340, 330 380, 50 40, 28 260, 140 220, 210 320, 140 270, 27 270, 20 340)),
       (
         (27 270, 28 260, 0 270, 27 270)))
   </op>
@@ -479,7 +480,10 @@ POLYGON ((13 27, 27 27, 27 13, 13 13, 13 27), (15 25, 20 25, 20 20, 15 20, 15 25
   </b>
 <test>
   <op name="intersectionNG" arg1="A" arg2="B">
-MULTIPOLYGON (((22 22, 27 22, 27 20, 20 20, 20 25, 20 27, 22 27, 22 22)), ((15 13, 15 15, 13 15, 13 20, 15 20, 20 20, 20 13, 15 13)))
+  GEOMETRYCOLLECTION (POLYGON ((22 22, 27 22, 27 20, 20 20, 20 25, 20 27, 22 27, 22 22)),
+    POLYGON ((15 20, 20 20, 20 13, 15 13, 15 15, 13 15, 13 20, 15 20)),
+    LINESTRING (22 27, 27 27),
+    LINESTRING (27 27, 27 22))
   </op>
 </test>
 <test>
diff --git a/tests/xmltester/tests/general/TestNGOverlayAPrec.xml b/tests/xmltester/tests/general/TestNGOverlayAPrec.xml
index e137f8d..9e99822 100644
--- a/tests/xmltester/tests/general/TestNGOverlayAPrec.xml
+++ b/tests/xmltester/tests/general/TestNGOverlayAPrec.xml
@@ -4,8 +4,8 @@ Covers topological situations with precision collapse,
 Uses snap-rounding.
 </desc>
 <!--  Precision must be specified for each operation.
-      rather than a global precision model, 
-      since that rounds input coordinates -->  
+      rather than a global precision model,
+      since that rounds input coordinates -->
 
 <case>
   <desc>AA - box-triangle collapse</desc>
@@ -166,7 +166,9 @@ MULTIPOLYGON (((0 7, 9 7, 9 0, 0 0, 0 7), (1 6, 8 6, 8 1, 1 1, 1 6)), ((1.5 5.7,
 POLYGON ((0 7, 10 7, 10 0, 0 0, 0 7), (7.8 5, 7.5 2, 9.5 2, 10 5, 7.8 5))
   </b>
 <test>  <op name="intersectionSR" arg1="A" arg2="B" arg3="1">
-POLYGON ((0 7, 9 7, 9 5, 8 5, 8 6, 6 6, 7 1, 8 1, 8 2, 9 2, 9 0, 0 0, 0 7), (1 6, 1 1, 4 1, 2 6, 1 6))
+GEOMETRYCOLLECTION (POLYGON ((0 7, 9 7, 9 5, 8 5, 8 6, 6 6, 7 1, 8 1, 8 2, 9 2, 9 0, 0 0, 0 7),
+  (1 6, 1 1, 4 1, 2 6, 1 6)),
+  LINESTRING (8 5, 8 2))
   </op></test>
 <test>  <op name="unionSR" arg1="A" arg2="B" arg3="1">
 POLYGON ((0 7, 9 7, 10 7, 10 5, 9 5, 9 2, 10 2, 10 0, 9 0, 0 0, 0 7))
@@ -281,4 +283,4 @@ MULTIPOLYGON (((0 1, 0 3, 1 3, 1 1, 0 1)), ((4 4, 4 1, 3 1, 3 3, 1 3, 1 4, 4 4))
   </op></test>
 </case>
 
-</run>
\ No newline at end of file
+</run>
diff --git a/tests/xmltester/tests/general/TestNGOverlayL.xml b/tests/xmltester/tests/general/TestNGOverlayL.xml
index 6e435c3..a928edf 100644
--- a/tests/xmltester/tests/general/TestNGOverlayL.xml
+++ b/tests/xmltester/tests/general/TestNGOverlayL.xml
@@ -163,7 +163,7 @@ LINESTRING (0 0, 10 10)
 LINESTRING (0 0, 3 3, 8 2, 1 9)
   </b>
 <test>  <op name="intersectionNG" arg1="A" arg2="B">
-LINESTRING (0 0, 3 3)
+GEOMETRYCOLLECTION (LINESTRING (0 0, 3 3), POINT (5 5))
   </op></test>
 <test>  <op name="unionNG" arg1="A" arg2="B">
 MULTILINESTRING ((5 5, 1 9), (0 0, 3 3), (5 5, 10 10), (3 3, 8 2, 5 5), (3 3, 5 5))
@@ -230,4 +230,4 @@ GEOMETRYCOLLECTION (POLYGON ((300 300, 300 400, 400 400, 400 300, 300 300)), POL
 </case>
 
 
-</run>
\ No newline at end of file
+</run>

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

Summary of changes:
 include/geos/operation/overlayng/LineBuilder.h     | 10 +--
 include/geos/operation/overlayng/OverlayEdge.h     |  2 +
 include/geos/operation/overlayng/OverlayLabel.h    | 81 +++++++++++-----------
 include/geos/operation/overlayng/OverlayNG.h       |  1 +
 src/operation/overlayng/LineBuilder.cpp            | 36 ++++++----
 src/operation/overlayng/OverlayEdge.cpp            |  7 ++
 src/operation/overlayng/OverlayLabel.cpp           |  8 +++
 src/operation/overlayng/OverlayNG.cpp              | 11 +--
 tests/unit/operation/overlayng/OverlayNGTest.cpp   | 25 +++++--
 tests/xmltester/tests/general/TestNGOverlayA.xml   | 12 ++--
 .../xmltester/tests/general/TestNGOverlayAPrec.xml | 10 +--
 tests/xmltester/tests/general/TestNGOverlayL.xml   |  4 +-
 12 files changed, 123 insertions(+), 84 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list