[geos-commits] [SCM] GEOS branch master updated. 1ebed610582ad026cd08425423b3ecd95f0dd2e6

git at osgeo.org git at osgeo.org
Wed Jan 23 08:24:29 PST 2019


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  1ebed610582ad026cd08425423b3ecd95f0dd2e6 (commit)
       via  fa7e4f8219395f6f9d4c4c67f1a6b567b5a59f47 (commit)
      from  df24b6bb8ba421d45cd4a0c4732a847b0b6e0d56 (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 1ebed610582ad026cd08425423b3ecd95f0dd2e6
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Wed Jan 23 08:23:49 2019 -0800

    Add test case and fix intersection finger

diff --git a/src/noding/NodingIntersectionFinder.cpp b/src/noding/NodingIntersectionFinder.cpp
index 98c10c4..a86b5c5 100644
--- a/src/noding/NodingIntersectionFinder.cpp
+++ b/src/noding/NodingIntersectionFinder.cpp
@@ -121,14 +121,13 @@ NodingIntersectionFinder::processIntersections(
     if (isInteriorInt || isInteriorVertexInt)
     {
         // found an intersection!
-        // TODO: record endpoint intersection(s)
-        // Coordinate intSegments[4];
-        // intSegments[0] = p00;
-        // intSegments[1] = p01;
-        // intSegments[2] = p10;
-        // intSegments[3] = p11;
+        intSegments.push_back(p00);
+        intSegments.push_back(p01);
+        intSegments.push_back(p10);
+        intSegments.push_back(p11);
 
         interiorIntersection = li.getIntersection(0);
+        // TODO: record endpoint intersection(s)
         // if (keepIntersections) intersections.add(interiorIntersection);
         intersectionCount++;
     }
diff --git a/tests/xmltester/CMakeLists.txt b/tests/xmltester/CMakeLists.txt
index 0ea8f77..47e8b8b 100644
--- a/tests/xmltester/CMakeLists.txt
+++ b/tests/xmltester/CMakeLists.txt
@@ -131,6 +131,7 @@ if(GEOS_ENABLE_TESTS)
     ${XMLTESTS_DIR}/ticket/bug615.xml
     ${XMLTESTS_DIR}/ticket/bug716.xml
     ${XMLTESTS_DIR}/ticket/bug837.xml
+    ${XMLTESTS_DIR}/ticket/bug838.xml
     ${XMLTESTS_DIR}/validate/TestRelateAA-big.xml
     ${XMLTESTS_DIR}/validate/TestRelateAA.xml
     ${XMLTESTS_DIR}/validate/TestRelateAC.xml
diff --git a/tests/xmltester/Makefile.am b/tests/xmltester/Makefile.am
index 2f7cff5..87b2b4f 100644
--- a/tests/xmltester/Makefile.am
+++ b/tests/xmltester/Makefile.am
@@ -100,6 +100,7 @@ SAFE_XMLTESTS= \
 	$(srcdir)/tests/ticket/bug615.xml \
 	$(srcdir)/tests/ticket/bug716.xml \
 	$(srcdir)/tests/ticket/bug837.xml \
+	$(srcdir)/tests/ticket/bug838.xml \
 	$(srcdir)/tests/validate/TestRelateAA-big.xml \
 	$(srcdir)/tests/validate/TestRelateAA.xml \
 	$(srcdir)/tests/validate/TestRelateAC.xml \
diff --git a/tests/xmltester/tests/ticket/bug838.xml b/tests/xmltester/tests/ticket/bug838.xml
new file mode 100644
index 0000000..7e15c28
--- /dev/null
+++ b/tests/xmltester/tests/ticket/bug838.xml
@@ -0,0 +1,23 @@
+<run>
+<precisionModel type="FLOATING" />
+<case>
+<desc>
+Union of two valid polygons resulting in an invalid geometry in JTS 1.15.
+See https://trac.osgeo.org/geos/ticket/838.
+Failure is due to very close vertices leading to noding robustness failure.
+Fixed by improved noding validation detection, which allows
+snapping heuristic to be activated.
+</desc>
+<a>
+00000000060000000200000000030000000100000005412CD75B00000000413D8F0966666667412CD75933333333413D8F6D80000000412CD82166666667413D8F6E4CCCCCCD412CD82500000000413D8EA61999999A412CD75B00000000413D8F096666666700000000030000000100000005412CD82500000001413D8EA61999999A412CD82333333334413D8F0A33333333412CD8EB66666666413D8F0B19999999412CD8ED33333333413D8EA700000001412CD82500000001413D8EA61999999A
+</a>
+<b>
+00000000030000000100000007412CD9D4D50CE8F7413D8EA7FBC39C12412CD8ED33333333413D8EA700000000412CD8EB66666667413D8F0B1999999A412CD82333333333413D8F0A33333333412CD82166666667413D8F6E4CCCCCCD412CD9B1CCCCCCCD413D8F701999999A412CD9D4D50CE8F7413D8EA7FBC39C12
+</b>
+<test>
+<op name="union" arg1="A" arg2="B">
+0103000000010000000A000000000000005BD72C4167666666098F3D413333333359D72C41000000806D8F3D416766666621D82C41CDCCCC4C6E8F3D41CDCCCCCCB1D92C419A999919708F3D41F7E80CD5D4D92C41129CC3FBA78E3D4133333333EDD82C4100000000A78E3D410100000025D82C419A999919A68E3D413333333323D82C41333333330A8F3D410000000025D82C419A999919A68E3D41000000005BD72C4167666666098F3D41
+</op>
+</test>
+</case>
+</run>

commit fa7e4f8219395f6f9d4c4c67f1a6b567b5a59f47
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Tue Jan 22 15:32:32 2019 -0800

    Improve overlay noding validation
    JTS 06fa68bf9e6e445f0252ae5fc0dac33e86b4f890

diff --git a/include/geos/noding/FastNodingValidator.h b/include/geos/noding/FastNodingValidator.h
index 9675c58..c9b6622 100644
--- a/include/geos/noding/FastNodingValidator.h
+++ b/include/geos/noding/FastNodingValidator.h
@@ -19,7 +19,7 @@
 #ifndef GEOS_NODING_FASTNODINGVALIDATOR_H
 #define GEOS_NODING_FASTNODINGVALIDATOR_H
 
-#include <geos/noding/SingleInteriorIntersectionFinder.h> // for composition
+#include <geos/noding/NodingIntersectionFinder.h> // for composition
 #include <geos/algorithm/LineIntersector.h> // for composition
 
 #include <memory>
@@ -39,16 +39,23 @@ namespace noding { // geos.noding
 /** \brief
  * Validates that a collection of {@link SegmentString}s is correctly noded.
  *
- * Uses indexes to improve performance.
- * Does NOT check a-b-a collapse situations.
- * Also does not check for endpt-interior vertex intersections.
- * This should not be a problem, since the noders should be
- * able to compute intersections between vertices correctly.
- * User may either test the valid condition, or request that a
- * {@link TopologyException}
- * be thrown.
+ * Indexing is used to improve performance.
+ * By default validation stops after a single
+ * non-noded intersection is detected.
+ * Alternatively, it can be requested to detect all intersections
+ * by using {@link #setFindAllIntersections(boolean)}.
+ *
+* The validator does not check for topology collapse situations
+ * (e.g. where two segment strings are fully co-incident).
+ *
+ * The validator checks for the following situations which indicated incorrect noding:
+ *
+ * - Proper intersections between segments (i.e. the intersection is interior to both segments)
+ * - Intersections at an interior vertex (i.e. with an endpoint or another interior vertex)
+ *
+ * The client may either test the {@link #isValid()} condition,
+ * or request that a suitable {@link TopologyException} be thrown.
  *
- * @version 1.7
  */
 class FastNodingValidator
 {
@@ -98,7 +105,7 @@ private:
 
 	std::vector<noding::SegmentString*>& segStrings;
 
-	std::unique_ptr<SingleInteriorIntersectionFinder> segInt;
+	std::unique_ptr<NodingIntersectionFinder> segInt;
 
 	bool isValidVar;
 
diff --git a/include/geos/noding/Makefile.am b/include/geos/noding/Makefile.am
index f1814fe..30cf761 100644
--- a/include/geos/noding/Makefile.am
+++ b/include/geos/noding/Makefile.am
@@ -8,31 +8,31 @@ EXTRA_DIST =
 geosdir = $(includedir)/geos/noding
 
 geos_HEADERS = \
-    BasicSegmentString.h \
-    FastNodingValidator.h \
-    FastSegmentSetIntersectionFinder.h \
-    GeometryNoder.h \
-    IntersectionAdder.h \
-    IntersectionFinderAdder.h \
-    IteratedNoder.h \
-    MCIndexNoder.h \
-    MCIndexNoder.inl \
-    MCIndexSegmentSetMutualIntersector.h \
-    NodableSegmentString.h \
-    NodedSegmentString.h \
-    Noder.h \
-    NodingValidator.h \
-    Octant.h \
-    OrientedCoordinateArray.h \
-    ScaledNoder.h \
-    SegmentIntersectionDetector.h \
-    SegmentIntersector.h \
-    SegmentNode.h \
-    SegmentNodeList.h \
-    SegmentPointComparator.h \
-    SegmentSetMutualIntersector.h \
-    SegmentString.h \
-    SegmentStringUtil.h \
-    SimpleNoder.h \
-    SingleInteriorIntersectionFinder.h \
-    SinglePassNoder.h
+	BasicSegmentString.h \
+	FastNodingValidator.h \
+	FastSegmentSetIntersectionFinder.h \
+	GeometryNoder.h \
+	IntersectionAdder.h \
+	IntersectionFinderAdder.h \
+	IteratedNoder.h \
+	MCIndexNoder.h \
+	MCIndexNoder.inl \
+	MCIndexSegmentSetMutualIntersector.h \
+	NodableSegmentString.h \
+	NodedSegmentString.h \
+	Noder.h \
+	NodingValidator.h \
+	Octant.h \
+	OrientedCoordinateArray.h \
+	ScaledNoder.h \
+	SegmentIntersectionDetector.h \
+	SegmentIntersector.h \
+	SegmentNode.h \
+	SegmentNodeList.h \
+	SegmentPointComparator.h \
+	SegmentSetMutualIntersector.h \
+	SegmentString.h \
+	SegmentStringUtil.h \
+	SimpleNoder.h \
+	NodingIntersectionFinder.h \
+	SinglePassNoder.h
diff --git a/include/geos/noding/NodingIntersectionFinder.h b/include/geos/noding/NodingIntersectionFinder.h
new file mode 100644
index 0000000..c7d2f26
--- /dev/null
+++ b/include/geos/noding/NodingIntersectionFinder.h
@@ -0,0 +1,220 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2006      Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************/
+
+#ifndef GEOS_NODING_NODINGINTERSECTIONFINDER_H
+#define GEOS_NODING_NODINGINTERSECTIONFINDER_H
+
+#include <geos/noding/SegmentIntersector.h> // for inheritance
+#include <geos/geom/Coordinate.h> // for composition
+
+#include <vector>
+
+// Forward declarations
+namespace geos {
+	namespace algorithm {
+		class LineIntersector;
+	}
+	namespace noding {
+		class SegmentString;
+	}
+}
+
+namespace geos {
+namespace noding { // geos.noding
+
+/**
+ * \brief Finds non-noded intersections in a set of {@link SegmentString}s, if any exist.
+ *
+ * Non-noded intersections include:
+ *
+ * - intersections which lie in the interior of a segment
+ * - intersections at a vertex in the interior of a {@link SegmentString}
+ * (e.g. with a segment string endpoint or other interior vertex)
+ *
+ * @version 1.7
+ */
+class NodingIntersectionFinder: public SegmentIntersector
+{
+
+public:
+
+	/** \brief
+	 * Creates an intersection finder which finds an interior intersection
+	 * if one exists
+	 *
+	 * @param li the LineIntersector to use
+	 */
+	NodingIntersectionFinder(algorithm::LineIntersector& newLi)
+		:
+		li(newLi),
+		interiorIntersection(geom::Coordinate::getNull()),
+        intersectionCount(0),
+        isCheckEndSegmentsOnly(false),
+        findAllIntersections(false),
+        keepIntersections(true)
+	{
+	}
+
+	/** \brief
+	 * Tests whether an intersection was found.
+	 *
+	 * @return true if an intersection was found
+	 */
+	bool hasIntersection() const
+	{
+		return !interiorIntersection.isNull();
+	}
+
+	/** \brief
+	 * Gets the computed location of the intersection.
+	 * Due to round-off, the location may not be exact.
+	 *
+	 * @return the coordinate for the intersection location
+	 */
+	const geom::Coordinate& getInteriorIntersection() const
+	{
+		return interiorIntersection;
+	}
+
+    /**
+    * Gets the count of intersections found.
+    *
+    * @return the intersection count
+    */
+    size_t count() const
+    {
+        return intersectionCount;
+    }
+
+    /**
+    * Sets whether only end segments should be tested for interior intersection.
+    * This is a performance optimization that may be used if
+    * the segments have been previously noded by an appropriate algorithm.
+    * It may be known that any potential noding failures will occur only in
+    * end segments.
+    *
+    * @param isCheckEndSegmentsOnly whether to test only end segments
+    */
+    void setCheckEndSegmentsOnly(bool isCESO)
+    {
+        isCheckEndSegmentsOnly = isCESO;
+    }
+
+
+    /**
+    * Sets whether all intersections should be computed.
+    * When this is <code>false</code> (the default value)
+    * the value of {@link #isDone()} is <code>true</code> after the first intersection is found.
+    * <p>
+    * Default is <code>false</code>.
+    *
+    * @param findAllIntersections whether all intersections should be computed
+    */
+    void setFindAllIntersections(bool fAI)
+    {
+        findAllIntersections = fAI;
+    }
+
+	/** \brief
+	 * Gets the endpoints of the intersecting segments.
+	 *
+	 * @return an array of the segment endpoints (p00, p01, p10, p11)
+	 */
+	const std::vector<geom::Coordinate>& getIntersectionSegments() const
+	{
+		return intSegments;
+	}
+
+	/** \brief
+	 * This method is called by clients
+	 * of the {@link SegmentIntersector} class to process
+	 * intersections for two segments of the {@link SegmentStrings} being intersected.
+	 *
+	 * Note that some clients (such as {@link MonotoneChain}s) may optimize away
+	 * this call for segment pairs which they have determined do not intersect
+	 * (e.g. by an disjoint envelope test).
+	 */
+	void processIntersections(
+		SegmentString* e0,  size_t segIndex0,
+		SegmentString* e1,  size_t segIndex1) override;
+
+	bool isDone() const override
+	{
+		return !interiorIntersection.isNull();
+	}
+
+private:
+	algorithm::LineIntersector& li;
+	geom::Coordinate interiorIntersection;
+    size_t intersectionCount;
+    bool isCheckEndSegmentsOnly;
+    bool findAllIntersections;
+    bool keepIntersections;
+	std::vector<geom::Coordinate> intSegments;
+
+    // Declare type as noncopyable
+    NodingIntersectionFinder(const NodingIntersectionFinder& other) = delete;
+    NodingIntersectionFinder& operator=(const NodingIntersectionFinder& rhs) = delete;
+
+    /**
+    * Tests if two vertices with at least one in a segmentString interior
+    * are equal.
+    *
+    * @param p0 a segment vertex
+    * @param p1 a segment vertex
+    * @param isEnd0 true if vertex is a segmentString endpoint
+    * @param isEnd1 true if vertex is a segmentString endpoint
+    * @return true if an intersection is found
+    */
+    bool isInteriorVertexIntersection(
+        const geom::Coordinate& p0, const geom::Coordinate& p1,
+        bool isEnd0, bool isEnd1);
+
+    /**
+    * Tests if an intersection occurs between a segmentString interior vertex and another vertex.
+    * Note that intersections between two endpoint vertices are valid noding,
+    * and are not flagged.
+    *
+    * @param p00 a segment vertex
+    * @param p01 a segment vertex
+    * @param p10 a segment vertex
+    * @param p11 a segment vertex
+    * @param isEnd00 true if vertex is a segmentString endpoint
+    * @param isEnd01 true if vertex is a segmentString endpoint
+    * @param isEnd10 true if vertex is a segmentString endpoint
+    * @param isEnd11 true if vertex is a segmentString endpoint
+    * @return true if an intersection is found
+    */
+    bool isInteriorVertexIntersection(
+        const geom::Coordinate& p00, const geom::Coordinate& p01,
+        const geom::Coordinate& p10, const geom::Coordinate& p11,
+        bool isEnd00, bool isEnd01, bool isEnd10, bool isEnd11);
+
+    /**
+    * Tests whether a segment in a {@link SegmentString} is an end segment.
+    * (either the first or last).
+    *
+    * @param segStr a segment string
+    * @param index the index of a segment in the segment string
+    * @return true if the segment is an end segment
+    */
+    bool isEndSegment(const SegmentString* segStr, size_t index);
+
+
+};
+
+} // namespace geos.noding
+} // namespace geos
+
+#endif // GEOS_NODING_NODINGINTERSECTIONFINDER_H
diff --git a/include/geos/noding/SingleInteriorIntersectionFinder.h b/include/geos/noding/SingleInteriorIntersectionFinder.h
deleted file mode 100644
index 8a3c6c4..0000000
--- a/include/geos/noding/SingleInteriorIntersectionFinder.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/**********************************************************************
- *
- * GEOS - Geometry Engine Open Source
- * http://geos.osgeo.org
- *
- * Copyright (C) 2006      Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU Lesser General Public Licence as published
- * by the Free Software Foundation.
- * See the COPYING file for more information.
- *
- **********************************************************************/
-
-#ifndef GEOS_NODING_SINGLEINTERIORINTERSECTIONFINDER_H
-#define GEOS_NODING_SINGLEINTERIORINTERSECTIONFINDER_H
-
-#include <geos/noding/SegmentIntersector.h> // for inheritance
-#include <geos/geom/Coordinate.h> // for composition
-
-#include <vector>
-
-// Forward declarations
-namespace geos {
-	namespace algorithm {
-		class LineIntersector;
-	}
-	namespace noding {
-		class SegmentString;
-	}
-}
-
-namespace geos {
-namespace noding { // geos.noding
-
-/**
- * \brief
- * Finds an interior intersection in a set of SegmentString,
- * if one exists.  Only the first intersection found is reported.
- *
- * @version 1.7
- */
-class SingleInteriorIntersectionFinder: public SegmentIntersector
-{
-
-public:
-
-	/** \brief
-	 * Creates an intersection finder which finds an interior intersection
-	 * if one exists
-	 *
-	 * @param li the LineIntersector to use
-	 */
-	SingleInteriorIntersectionFinder(algorithm::LineIntersector& newLi)
-		:
-		li(newLi),
-		interiorIntersection(geom::Coordinate::getNull())
-	{
-	}
-
-	/** \brief
-	 * Tests whether an intersection was found.
-	 *
-	 * @return true if an intersection was found
-	 */
-	bool hasIntersection() const
-	{
-		return !interiorIntersection.isNull();
-	}
-
-	/** \brief
-	 * Gets the computed location of the intersection.
-	 * Due to round-off, the location may not be exact.
-	 *
-	 * @return the coordinate for the intersection location
-	 */
-	const geom::Coordinate& getInteriorIntersection() const
-	{
-		return interiorIntersection;
-	}
-
-	/** \brief
-	 * Gets the endpoints of the intersecting segments.
-	 *
-	 * @return an array of the segment endpoints (p00, p01, p10, p11)
-	 */
-	const std::vector<geom::Coordinate>& getIntersectionSegments() const
-	{
-		return intSegments;
-	}
-
-	/** \brief
-	 * This method is called by clients
-	 * of the {@link SegmentIntersector} class to process
-	 * intersections for two segments of the {@link SegmentStrings} being intersected.
-	 *
-	 * Note that some clients (such as {@link MonotoneChain}s) may optimize away
-	 * this call for segment pairs which they have determined do not intersect
-	 * (e.g. by an disjoint envelope test).
-	 */
-	void processIntersections(
-		SegmentString* e0,  size_t segIndex0,
-		SegmentString* e1,  size_t segIndex1) override;
-
-	bool isDone() const override
-	{
-		return !interiorIntersection.isNull();
-	}
-
-private:
-	algorithm::LineIntersector& li;
-	geom::Coordinate interiorIntersection;
-	std::vector<geom::Coordinate> intSegments;
-
-    // Declare type as noncopyable
-    SingleInteriorIntersectionFinder(const SingleInteriorIntersectionFinder& other) = delete;
-    SingleInteriorIntersectionFinder& operator=(const SingleInteriorIntersectionFinder& rhs) = delete;
-};
-
-} // namespace geos.noding
-} // namespace geos
-
-#endif // GEOS_NODING_SINGLEINTERIORINTERSECTIONFINDER_H
diff --git a/src/Makefile.vc b/src/Makefile.vc
index f67802d..28beef0 100644
--- a/src/Makefile.vc
+++ b/src/Makefile.vc
@@ -187,7 +187,7 @@ OBJ = \
 	noding\SegmentString.$(EXT) \
 	noding\SegmentStringUtil.$(EXT) \
 	noding\SimpleNoder.$(EXT) \
-	noding\SingleInteriorIntersectionFinder.$(EXT) \
+	noding\NodingIntersectionFinder.$(EXT) \
 	noding\snapround\HotPixel.$(EXT) \
 	noding\snapround\MCIndexPointSnapper.$(EXT) \
 	noding\snapround\MCIndexSnapRounder.$(EXT) \
diff --git a/src/noding/FastNodingValidator.cpp b/src/noding/FastNodingValidator.cpp
index 69223bf..eb6e3f9 100644
--- a/src/noding/FastNodingValidator.cpp
+++ b/src/noding/FastNodingValidator.cpp
@@ -18,7 +18,7 @@
 
 #include <geos/noding/FastNodingValidator.h>
 #include <geos/noding/MCIndexNoder.h> // for checkInteriorIntersections()
-#include <geos/noding/SingleInteriorIntersectionFinder.h>
+#include <geos/noding/NodingIntersectionFinder.h>
 #include <geos/util/TopologyException.h> // for checkValid()
 #include <geos/geom/Coordinate.h>
 #include <geos/io/WKTWriter.h> // for getErrorMessage()
@@ -33,45 +33,45 @@ namespace noding { // geos.noding
 void
 FastNodingValidator::checkInteriorIntersections()
 {
-	isValidVar = true;
-	segInt.reset(new SingleInteriorIntersectionFinder(li));
-	MCIndexNoder noder;
-	noder.setSegmentIntersector(segInt.get());
-	noder.computeNodes(&segStrings);
-	if (segInt->hasIntersection()) {
-		isValidVar = false;
-		return;
-	}
+    isValidVar = true;
+    segInt.reset(new NodingIntersectionFinder(li));
+    MCIndexNoder noder;
+    noder.setSegmentIntersector(segInt.get());
+    noder.computeNodes(&segStrings);
+    if (segInt->hasIntersection()) {
+        isValidVar = false;
+        return;
+    }
 }
 
 /*public*/
 std::string
 FastNodingValidator::getErrorMessage() const
 {
-	using geos::io::WKTWriter;
-	using geos::geom::Coordinate;
+    using geos::io::WKTWriter;
+    using geos::geom::Coordinate;
 
-	if (isValidVar) return std::string("no intersections found");
+    if (isValidVar) return std::string("no intersections found");
 
-	//return std::string("found non-noded intersection etc etc");
+    //return std::string("found non-noded intersection etc etc");
 
-	const std::vector<Coordinate>& intSegs = segInt->getIntersectionSegments();
-	assert(intSegs.size() == 4);
-	return "found non-noded intersection between "
-		+ WKTWriter::toLineString(intSegs[0], intSegs[1])
-		+ " and "
-		+ WKTWriter::toLineString(intSegs[2], intSegs[3]);
+    const std::vector<Coordinate>& intSegs = segInt->getIntersectionSegments();
+    assert(intSegs.size() == 4);
+    return "found non-noded intersection between "
+        + WKTWriter::toLineString(intSegs[0], intSegs[1])
+        + " and "
+        + WKTWriter::toLineString(intSegs[2], intSegs[3]);
 }
 
 void
 FastNodingValidator::checkValid()
 {
-	execute();
-	if (! isValidVar)
-	{
-		//std::cerr << "Not valid: " << getErrorMessage() << " interior intersection: " << segInt->getInteriorIntersection() << std::endl;
-		throw util::TopologyException(getErrorMessage(), segInt->getInteriorIntersection());
-	}
+    execute();
+    if (! isValidVar)
+    {
+        //std::cerr << "Not valid: " << getErrorMessage() << " interior intersection: " << segInt->getInteriorIntersection() << std::endl;
+        throw util::TopologyException(getErrorMessage(), segInt->getInteriorIntersection());
+    }
 }
 
 } // namespace geos.noding
diff --git a/src/noding/Makefile.am b/src/noding/Makefile.am
index 010adac..7bddb6b 100644
--- a/src/noding/Makefile.am
+++ b/src/noding/Makefile.am
@@ -28,6 +28,6 @@ libnoding_la_SOURCES = \
 	SegmentString.cpp \
 	SegmentStringUtil.cpp \
 	SimpleNoder.cpp \
-	SingleInteriorIntersectionFinder.cpp
+	NodingIntersectionFinder.cpp
 
 libnoding_la_LIBADD = snapround/libsnapround.la
diff --git a/src/noding/NodingIntersectionFinder.cpp b/src/noding/NodingIntersectionFinder.cpp
new file mode 100644
index 0000000..98c10c4
--- /dev/null
+++ b/src/noding/NodingIntersectionFinder.cpp
@@ -0,0 +1,139 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2006 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************
+ *
+ * Last port: noding/NodingIntersectionFinder.java rev. ??? (JTS-1.8)
+ *
+ **********************************************************************/
+
+#include <geos/noding/NodingIntersectionFinder.h>
+#include <geos/noding/SegmentString.h>
+#include <geos/algorithm/LineIntersector.h>
+#include <geos/geom/Coordinate.h>
+
+#include <cstdlib>
+
+using namespace geos::geom;
+
+namespace geos {
+namespace noding { // geos.noding
+
+/* private */
+bool
+NodingIntersectionFinder::isEndSegment(const SegmentString* segStr, size_t index)
+{
+    if (index == 0) return true;
+    if (index >= segStr->size() - 2) return true;
+    return false;
+}
+
+/* private */
+bool
+NodingIntersectionFinder::isInteriorVertexIntersection(
+    const Coordinate& p0, const Coordinate& p1,
+    bool isEnd0, bool isEnd1)
+{
+    // Intersections between endpoints are valid nodes, so not reported
+    if (isEnd0 && isEnd1) return false;
+
+    if (p0.equals2D(p1)) return true;
+
+    return false;
+}
+
+
+/* private */
+bool
+NodingIntersectionFinder::isInteriorVertexIntersection(
+    const Coordinate& p00, const Coordinate& p01, const Coordinate& p10, const Coordinate& p11,
+    bool isEnd00, bool isEnd01, bool isEnd10, bool isEnd11)
+{
+    if (isInteriorVertexIntersection(p00, p10, isEnd00, isEnd10)) return true;
+    if (isInteriorVertexIntersection(p00, p11, isEnd00, isEnd11)) return true;
+    if (isInteriorVertexIntersection(p01, p10, isEnd01, isEnd10)) return true;
+    if (isInteriorVertexIntersection(p01, p11, isEnd01, isEnd11)) return true;
+    return false;
+}
+
+
+/* public (override) */
+void
+NodingIntersectionFinder::processIntersections(
+	SegmentString* e0,  size_t segIndex0,
+	SegmentString* e1,  size_t segIndex1)
+{
+	using geos::geom::Coordinate;
+
+	// short-circuit if intersection already found
+	if (!findAllIntersections && hasIntersection())
+		return;
+
+	// don't bother intersecting a segment with itself
+    bool isSameSegString = e0 == e1;
+    bool isSameSegment = isSameSegString && segIndex0 == segIndex1;
+	if (isSameSegment) return;
+
+    /**
+     * If enabled, only test end segments (on either segString).
+     */
+    if (isCheckEndSegmentsOnly)
+    {
+        bool isEndSegPresent =
+            isEndSegment(e0, segIndex0) ||
+            isEndSegment(e1, segIndex1);
+        if (! isEndSegPresent)
+            return;
+    }
+
+	const Coordinate& p00 = e0->getCoordinate(segIndex0);
+	const Coordinate& p01 = e0->getCoordinate(segIndex0 + 1);
+	const Coordinate& p10 = e1->getCoordinate(segIndex1);
+	const Coordinate& p11 = e1->getCoordinate(segIndex1 + 1);
+
+    bool isEnd00 = segIndex0 == 0;
+    bool isEnd01 = segIndex0 + 2 == e0->size();
+    bool isEnd10 = segIndex1 == 0;
+    bool isEnd11 = segIndex1 + 2 == e1->size();
+
+	li.computeIntersection(p00, p01, p10, p11);
+    /**
+     * Check for an intersection in the interior of a segment
+     */
+    bool isInteriorInt = li.hasIntersection() && li.isInteriorIntersection();
+    /**
+     * Check for an intersection between two vertices which are not both endpoints.
+     */
+    int segDiff = segIndex1 - segIndex0;
+    bool isAdjacentSegment = isSameSegString && std::abs(segDiff) <= 1;
+    bool isInteriorVertexInt = (!isAdjacentSegment) &&
+        isInteriorVertexIntersection(p00, p01, p10, p11, isEnd00, isEnd01, isEnd10, isEnd11);
+
+    if (isInteriorInt || isInteriorVertexInt)
+    {
+        // found an intersection!
+        // TODO: record endpoint intersection(s)
+        // Coordinate intSegments[4];
+        // intSegments[0] = p00;
+        // intSegments[1] = p01;
+        // intSegments[2] = p10;
+        // intSegments[3] = p11;
+
+        interiorIntersection = li.getIntersection(0);
+        // if (keepIntersections) intersections.add(interiorIntersection);
+        intersectionCount++;
+    }
+}
+
+
+} // namespace geos.noding
+} // namespace geos
diff --git a/src/noding/SingleInteriorIntersectionFinder.cpp b/src/noding/SingleInteriorIntersectionFinder.cpp
deleted file mode 100644
index e735ea0..0000000
--- a/src/noding/SingleInteriorIntersectionFinder.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/**********************************************************************
- *
- * GEOS - Geometry Engine Open Source
- * http://geos.osgeo.org
- *
- * Copyright (C) 2006 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU Lesser General Licence as published
- * by the Free Software Foundation.
- * See the COPYING file for more information.
- *
- **********************************************************************
- *
- * Last port: noding/SingleInteriorIntersectionFinder.java rev. ??? (JTS-1.8)
- *
- **********************************************************************/
-
-#include <geos/noding/SingleInteriorIntersectionFinder.h>
-#include <geos/noding/SegmentString.h>
-#include <geos/algorithm/LineIntersector.h>
-#include <geos/geom/Coordinate.h>
-
-using namespace geos::geom;
-
-namespace geos {
-namespace noding { // geos.noding
-
-/*public (override) */
-void
-SingleInteriorIntersectionFinder::processIntersections(
-	SegmentString* e0,  size_t segIndex0,
-	SegmentString* e1,  size_t segIndex1)
-{
-	using geos::geom::Coordinate;
-
-	// short-circuit if intersection already found
-	if (hasIntersection())
-		return;
-
-	// don't bother intersecting a segment with itself
-	if (e0 == e1 && segIndex0 == segIndex1) return;
-
-	const Coordinate& p00 = e0->getCoordinate(segIndex0);
-	const Coordinate& p01 = e0->getCoordinate(segIndex0 + 1);
-	const Coordinate& p10 = e1->getCoordinate(segIndex1);
-	const Coordinate& p11 = e1->getCoordinate(segIndex1 + 1);
-
-	li.computeIntersection(p00, p01, p10, p11);
-//if (li.hasIntersection() && li.isProper()) Debug.println(li);
-
-	if (li.hasIntersection())
-	{
-		if (li.isInteriorIntersection())
-		{
-			intSegments.resize(4);
-			intSegments[0] = p00;
-			intSegments[1] = p01;
-			intSegments[2] = p10;
-			intSegments[3] = p11;
-
-			interiorIntersection = li.getIntersection(0);
-		}
-	}
-}
-
-
-} // namespace geos.noding
-} // namespace geos

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

Summary of changes:
 include/geos/noding/FastNodingValidator.h          |  29 +--
 include/geos/noding/Makefile.am                    |  56 +++---
 include/geos/noding/NodingIntersectionFinder.h     | 220 +++++++++++++++++++++
 .../geos/noding/SingleInteriorIntersectionFinder.h | 123 ------------
 src/Makefile.vc                                    |   2 +-
 src/noding/FastNodingValidator.cpp                 |  52 ++---
 src/noding/Makefile.am                             |   2 +-
 src/noding/NodingIntersectionFinder.cpp            | 138 +++++++++++++
 src/noding/SingleInteriorIntersectionFinder.cpp    |  69 -------
 tests/xmltester/CMakeLists.txt                     |   1 +
 tests/xmltester/Makefile.am                        |   1 +
 tests/xmltester/tests/ticket/bug838.xml            |  23 +++
 12 files changed, 457 insertions(+), 259 deletions(-)
 create mode 100644 include/geos/noding/NodingIntersectionFinder.h
 delete mode 100644 include/geos/noding/SingleInteriorIntersectionFinder.h
 create mode 100644 src/noding/NodingIntersectionFinder.cpp
 delete mode 100644 src/noding/SingleInteriorIntersectionFinder.cpp
 create mode 100644 tests/xmltester/tests/ticket/bug838.xml


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list