[geos-commits] r3749 - in trunk: . include/geos/algorithm src/algorithm src/geom tests/xmltester tests/xmltester/tests/general

svn_geos at osgeo.org svn_geos at osgeo.org
Mon Jan 14 08:15:37 PST 2013


Author: strk
Date: 2013-01-14 08:15:37 -0800 (Mon, 14 Jan 2013)
New Revision: 3749

Added:
   trunk/include/geos/algorithm/Centroid.h
   trunk/src/algorithm/Centroid.cpp
Modified:
   trunk/NEWS
   trunk/include/geos/algorithm/CentroidArea.h
   trunk/include/geos/algorithm/CentroidLine.h
   trunk/include/geos/algorithm/CentroidPoint.h
   trunk/include/geos/algorithm/Makefile.am
   trunk/src/algorithm/Makefile.am
   trunk/src/geom/Geometry.cpp
   trunk/tests/xmltester/XMLTester.cpp
   trunk/tests/xmltester/tests/general/TestCentroid.xml
Log:
Fix EMPTY return from single-point lines and zero-length polygons

This commit ports new Centroid class from JTS (#612)

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2013-01-14 11:16:01 UTC (rev 3748)
+++ trunk/NEWS	2013-01-14 16:15:37 UTC (rev 3749)
@@ -7,6 +7,7 @@
   - CAPI: GEOSNode (#496) - PHP: Geometry->node
   - GeometryPrecisionReducer class
   - BufferInputLineSimplifier header exposed (#548)
+  - New Centroid class supporting mixed geometry components (#612)
 - C++ API changes:
   - New noding::GeometryNoder class
   - Added BufferOp::setSingleSided 
@@ -15,7 +16,7 @@
   - Signature of most functions taking an IntersectionMatrix changed
     to take it by reference rather than pointer.
   - GraphComponent::label is now a Label value (from a pointer)
-  - NodedSegmentString takes ownership of CoordinateSequence now
+  -e NodedSegmentString takes ownership of CoordinateSenuence now
 - Bug fixes / improvements
   - Improve Buffer robustness by reducing input precision on topology
     exception (#605)
@@ -23,6 +24,8 @@
     by always using the lowest possible index value, and by trimming
     zero-length components from results (#323)
   - Fixed CMake configuration to set correct SOVERSION (current - age)
+  - Fix EMPTY return from single-point lines and zero-length polygons (#612)
+  
 
 Changes in 3.3.0
 2011-05-30

Added: trunk/include/geos/algorithm/Centroid.h
===================================================================
--- trunk/include/geos/algorithm/Centroid.h	                        (rev 0)
+++ trunk/include/geos/algorithm/Centroid.h	2013-01-14 16:15:37 UTC (rev 3749)
@@ -0,0 +1,157 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2013 Sandro Santilli <strk at keybit.net>
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: algorithm/Centroid.java r728 (JTS-0.13+)
+ *
+ **********************************************************************/
+
+#ifndef GEOS_ALGORITHM_CENTROID_H
+#define GEOS_ALGORITHM_CENTROID_H
+
+#include <geos/export.h>
+#include <geos/geom/Coordinate.h> // for composition
+#include <memory> // for std::auto_ptr
+
+// Forward declarations
+namespace geos {
+	namespace geom {
+		class Geometry;
+		class Polygon;
+		class CoordinateSequence;
+	}
+}
+
+
+namespace geos {
+namespace algorithm { // geos::algorithm
+
+/**
+ * Computes the centroid of a {@link Geometry} of any dimension.
+ * If the geometry is nomimally of higher dimension, but contains only components
+ * having a lower effective dimension (i.e. zero length or area),
+ * the centroid will be computed appropriately.
+ *
+ * <h2>Algorithm</h2>
+ * <ul>
+ * <li><b>Dimension = 2</b> - Based on the usual algorithm for calculating
+ * the centroid as a weighted sum of the centroids
+ * of a decomposition of the area into (possibly overlapping) triangles.
+ * The algorithm has been extended to handle holes and multi-polygons.
+ * See <code>http://www.faqs.org/faqs/graphics/algorithms-faq/</code>
+ * for further details of the basic approach.
+ * <li><b>Dimension = 1</b> - Computes the average of the midpoints
+ * of all line segments weighted by the segment length.
+ * <li><b>Dimension = 0</b> - Compute the average coordinate over all points.
+ * </ul>
+ * If the input geometries are empty, a
+ * <code>null</code> Coordinate is returned.
+ *
+ */
+class GEOS_DLL Centroid {
+
+public:
+
+  /**
+   * Computes the centroid point of a geometry.
+   *
+   * @param geom the geometry to use
+   * @param cent will be set to the centroid point, if any
+   *
+   * @return true if a centroid could be computed,
+   *         false otherwise (empty geom)
+   */
+  static bool getCentroid(const geom::Geometry& geom, geom::Coordinate& cent);
+
+  /**
+   * Creates a new instance for computing the centroid of a geometry
+   */
+  Centroid(const geom::Geometry& geom)
+    :
+    areasum2(0.0),
+    totalLength(0.0),
+    ptCount(0)
+  {
+    add(geom);
+  }
+
+  /**
+   * Gets the computed centroid.
+   *
+   * @param cent will be set to the centroid point, if any
+   *
+   * @return true if a centroid could be computed,
+   *         false otherwise (empty geom)
+   */
+  bool getCentroid(geom::Coordinate& cent) const;
+
+private:
+
+  std::auto_ptr<geom::Coordinate> areaBasePt;
+  geom::Coordinate triangleCent3;
+  geom::Coordinate cg3;
+  geom::Coordinate lineCentSum;
+  geom::Coordinate ptCentSum;
+  double areasum2;
+  double totalLength;
+  int ptCount;
+  
+  /**
+   * Adds a Geometry to the centroid total.
+   *
+   * @param geom the geometry to add
+   */
+  void add(const geom::Geometry& geom);
+  
+  void setBasePoint(const geom::Coordinate& basePt);
+
+  void add(const geom::Polygon& poly);
+
+  void addShell(const geom::CoordinateSequence& pts);
+
+  void addHole(const geom::CoordinateSequence& pts);
+
+  void addTriangle(const geom::Coordinate& p0, const geom::Coordinate& p1, const geom::Coordinate& p2, bool isPositiveArea);
+
+  /**
+   * Computes three times the centroid of the triangle p1-p2-p3.
+   * The factor of 3 is
+   * left in to permit division to be avoided until later.
+   */
+  static void centroid3(const geom::Coordinate& p1, const geom::Coordinate& p2, const geom::Coordinate& p3, geom::Coordinate& c );
+
+  /**
+   * Returns twice the signed area of the triangle p1-p2-p3.
+   * The area is positive if the triangle is oriented CCW, and negative if CW.
+   */
+  static double area2(const geom::Coordinate& p1, const geom::Coordinate& p2, const geom::Coordinate& p3 );
+
+  /**
+   * Adds the line segments defined by an array of coordinates
+   * to the linear centroid accumulators.
+   *
+   * @param pts an array of {@link Coordinate}s
+   */
+  void addLineSegments(const geom::CoordinateSequence& pts);
+
+  /**
+   * Adds a point to the point centroid accumulator.
+   * @param pt a {@link Coordinate}
+   */
+  void addPoint(const geom::Coordinate& pt);
+};
+
+} // namespace geos::algorithm
+} // namespace geos
+
+#endif // GEOS_ALGORITHM_CENTROID_H

Modified: trunk/include/geos/algorithm/CentroidArea.h
===================================================================
--- trunk/include/geos/algorithm/CentroidArea.h	2013-01-14 11:16:01 UTC (rev 3748)
+++ trunk/include/geos/algorithm/CentroidArea.h	2013-01-14 16:15:37 UTC (rev 3749)
@@ -53,6 +53,9 @@
  * The code has also be extended to handle degenerate (zero-area) polygons.
  * In this case, the centroid of the line segments in the polygon
  * will be returned.
+ *
+ * @deprecated use Centroid instead
+ *
  */
 class GEOS_DLL CentroidArea {
 

Modified: trunk/include/geos/algorithm/CentroidLine.h
===================================================================
--- trunk/include/geos/algorithm/CentroidLine.h	2013-01-14 11:16:01 UTC (rev 3748)
+++ trunk/include/geos/algorithm/CentroidLine.h	2013-01-14 16:15:37 UTC (rev 3749)
@@ -31,6 +31,7 @@
 namespace geos {
 namespace algorithm { // geos::algorithm
 
+/// @deprecated use Centroid instead
 class GEOS_DLL CentroidLine {
 private:
 

Modified: trunk/include/geos/algorithm/CentroidPoint.h
===================================================================
--- trunk/include/geos/algorithm/CentroidPoint.h	2013-01-14 11:16:01 UTC (rev 3748)
+++ trunk/include/geos/algorithm/CentroidPoint.h	2013-01-14 16:15:37 UTC (rev 3749)
@@ -30,6 +30,7 @@
 namespace geos {
 namespace algorithm { // geos::algorithm
 
+/// @deprecated use Centroid instead
 class GEOS_DLL CentroidPoint {
 
 private:

Modified: trunk/include/geos/algorithm/Makefile.am
===================================================================
--- trunk/include/geos/algorithm/Makefile.am	2013-01-14 11:16:01 UTC (rev 3748)
+++ trunk/include/geos/algorithm/Makefile.am	2013-01-14 16:15:37 UTC (rev 3749)
@@ -13,6 +13,7 @@
     Angle.h \
     BoundaryNodeRule.h \
     CentralEndpointIntersector.h \
+    Centroid.h \
     CentroidArea.h \
     CentroidLine.h \
     CentroidPoint.h \

Added: trunk/src/algorithm/Centroid.cpp
===================================================================
--- trunk/src/algorithm/Centroid.cpp	                        (rev 0)
+++ trunk/src/algorithm/Centroid.cpp	2013-01-14 16:15:37 UTC (rev 3749)
@@ -0,0 +1,194 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2013 Sandro Santilli <strk at keybit.net>
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: algorithm/Centroid.java r728 (JTS-0.13+)
+ *
+ **********************************************************************/
+
+#include <geos/algorithm/Centroid.h>
+#include <geos/algorithm/CGAlgorithms.h>
+#include <geos/geom/CoordinateSequence.h>
+#include <geos/geom/Geometry.h>
+#include <geos/geom/Point.h>
+#include <geos/geom/Polygon.h>
+#include <geos/geom/GeometryCollection.h>
+#include <geos/geom/LineString.h>
+
+#include <cmath> // for std::abs
+
+using namespace geos::geom;
+
+namespace geos {
+namespace algorithm { // geos.algorithm
+
+/* static public */
+bool
+Centroid::getCentroid(const Geometry& geom, Coordinate& pt)
+{
+  Centroid cent(geom);
+  return cent.getCentroid(pt);
+}
+
+/* public */
+bool
+Centroid::getCentroid(Coordinate& cent) const
+{
+  if (std::abs(areasum2) > 0.0) {
+    cent.x = cg3.x / 3 / areasum2;
+    cent.y = cg3.y / 3 / areasum2;
+  }
+  else if (totalLength > 0.0) {
+    // if polygon was degenerate, compute linear centroid instead
+    cent.x = lineCentSum.x / totalLength;
+    cent.y = lineCentSum.y / totalLength;
+  }
+  else if (ptCount > 0){
+    cent.x = ptCentSum.x / ptCount;
+    cent.y = ptCentSum.y / ptCount;
+  }
+  else {
+    return false;
+  }
+  return true;
+}
+
+/* private */
+void
+Centroid::add(const Geometry& geom)
+{
+  if (geom.isEmpty()) return;
+
+  if (const Point* g = dynamic_cast<const Point*>(&geom)) {
+    addPoint(*g->getCoordinate());
+  }
+  else if (const LineString* g = dynamic_cast<const LineString*>(&geom)) {
+    addLineSegments(*g->getCoordinatesRO());
+  }
+  else if (const Polygon* g = dynamic_cast<const Polygon*>(&geom)) {
+    add(*g);
+  }
+  else if (const GeometryCollection* g = dynamic_cast<const GeometryCollection*>(&geom)) {
+    for (size_t i = 0; i < g->getNumGeometries(); i++) {
+      add(*g->getGeometryN(i));
+    }
+  }
+}
+
+/* private */
+void
+Centroid::setBasePoint(const Coordinate& basePt)
+{
+  if ( ! areaBasePt.get() )
+      areaBasePt.reset( new Coordinate(basePt) );
+}
+
+/* private */
+void
+Centroid::add(const Polygon& poly)
+{
+  addShell(*poly.getExteriorRing()->getCoordinatesRO());
+  for (size_t i = 0; i < poly.getNumInteriorRing(); i++) {
+    addHole(*poly.getInteriorRingN(i)->getCoordinatesRO());
+  }
+}
+
+/* private */
+void
+Centroid::addShell(const CoordinateSequence& pts)
+{
+  size_t len = pts.size();
+  if (len > 0)
+    setBasePoint(pts[0]);
+  bool isPositiveArea = ! CGAlgorithms::isCCW(&pts);
+  for (size_t i = 0; i < len - 1; ++i) {
+    addTriangle(*areaBasePt, pts[i], pts[i+1], isPositiveArea);
+  }
+  addLineSegments(pts);
+}
+
+/* private */
+void
+Centroid::addHole(const CoordinateSequence& pts)
+{
+  bool isPositiveArea = CGAlgorithms::isCCW(&pts);
+  for (size_t i = 0, e = pts.size() - 1; i < e; ++i) {
+    addTriangle(*areaBasePt, pts[i], pts[i+1], isPositiveArea);
+  }
+  addLineSegments(pts);
+}
+
+/* private */
+void
+Centroid::addTriangle(const Coordinate& p0, const Coordinate& p1, const Coordinate& p2, bool isPositiveArea)
+{
+  double sign = (isPositiveArea) ? 1.0 : -1.0;
+  centroid3( p0, p1, p2, triangleCent3 );
+  double a2 = area2( p0, p1, p2 );
+  cg3.x += sign * a2 * triangleCent3.x;
+  cg3.y += sign * a2 * triangleCent3.y;
+  areasum2 += sign * a2;
+}
+
+/* static private */
+void
+Centroid::centroid3(const Coordinate& p1, const Coordinate& p2, const Coordinate& p3, Coordinate& c )
+{
+  c.x = p1.x + p2.x + p3.x;
+  c.y = p1.y + p2.y + p3.y;
+  return;
+}
+
+/* static private */
+double
+Centroid::area2(const Coordinate& p1, const Coordinate& p2, const Coordinate& p3 )
+{
+  return
+    (p2.x - p1.x) * (p3.y - p1.y) -
+    (p3.x - p1.x) * (p2.y - p1.y);
+}
+
+/* private */
+void
+Centroid::addLineSegments(const CoordinateSequence& pts)
+{
+  size_t npts = pts.size();
+  double lineLen = 0.0;
+  for (size_t i = 0; i < npts - 1; i++) {
+    double segmentLen = pts[i].distance(pts[i + 1]);
+    if (segmentLen == 0.0)
+      continue;
+
+    lineLen += segmentLen;
+
+    double midx = (pts[i].x + pts[i + 1].x) / 2;
+    lineCentSum.x += segmentLen * midx;
+    double midy = (pts[i].y + pts[i + 1].y) / 2;
+    lineCentSum.y += segmentLen * midy;
+  }
+  totalLength += lineLen;
+  if (lineLen == 0.0 && npts > 0)
+    addPoint(pts[0]);
+}
+
+/* private */
+void
+Centroid::addPoint(const Coordinate& pt)
+{
+  ptCount += 1;
+  ptCentSum.x += pt.x;
+  ptCentSum.y += pt.y;
+}
+
+} // namespace geos.algorithm
+} // namespace geos

Modified: trunk/src/algorithm/Makefile.am
===================================================================
--- trunk/src/algorithm/Makefile.am	2013-01-14 11:16:01 UTC (rev 3748)
+++ trunk/src/algorithm/Makefile.am	2013-01-14 16:15:37 UTC (rev 3749)
@@ -12,6 +12,7 @@
 libalgorithm_la_SOURCES = \
     Angle.cpp \
     BoundaryNodeRule.cpp \
+    Centroid.cpp \
     CentroidArea.cpp \
     CentroidLine.cpp \
     CentroidPoint.cpp \

Modified: trunk/src/geom/Geometry.cpp
===================================================================
--- trunk/src/geom/Geometry.cpp	2013-01-14 11:16:01 UTC (rev 3748)
+++ trunk/src/geom/Geometry.cpp	2013-01-14 16:15:37 UTC (rev 3749)
@@ -34,9 +34,7 @@
 #include <geos/geom/MultiPolygon.h>
 #include <geos/geom/IntersectionMatrix.h>
 #include <geos/util/IllegalArgumentException.h>
-#include <geos/algorithm/CentroidPoint.h>
-#include <geos/algorithm/CentroidLine.h>
-#include <geos/algorithm/CentroidArea.h>
+#include <geos/algorithm/Centroid.h>
 #include <geos/algorithm/InteriorPointPoint.h>
 #include <geos/algorithm/InteriorPointLine.h>
 #include <geos/algorithm/InteriorPointArea.h>
@@ -202,30 +200,8 @@
 Geometry::getCentroid(Coordinate& ret) const
 {
 	if ( isEmpty() ) { return false; }
-
-	Coordinate c;
-
-	int dim=getDimension();
-	if(dim==0) {
-		CentroidPoint cent; 
-		cent.add(this);
-		if ( ! cent.getCentroid(c) )
-				return false;
-	} else if (dim==1) {
-		CentroidLine cent;
-		cent.add(this);
-		if ( ! cent.getCentroid(c) ) 
-			return false;
-	} else {
-		CentroidArea cent;
-		cent.add(this);
-		if ( ! cent.getCentroid(c) )
-			return false;
-	}
-
-	getPrecisionModel()->makePrecise(c);
-	ret=c;
-
+	if ( ! Centroid::getCentroid(*this, ret) ) return false;
+	getPrecisionModel()->makePrecise(ret); // not in JTS
 	return true;
 }
 

Modified: trunk/tests/xmltester/XMLTester.cpp
===================================================================
--- trunk/tests/xmltester/XMLTester.cpp	2013-01-14 11:16:01 UTC (rev 3748)
+++ trunk/tests/xmltester/XMLTester.cpp	2013-01-14 16:15:37 UTC (rev 3749)
@@ -957,7 +957,7 @@
 			GeomAutoPtr gRealRes(gT->getCentroid());
 
 			if ( gRealRes.get() ) gRealRes->normalize();
-			else gRealRes.reset(factory->createGeometryCollection());
+			else gRealRes.reset(factory->createPoint());
 			gRealRes->normalize();
 
 			if (gRes->compareTo(gRealRes.get())==0) success=1;

Modified: trunk/tests/xmltester/tests/general/TestCentroid.xml
===================================================================
--- trunk/tests/xmltester/tests/general/TestCentroid.xml	2013-01-14 11:16:01 UTC (rev 3748)
+++ trunk/tests/xmltester/tests/general/TestCentroid.xml	2013-01-14 16:15:37 UTC (rev 3749)
@@ -1,7 +1,13 @@
 <run>
-  <precisionModel scale="1.0" offsetx="0.0" offsety="0.0"/>
+  <!-- <precisionModel scale="1.0" offsetx="0.0" offsety="0.0"/> -->
 
 <case>
+  <desc>P - empty</desc>
+  <a>    POINT EMPTY  </a>
+<test><op name="getCentroid" arg1="A" >    POINT EMPTY   </op></test>
+</case>
+
+<case>
   <desc>P - single point</desc>
   <a>    POINT(10 10)  </a>
 <test><op name="getCentroid" arg1="A" >    POINT(10 10)   </op></test>
@@ -9,13 +15,13 @@
 
 <case>
   <desc>mP - two points</desc>
-  <a>    MULTIPOINT(10 10, 20 20 )  </a>
+  <a>    MULTIPOINT((10 10), (20 20) )  </a>
 <test><op name="getCentroid" arg1="A" >    POINT(15 15)   </op></test>
 </case>
 
 <case>
   <desc>mP - 4 points</desc>
-  <a>    MULTIPOINT(10 10, 20 20, 10 20, 20 10)  </a>
+  <a>    MULTIPOINT((10 10), (20 20), (10 20), (20 10))  </a>
 <test><op name="getCentroid" arg1="A" >    POINT(15 15)   </op></test>
 </case>
 
@@ -26,6 +32,18 @@
 </case>
 
 <case>
+  <desc>L - zero length line</desc>
+  <a>    LINESTRING (10 10, 10 10)  </a>
+<test><op name="getCentroid" arg1="A" >    POINT (10 10)   </op></test>
+</case>
+
+<case>
+  <desc>mL - zero length lines</desc>
+  <a>    MULTILINESTRING ((10 10, 10 10), (20 20, 20 20))  </a>
+<test><op name="getCentroid" arg1="A" >    POINT (15 15)   </op></test>
+</case>
+
+<case>
   <desc>L - two segments</desc>
   <a>    LINESTRING (60 180, 120 100, 180 180)  </a>
 <test><op name="getCentroid" arg1="A" >    POINT (120 140)   </op></test>
@@ -35,7 +53,7 @@
   <desc>L - elongated horseshoe</desc>
   <a>    LINESTRING (80 0, 80 120, 120 120, 120 0))
 	</a>
-<test><op name="getCentroid" arg1="A" >    POINT (100 69)   </op></test>
+<test><op name="getCentroid" arg1="A" >    POINT (100 68.57142857142857)   </op></test>
 </case>
 
 
@@ -76,7 +94,7 @@
 <case>
   <desc>A - box with hole</desc>
   <a>    POLYGON ((0 200, 200 200, 200 0, 0 0, 0 200), (20 180, 80 180, 80 20, 20 20, 20 180)) </a>
-<test><op name="getCentroid" arg1="A" >    POINT (116 100)   </op></test>
+<test><op name="getCentroid" arg1="A" >    POINT (115.78947368421052 100)  </op></test>
 </case>
 
 <case>
@@ -84,7 +102,7 @@
   <a>    POLYGON ((0 0, 0 200, 200 200, 200 0, 0 0), 
   (60 180, 20 180, 20 140, 60 140, 60 180))
 	 </a>
-<test><op name="getCentroid" arg1="A" >    POINT (103 98)   </op></test>
+<test><op name="getCentroid" arg1="A" >    POINT (102.5 97.5)  </op></test>
 </case>
 
 <case>
@@ -109,15 +127,15 @@
   <a>    GEOMETRYCOLLECTION (POLYGON ((0 200, 20 180, 20 140, 60 140, 200 0, 0 0, 0 200)), 
   POLYGON ((200 200, 0 200, 20 180, 60 180, 60 140, 200 0, 200 200))) 
 	</a>
-<test><op name="getCentroid" arg1="A" >    POINT (103 98)   </op></test>
+<test><op name="getCentroid" arg1="A" >    POINT (102.5 97.5)   </op></test>
 </case>
 
 <case>
   <desc>GC - heterogeneous collection of lines, points</desc>
   <a>    GEOMETRYCOLLECTION (LINESTRING (80 0, 80 120, 120 120, 120 0), 
-  MULTIPOINT (20 60, 40 80, 60 60))
+  MULTIPOINT ((20 60), (40 80), (60 60)))
 	</a>
-<test><op name="getCentroid" arg1="A" >    POINT (100 69)   </op></test>
+<test><op name="getCentroid" arg1="A" >    POINT (100 68.57142857142857)   </op></test>
 </case>
 
 <case>
@@ -129,15 +147,58 @@
 </case>
 
 <case>
-  <desc>GC - heterogeneous collection of polygons, lines, points</desc>
+  <desc>GC - collection of polygons, lines, points</desc>
   <a>    GEOMETRYCOLLECTION (POLYGON ((0 40, 40 40, 40 0, 0 0, 0 40)), 
   LINESTRING (80 0, 80 80, 120 40), 
-  MULTIPOINT (20 60, 40 80, 60 60))
+  MULTIPOINT ((20 60), (40 80), (60 60)))
 	</a>
 <test><op name="getCentroid" arg1="A" >    POINT (20 20)   </op></test>
 </case>
 
 <case>
+  <desc>GC - collection of zero-area polygons and lines</desc>
+  <a>    GEOMETRYCOLLECTION (POLYGON ((10 10, 10 10, 10 10, 10 10)), 
+  LINESTRING (20 20, 30 30))
+	</a>
+<test><op name="getCentroid" arg1="A" >    POINT (25 25)   </op></test>
+</case>
+
+<case>
+  <desc>GC - collection of zero-area polygons and zero-length lines</desc>
+  <a>    GEOMETRYCOLLECTION (POLYGON ((10 10, 10 10, 10 10, 10 10)), 
+  LINESTRING (20 20, 20 20))
+	</a>
+<test><op name="getCentroid" arg1="A" >    POINT (15 15)   </op></test>
+</case>
+
+<case>
+  <desc>GC - collection of zero-area polygons, zero-length lines, and points</desc>
+  <a>    GEOMETRYCOLLECTION (POLYGON ((10 10, 10 10, 10 10, 10 10)), 
+  LINESTRING (20 20, 20 20),
+  MULTIPOINT ((20 10), (10 20)) )
+	</a>
+<test><op name="getCentroid" arg1="A" >    POINT (15 15)   </op></test>
+</case>
+
+<case>
+  <desc>GC - collection of zero-area polygons, zero-length lines, and points</desc>
+  <a>    GEOMETRYCOLLECTION (POLYGON ((10 10, 10 10, 10 10, 10 10)), 
+  LINESTRING (20 20, 20 20),
+  POINT EMPTY )
+	</a>
+<test><op name="getCentroid" arg1="A" >    POINT (15 15)   </op></test>
+</case>
+
+<case>
+  <desc>GC - collection of zero-area polygons, zero-length lines, and points</desc>
+  <a>    GEOMETRYCOLLECTION (POLYGON ((10 10, 10 10, 10 10, 10 10)), 
+  LINESTRING EMPTY,
+  POINT EMPTY )
+	</a>
+<test><op name="getCentroid" arg1="A" >    POINT (10 10)   </op></test>
+</case>
+
+<case>
   <desc>GC - overlapping polygons </desc>
   <a>    GEOMETRYCOLLECTION (POLYGON ((20 100, 20 -20, 60 -20, 60 100, 20 100)), 
   POLYGON ((-20 60, 100 60, 100 20, -20 20, -20 60)))
@@ -145,5 +206,36 @@
 <test><op name="getCentroid" arg1="A" >    POINT (40 40)   </op></test>
 </case>
 
+<case>
+  <desc>A - degenerate box</desc>
+  <a>    POLYGON ((40 160, 160 160, 160 160, 40 160, 40 160))  </a>
+<test><op name="getCentroid" arg1="A" >    POINT (100 160)   </op></test>
+</case>
 
+<case>
+  <desc>A - degenerate triangle</desc>
+  <a>    POLYGON ((10 10, 100 100, 100 100, 10 10))  </a>
+<test><op name="getCentroid" arg1="A" >    POINT (55 55)   </op></test>
+</case>
+
+<case>
+  <desc>A - empty</desc>
+  <a>    POLYGON EMPTY
+	</a>
+<test><op name="getCentroid" arg1="A" >    POINT EMPTY   </op></test>
+</case>
+
+<case>
+  <desc>A - almost degenerate triangle</desc>
+  <a>    POLYGON((
+56.528666666700 25.2101666667,
+56.529000000000 25.2105000000,
+56.528833333300 25.2103333333,
+56.528666666700 25.2101666667))
+	</a>
+<test><op name="getCentroid" arg1="A" >    POINT (56.52883333335 25.21033333335)  </op></test>
+</case>
+
+
+
 </run>



More information about the geos-commits mailing list