Commit 287b45da authored by Paul Ramsey's avatar Paul Ramsey

Invalid union result from valid polygon inputs

Closes #838
parent d137633a
Pipeline #45176025 passed with stage
in 19 minutes and 35 seconds
......@@ -8,6 +8,7 @@ Changes in 3.6.4
GEOSisValidDetail (#941, Dan Baston)
- Envelope constructor use strtod (#875)
- Polygon build failure in Overlay difference (#789 Paul Ramsey)
- Invalid union result from valid polygon inputs (#838)
Changes in 3.6.3
......
......@@ -7,12 +7,12 @@
*
* 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.
* by the Free Software Foundation.
* See the COPYING file for more information.
*
**********************************************************************
*
* Last port: noding/SingleInteriorIntersectionFinder.java rev. ??? (JTS-1.8)
* Last port: noding/SingleInteriorIntersectionFinder.java rev. 2019-01-28
*
**********************************************************************/
......@@ -23,6 +23,38 @@
using namespace geos::geom;
namespace { // anonymous
/* private in JTS */
bool isEndInteriorIntersection(
const Coordinate& p0, bool isEnd0,
const Coordinate& p1, bool isEnd1)
{
if (isEnd0 && isEnd1) return false;
if (p0.equals2D(p1)) {
return true;
}
return false;
}
/* public in JTS */
bool isEndInteriorIntersection(
const Coordinate& p00, const Coordinate& p01,
const Coordinate& p10, const Coordinate& p11,
bool isEnd00, bool isEnd01,
bool isEnd10, bool isEnd11)
{
if (isEndInteriorIntersection(p00, isEnd00, p10, isEnd10)) return true;
if (isEndInteriorIntersection(p00, isEnd00, p11, isEnd11)) return true;
if (isEndInteriorIntersection(p01, isEnd01, p10, isEnd10)) return true;
if (isEndInteriorIntersection(p01, isEnd01, p11, isEnd11)) return true;
return false;
}
} // anonymous namespace
namespace geos {
namespace noding { // geos.noding
......@@ -37,7 +69,7 @@ SingleInteriorIntersectionFinder::processIntersections(
// short-circuit if intersection already found
if (hasIntersection())
return;
// don't bother intersecting a segment with itself
if (e0 == e1 && segIndex0 == segIndex1) return;
......@@ -45,23 +77,29 @@ SingleInteriorIntersectionFinder::processIntersections(
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 == static_cast<int>(e0->size());
bool isEnd10 = segIndex1 == 0;
bool isEnd11 = segIndex1 + 2 == static_cast<int>(e1->size());
li.computeIntersection(p00, p01, p10, p11);
//if (li.hasIntersection() && li.isProper()) Debug.println(li);
bool isProperInteriorInt = li.hasIntersection() &&
li.isInteriorIntersection();
bool isEndInteriorInt = (e0 != e1) && isEndInteriorIntersection(
p00, p01, p10, p11, isEnd00, isEnd01, isEnd10, isEnd11);
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);
}
if (isProperInteriorInt || isEndInteriorInt) {
// found an intersection!
intSegments.resize(4);
intSegments[0] = p00;
intSegments[1] = p01;
intSegments[2] = p10;
intSegments[3] = p11;
interiorIntersection = li.getIntersection(0);
}
}
......
......@@ -60,6 +60,7 @@ if(GEOS_ENABLE_TESTS)
${XMLTESTS_DIR}/ticket/bug188.xml
${XMLTESTS_DIR}/ticket/bug244.xml
${XMLTESTS_DIR}/ticket/bug275.xml
${XMLTESTS_DIR}/ticket/bug838.xml
${XMLTESTS_DIR}/general/TestBoundary.xml
${XMLTESTS_DIR}/general/TestBuffer.xml
${XMLTESTS_DIR}/general/TestBufferMitredJoin.xml
......
......@@ -44,6 +44,7 @@ SAFE_XMLTESTS=$(srcdir)/tests/testLeaksBig.xml \
$(srcdir)/tests/ticket/bug615.xml \
$(srcdir)/tests/ticket/bug716.xml \
$(srcdir)/tests/ticket/bug837.xml \
$(srcdir)/tests/ticket/bug838.xml \
$(srcdir)/tests/general/TestBoundary.xml \
$(srcdir)/tests/general/TestBuffer.xml \
$(srcdir)/tests/general/TestBufferMitredJoin.xml \
......
<run>
<precisionModel type="FLOATING" />
<case>
<desc>
Union of two valid polygons resulting in an invalid geometry
See https://trac.osgeo.org/geos/ticket/838
</desc>
<a>
00000000060000000200000000030000000100000005412CD75B00000000413D8F0966666667412CD75933333333413D8F6D80000000412CD82166666667413D8F6E4CCCCCCD412CD82500000000413D8EA61999999A412CD75B00000000413D8F096666666700000000030000000100000005412CD82500000001413D8EA61999999A412CD82333333334413D8F0A33333333412CD8EB66666666413D8F0B19999999412CD8ED33333333413D8EA700000001412CD82500000001413D8EA61999999A
</a>
<b>
00000000030000000100000007412CD9D4D50CE8F7413D8EA7FBC39C12412CD8ED33333333413D8EA700000000412CD8EB66666667413D8F0B1999999A412CD82333333333413D8F0A33333333412CD82166666667413D8F6E4CCCCCCD412CD9B1CCCCCCCD413D8F701999999A412CD9D4D50CE8F7413D8EA7FBC39C12
</b>
<test>
<op name="union" arg1="A" arg2="B">
0103000000010000000A000000000000005BD72C4167666666098F3D413333333359D72C41000000806D8F3D416766666621D82C41CDCCCC4C6E8F3D41CDCCCCCCB1D92C419A999919708F3D41F7E80CD5D4D92C41129CC3FBA78E3D4133333333EDD82C4100000000A78E3D410100000025D82C419A999919A68E3D413333333323D82C41333333330A8F3D410000000025D82C419A999919A68E3D41000000005BD72C4167666666098F3D41
</op>
</test>
</case>
</run>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment