[geos-commits] r3087 - in trunk: src/operation/buffer src/operation/valid tests/xmltester/tests/general

svn_geos at osgeo.org svn_geos at osgeo.org
Mon Jul 26 18:21:07 EDT 2010


Author: swongu
Date: 2010-07-26 22:21:07 +0000 (Mon, 26 Jul 2010)
New Revision: 3087

Modified:
   trunk/src/operation/buffer/BufferBuilder.cpp
   trunk/src/operation/valid/ConnectedInteriorTester.cpp
   trunk/src/operation/valid/IsValidOp.cpp
   trunk/tests/xmltester/tests/general/TestValid2.xml
Log:
Fixed a bufferLineSingleSided crash and fixed OGC validation on rare cases. (#364)

Modified: trunk/src/operation/buffer/BufferBuilder.cpp
===================================================================
--- trunk/src/operation/buffer/BufferBuilder.cpp	2010-07-15 15:54:52 UTC (rev 3086)
+++ trunk/src/operation/buffer/BufferBuilder.cpp	2010-07-26 22:21:07 UTC (rev 3087)
@@ -7,6 +7,7 @@
  * Copyright (C) 2009 Sandro Santilli <strk at keybit.net>
  * Copyright (C) 2005-2007 Refractions Research Inc.
  * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ * Copyright (C) 2008-2010 Safe Software Inc.
  *
  * This is free software; you can redistribute and/or modify it under
  * the terms of the GNU Lesser General Public Licence as published
@@ -314,14 +315,22 @@
    geomFact->destroyGeometry( singleSided );
    geomFact->destroyGeometry( intersectedLines );
 
-   if ( mergedLinesGeom->size() > 1 ) return geomFact->createMultiLineString( mergedLinesGeom );
-   else
+   if ( mergedLinesGeom->size() > 1 )
+   {      
+      return geomFact->createMultiLineString( mergedLinesGeom );
+   }
+   else if ( mergedLinesGeom->size() == 1 )
    {
-      // Must be a single line
+
       Geometry* single = (*mergedLinesGeom)[0];
       delete mergedLinesGeom;
       return single;
    }
+   else
+   {
+      delete mergedLinesGeom;
+      return NULL;
+   }
 }
 
 /*public*/

Modified: trunk/src/operation/valid/ConnectedInteriorTester.cpp
===================================================================
--- trunk/src/operation/valid/ConnectedInteriorTester.cpp	2010-07-15 15:54:52 UTC (rev 3086)
+++ trunk/src/operation/valid/ConnectedInteriorTester.cpp	2010-07-26 22:21:07 UTC (rev 3087)
@@ -4,6 +4,7 @@
  * GEOS - Geometry Engine Open Source
  * http://geos.refractions.net
  *
+ * Copyright (C) 2007-2010 Safe Software Inc.
  * Copyright (C) 2005-2006 Refractions Research Inc.
  * Copyright (C) 2001-2002 Vivid Solutions Inc.
  *
@@ -259,6 +260,9 @@
 void
 ConnectedInteriorTester::visitInteriorRing(const LineString *ring, PlanarGraph &graph)
 {
+	// can't visit an empty ring
+	if(ring->isEmpty()) return;
+   
 	const CoordinateSequence *pts=ring->getCoordinatesRO();
 	const Coordinate& pt0=pts->getAt(0);
 

Modified: trunk/src/operation/valid/IsValidOp.cpp
===================================================================
--- trunk/src/operation/valid/IsValidOp.cpp	2010-07-15 15:54:52 UTC (rev 3086)
+++ trunk/src/operation/valid/IsValidOp.cpp	2010-07-26 22:21:07 UTC (rev 3087)
@@ -4,6 +4,7 @@
  * GEOS - Geometry Engine Open Source
  * http://geos.refractions.net
  *
+ * Copyright (C) 2010 Safe Software Inc.
  * Copyright (C) 2010 Sandro Santilli <strk at keybit.net>
  * Copyright (C) 2001-2002 Vivid Solutions Inc.
  * Copyright (C) 2005 Refractions Research Inc.
@@ -370,12 +371,34 @@
 
 	const LinearRing *shell=static_cast<const LinearRing*>(
 			p->getExteriorRing());
+         
+	int nholes = p->getNumInteriorRing();
 
+	if(shell->isEmpty())
+	{
+		for(int i=0; i<nholes; ++i)
+		{
+			assert(dynamic_cast<const LinearRing*>(
+				p->getInteriorRingN(i)));
+
+			const LinearRing *hole=static_cast<const LinearRing*>(
+				p->getInteriorRingN(i));
+
+			if(!hole->isEmpty())
+			{
+				validErr=new TopologyValidationError(
+					TopologyValidationError::eHoleOutsideShell);
+				return;
+			}
+		}
+		// all interiors also empty or none exist
+		return;
+	}
+
 	//SimplePointInRing pir(shell);
 	//SIRtreePointInRing pir(shell);
 	MCPointInRing pir(shell);
 
-	int nholes = p->getNumInteriorRing();
 	for(int i=0; i<nholes; ++i)
 	{
 		assert(dynamic_cast<const LinearRing*>(
@@ -421,6 +444,9 @@
 
 		const LinearRing *innerHole=static_cast<const LinearRing*>(
 				p->getInteriorRingN(i));
+   
+		//empty holes always pass
+		if(innerHole->isEmpty()) continue;
 
 		nestedTester.add(innerHole);
 	}
@@ -457,6 +483,8 @@
 			const Polygon *p2=static_cast<const Polygon *>(
 					mp->getGeometryN(j));
 
+			if (shell->isEmpty() || p2->isEmpty()) continue;
+
 			checkShellNotNested(shell, p2, graph);
 
 			if (validErr!=NULL) return;
@@ -619,7 +647,7 @@
 void
 IsValidOp::checkClosedRing(const LinearRing *ring)
 {
-	if ( ! ring->isClosed() )
+	if ( ! ring->isClosed() && ! ring->isEmpty() )
 	{
 		validErr = new TopologyValidationError(
 			TopologyValidationError::eRingNotClosed,

Modified: trunk/tests/xmltester/tests/general/TestValid2.xml
===================================================================
--- trunk/tests/xmltester/tests/general/TestValid2.xml	2010-07-15 15:54:52 UTC (rev 3086)
+++ trunk/tests/xmltester/tests/general/TestValid2.xml	2010-07-26 22:21:07 UTC (rev 3087)
@@ -5243,4 +5243,25 @@
   </a>
   <test> <op name="isValid" arg1="A"> true </op> </test>
 </case>
+<case>
+  <desc>Test 752</desc>
+  <a>
+    POLYGON ((180 260, 80 300, 40 180, 160 120, 180 260), EMPTY)
+  </a>
+  <test> <op name="isValid" arg1="A"> true </op> </test>
+</case>
+<case>
+  <desc>Test 753</desc>
+  <a>
+    POLYGON ((180 260, 80 300, 40 180, 160 120, 180 260), EMPTY, EMPTY)
+  </a>
+  <test> <op name="isValid" arg1="A"> true </op> </test>
+</case>
+<case>
+  <desc>Test 754</desc>
+  <a>
+    MultiPolygon(((10 10, 10 20, 20 20, 20 15, 10 10)),((60 60, 70 70, 80 60, 60 60 )), (EMPTY))
+  </a>
+  <test> <op name="isValid" arg1="A"> true </op> </test>
+</case>
 </run>



More information about the geos-commits mailing list