[geos-commits] r4123 - in trunk: . capi include/geos/algorithm src/algorithm tests/unit tests/unit/algorithm tests/unit/capi
svn_geos at osgeo.org
svn_geos at osgeo.org
Mon Nov 30 04:01:42 PST 2015
Author: strk
Date: 2015-11-30 04:01:42 -0800 (Mon, 30 Nov 2015)
New Revision: 4123
Added:
trunk/tests/unit/algorithm/MinimumDiameterTest.cpp
trunk/tests/unit/capi/GEOSMinimumDiameterTest.cpp
trunk/tests/unit/capi/GEOSMinimumRectangleTest.cpp
Modified:
trunk/NEWS
trunk/capi/geos_c.cpp
trunk/capi/geos_c.h.in
trunk/capi/geos_ts_c.cpp
trunk/include/geos/algorithm/MinimumDiameter.h
trunk/src/algorithm/MinimumDiameter.cpp
trunk/tests/unit/Makefile.am
Log:
Port MinimumDiameter::getMinimumRectangle algorithm from JTS
Also add GEOSMinimumRotatedRectangle and GEOSMinimumDiameter
to C API, and re-sync MinimumDiameter with JTS r966.
Includes testcases.
Fixes #729.
Patch by: Nyall Dawson <nyall.dawson at gmail.com>
Signed-off-by: Sandro Santilli <strk at keybit.net>
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2015-11-30 10:06:15 UTC (rev 4122)
+++ trunk/NEWS 2015-11-30 12:01:42 UTC (rev 4123)
@@ -4,6 +4,8 @@
- New things:
- CAPI: GEOSGeom_setPrecision (#713) - PHP: Geometry->setPrecision
- CAPI: GEOSGeom_getPrecision - PHP: Geometry->getPrecision
+ - CAPI: GEOSMinimumRotatedRectangle and GEOSMinimumDiameter
+ (#729, Nyall Dawson)
- Improvements:
- ...
- C++ API changes:
Modified: trunk/capi/geos_c.cpp
===================================================================
--- trunk/capi/geos_c.cpp 2015-11-30 10:06:15 UTC (rev 4122)
+++ trunk/capi/geos_c.cpp 2015-11-30 12:01:42 UTC (rev 4123)
@@ -437,6 +437,18 @@
}
Geometry *
+GEOSMinimumRotatedRectangle(const Geometry *g)
+{
+ return GEOSMinimumRotatedRectangle_r( handle, g );
+}
+
+Geometry *
+GEOSMinimumDiameter(const Geometry *g)
+{
+ return GEOSMinimumDiameter_r( handle, g );
+}
+
+Geometry *
GEOSDifference(const Geometry *g1, const Geometry *g2)
{
return GEOSDifference_r( handle, g1, g2 );
Modified: trunk/capi/geos_c.h.in
===================================================================
--- trunk/capi/geos_c.h.in 2015-11-30 10:06:15 UTC (rev 4122)
+++ trunk/capi/geos_c.h.in 2015-11-30 12:01:42 UTC (rev 4123)
@@ -538,6 +538,10 @@
const GEOSGeometry* g2);
extern GEOSGeometry GEOS_DLL *GEOSConvexHull_r(GEOSContextHandle_t handle,
const GEOSGeometry* g);
+extern GEOSGeometry GEOS_DLL *GEOSMinimumRotatedRectangle_r(GEOSContextHandle_t handle,
+ const GEOSGeometry* g);
+extern GEOSGeometry GEOS_DLL *GEOSMinimumDiameter_r(GEOSContextHandle_t handle,
+ const GEOSGeometry* g);
extern GEOSGeometry GEOS_DLL *GEOSDifference_r(GEOSContextHandle_t handle,
const GEOSGeometry* g1,
const GEOSGeometry* g2);
@@ -1448,6 +1452,8 @@
extern GEOSGeometry GEOS_DLL *GEOSEnvelope(const GEOSGeometry* g);
extern GEOSGeometry GEOS_DLL *GEOSIntersection(const GEOSGeometry* g1, const GEOSGeometry* g2);
extern GEOSGeometry GEOS_DLL *GEOSConvexHull(const GEOSGeometry* g);
+extern GEOSGeometry GEOS_DLL *GEOSMinimumRotatedRectangle(const GEOSGeometry* g);
+extern GEOSGeometry GEOS_DLL *GEOSMinimumDiameter(const GEOSGeometry* g);
extern GEOSGeometry GEOS_DLL *GEOSDifference(const GEOSGeometry* g1, const GEOSGeometry* g2);
extern GEOSGeometry GEOS_DLL *GEOSSymDifference(const GEOSGeometry* g1, const GEOSGeometry* g2);
extern GEOSGeometry GEOS_DLL *GEOSBoundary(const GEOSGeometry* g);
Modified: trunk/capi/geos_ts_c.cpp
===================================================================
--- trunk/capi/geos_ts_c.cpp 2015-11-30 10:06:15 UTC (rev 4122)
+++ trunk/capi/geos_ts_c.cpp 2015-11-30 12:01:42 UTC (rev 4123)
@@ -43,6 +43,7 @@
#include <geos/algorithm/distance/DiscreteHausdorffDistance.h>
#include <geos/algorithm/CGAlgorithms.h>
#include <geos/algorithm/BoundaryNodeRule.h>
+#include <geos/algorithm/MinimumDiameter.h>
#include <geos/simplify/DouglasPeuckerSimplifier.h>
#include <geos/simplify/TopologyPreservingSimplifier.h>
#include <geos/noding/GeometryNoder.h>
@@ -2007,7 +2008,77 @@
return NULL;
}
+
Geometry *
+GEOSMinimumRotatedRectangle_r(GEOSContextHandle_t extHandle, const Geometry *g)
+{
+ if ( 0 == extHandle )
+ {
+ return NULL;
+ }
+
+ GEOSContextHandleInternal_t *handle = 0;
+ handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
+ if ( 0 == handle->initialized )
+ {
+ return NULL;
+ }
+
+ try
+ {
+ geos::algorithm::MinimumDiameter m(g);
+
+ Geometry *g3 = m.getMinimumRectangle();
+ return g3;
+ }
+ catch (const std::exception &e)
+ {
+ handle->ERROR_MESSAGE("%s", e.what());
+ }
+ catch (...)
+ {
+ handle->ERROR_MESSAGE("Unknown exception thrown");
+ }
+
+ return NULL;
+}
+
+Geometry *
+GEOSMinimumDiameter_r(GEOSContextHandle_t extHandle, const Geometry *g)
+{
+ if ( 0 == extHandle )
+ {
+ return NULL;
+ }
+
+ GEOSContextHandleInternal_t *handle = 0;
+ handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
+ if ( 0 == handle->initialized )
+ {
+ return NULL;
+ }
+
+ try
+ {
+ geos::algorithm::MinimumDiameter m(g);
+
+ Geometry *g3 = m.getDiameter();
+ return g3;
+ }
+ catch (const std::exception &e)
+ {
+ handle->ERROR_MESSAGE("%s", e.what());
+ }
+ catch (...)
+ {
+ handle->ERROR_MESSAGE("Unknown exception thrown");
+ }
+
+ return NULL;
+}
+
+
+Geometry *
GEOSDifference_r(GEOSContextHandle_t extHandle, const Geometry *g1, const Geometry *g2)
{
if ( 0 == extHandle )
Modified: trunk/include/geos/algorithm/MinimumDiameter.h
===================================================================
--- trunk/include/geos/algorithm/MinimumDiameter.h 2015-11-30 10:06:15 UTC (rev 4122)
+++ trunk/include/geos/algorithm/MinimumDiameter.h 2015-11-30 12:01:42 UTC (rev 4123)
@@ -11,6 +11,10 @@
* by the Free Software Foundation.
* See the COPYING file for more information.
*
+ **********************************************************************
+ *
+ * Last port: algorithm/MinimumDiameter.java r966
+ *
**********************************************************************/
#ifndef GEOS_ALGORITHM_MINIMUMDIAMETER_H
@@ -47,6 +51,13 @@
* The first step in the algorithm is computing the convex hull of the Geometry.
* If the input Geometry is known to be convex, a hint can be supplied to
* avoid this computation.
+ * <p>
+ * This class can also be used to compute a line segment representing
+ * the minimum diameter, the supporting line segment of the minimum diameter,
+ * and a minimum rectangle enclosing the input geometry.
+ * This rectangle will
+ * have width equal to the minimum diameter, and have one side
+ * parallel to the supporting segment.
*
* @see ConvexHull
*
@@ -55,6 +66,9 @@
private:
const geom::Geometry* inputGeom;
bool isConvex;
+
+ geom::CoordinateSequence* convexHullPts;
+
geom::LineSegment* minBaseSeg;
geom::Coordinate* minWidthPt;
int minPtIndex;
@@ -77,6 +91,10 @@
static unsigned int getNextIndex(const geom::CoordinateSequence* pts,
unsigned int index);
+ static double computeC(double a, double b, const geom::Coordinate &p);
+
+ static geom::LineSegment computeSegmentForLine(double a, double b, double c);
+
public:
~MinimumDiameter();
@@ -126,6 +144,33 @@
* @return a LineString which is a minimum diameter
*/
geom::LineString* getDiameter();
+
+ /**
+ * Gets the minimum rectangular Polygon which encloses the input geometry. The rectangle has width
+ * equal to the minimum diameter, and a longer length. If the convex hill of the input is degenerate
+ * (a line or point) a LineString or Point is returned.
+ * The minimum rectangle can be used as an extremely generalized representation for the given
+ * geometry.
+ *
+ * @return the minimum rectangle enclosing the input (or a line or point if degenerate)
+ */
+ geom::Geometry* getMinimumRectangle();
+
+ /**
+ * Gets the minimum rectangle enclosing a geometry.
+ *
+ * @param geom the geometry
+ * @return the minimum rectangle enclosing the geometry
+ */
+ static geom::Geometry* getMinimumRectangle(geom::Geometry* geom);
+
+ /**
+ * Gets the length of the minimum diameter enclosing a geometry
+ * @param geom the geometry
+ * @return the length of the minimum diameter of the geometry
+ */
+ static geom::Geometry* getMinimumDiameter(geom::Geometry* geom);
+
};
} // namespace geos::algorithm
Modified: trunk/src/algorithm/MinimumDiameter.cpp
===================================================================
--- trunk/src/algorithm/MinimumDiameter.cpp 2015-11-30 10:06:15 UTC (rev 4122)
+++ trunk/src/algorithm/MinimumDiameter.cpp 2015-11-30 12:01:42 UTC (rev 4123)
@@ -12,6 +12,10 @@
* See the COPYING file for more information.
*
**********************************************************************
+ *
+ * Last port: algorithm/MinimumDiameter.java r966
+ *
+ **********************************************************************
*
* TODO:
* - avoid heap allocation for LineSegment and Coordinate
@@ -23,6 +27,7 @@
#include <geos/geom/Geometry.h>
#include <geos/geom/LineSegment.h>
#include <geos/geom/Polygon.h>
+#include <geos/geom/Point.h>
#include <geos/geom/LineString.h>
#include <geos/geom/CoordinateSequenceFactory.h>
#include <geos/geom/GeometryFactory.h>
@@ -67,6 +72,7 @@
minWidth=0.0;
inputGeom=newInputGeom;
isConvex=false;
+ convexHullPts=NULL;
}
/**
@@ -86,12 +92,14 @@
minWidth=0.0;
inputGeom=newInputGeom;
isConvex=newIsConvex;
+ convexHullPts=NULL;
}
MinimumDiameter::~MinimumDiameter()
{
delete minBaseSeg;
delete minWidthPt;
+ delete convexHullPts;
}
/**
@@ -177,42 +185,45 @@
MinimumDiameter::computeWidthConvex(const Geometry *geom)
{
//System.out.println("Input = " + geom);
- CoordinateSequence* pts=NULL;
+ delete convexHullPts;
if (typeid(*geom)==typeid(Polygon))
{
const Polygon* p = dynamic_cast<const Polygon*>(geom);
- pts=p->getExteriorRing()->getCoordinates();
+ convexHullPts=p->getExteriorRing()->getCoordinates();
}
else
{
- pts=geom->getCoordinates();
+ convexHullPts=geom->getCoordinates();
}
// special cases for lines or points or degenerate rings
- switch(pts->getSize())
+ switch(convexHullPts->getSize())
{
case 0:
minWidth=0.0;
+ delete minWidthPt;
minWidthPt=NULL;
+ delete minBaseSeg;
minBaseSeg=NULL;
break;
case 1:
minWidth = 0.0;
- minWidthPt=new Coordinate(pts->getAt(0));
- minBaseSeg->p0=pts->getAt(0);
- minBaseSeg->p1=pts->getAt(0);
+ delete minWidthPt;
+ minWidthPt=new Coordinate(convexHullPts->getAt(0));
+ minBaseSeg->p0=convexHullPts->getAt(0);
+ minBaseSeg->p1=convexHullPts->getAt(0);
break;
case 2:
case 3:
minWidth = 0.0;
- minWidthPt=new Coordinate(pts->getAt(0));
- minBaseSeg->p0=pts->getAt(0);
- minBaseSeg->p1=pts->getAt(1);
+ delete minWidthPt;
+ minWidthPt=new Coordinate(convexHullPts->getAt(0));
+ minBaseSeg->p0=convexHullPts->getAt(0);
+ minBaseSeg->p1=convexHullPts->getAt(1);
break;
default:
- computeConvexRingMinDiameter(pts);
+ computeConvexRingMinDiameter(convexHullPts);
}
- delete pts;
}
/**
@@ -275,6 +286,111 @@
return index;
}
+Geometry* MinimumDiameter::getMinimumRectangle()
+{
+ computeMinimumDiameter();
+
+ if ( !minBaseSeg || !convexHullPts )
+ {
+ //return empty polygon
+ return inputGeom->getFactory()->createPolygon();
+ }
+
+ // check if minimum rectangle is degenerate (a point or line segment)
+ if (minWidth == 0.0) {
+ if (minBaseSeg->p0.equals2D(minBaseSeg->p1)) {
+ return inputGeom->getFactory()->createPoint(minBaseSeg->p0);
+ }
+ return minBaseSeg->toGeometry(*inputGeom->getFactory()).release();
+ }
+
+ // deltas for the base segment of the minimum diameter
+ double dx = minBaseSeg->p1.x - minBaseSeg->p0.x;
+ double dy = minBaseSeg->p1.y - minBaseSeg->p0.y;
+
+ double minPara = DoubleMax;
+ double maxPara = -DoubleMax;
+ double minPerp = DoubleMax;
+ double maxPerp = -DoubleMax;
+
+ // compute maxima and minima of lines parallel and perpendicular to base segment
+ std::size_t const n=convexHullPts->getSize();
+ for (std::size_t i = 0; i < n; ++i) {
+
+ double paraC = computeC(dx, dy, convexHullPts->getAt(i));
+ if (paraC > maxPara) maxPara = paraC;
+ if (paraC < minPara) minPara = paraC;
+
+ double perpC = computeC(-dy, dx, convexHullPts->getAt(i));
+ if (perpC > maxPerp) maxPerp = perpC;
+ if (perpC < minPerp) minPerp = perpC;
+ }
+
+ // compute lines along edges of minimum rectangle
+ LineSegment maxPerpLine = computeSegmentForLine(-dx, -dy, maxPerp);
+ LineSegment minPerpLine = computeSegmentForLine(-dx, -dy, minPerp);
+ LineSegment maxParaLine = computeSegmentForLine(-dy, dx, maxPara);
+ LineSegment minParaLine = computeSegmentForLine(-dy, dx, minPara);
+
+ // compute vertices of rectangle (where the para/perp max & min lines intersect)
+ Coordinate p0, p1, p2, p3;
+ maxParaLine.lineIntersection(maxPerpLine, p0);
+ minParaLine.lineIntersection(maxPerpLine, p1);
+ minParaLine.lineIntersection(minPerpLine, p2);
+ maxParaLine.lineIntersection(minPerpLine, p3);
+
+ const CoordinateSequenceFactory *csf =
+ inputGeom->getFactory()->getCoordinateSequenceFactory();
+
+ geom::CoordinateSequence *seq = csf->create(5, 2);
+ seq->setAt(p0, 0);
+ seq->setAt(p1, 1);
+ seq->setAt(p2, 2);
+ seq->setAt(p3, 3);
+ seq->setAt(p0, 4); // close
+
+ LinearRing* shell = inputGeom->getFactory()->createLinearRing( seq );
+ return inputGeom->getFactory()->createPolygon( shell, NULL );
+}
+
+double MinimumDiameter::computeC(double a, double b, const Coordinate& p)
+{
+ return a * p.y - b * p.x;
+}
+
+LineSegment MinimumDiameter::computeSegmentForLine(double a, double b, double c)
+{
+ Coordinate p0;
+ Coordinate p1;
+ /*
+ * Line eqn is ax + by = c
+ * Slope is a/b.
+ * If slope is steep, use y values as the inputs
+ */
+ if (fabs(b) > fabs(a) ) {
+ p0 = Coordinate(0.0, c/b);
+ p1 = Coordinate(1.0, c/b - a/b);
+ }
+ else {
+ p0 = Coordinate(c/a, 0.0);
+ p1 = Coordinate(c/a - b/a, 1.0);
+ }
+ return LineSegment(p0, p1);
+}
+
+
+Geometry *MinimumDiameter::getMinimumRectangle(Geometry *geom)
+{
+ MinimumDiameter md( geom );
+ return md.getMinimumRectangle();
+}
+
+Geometry *MinimumDiameter::getMinimumDiameter(Geometry *geom)
+{
+ MinimumDiameter md( geom );
+ return md.getDiameter();
+}
+
} // namespace geos.algorithm
} // namespace geos
Modified: trunk/tests/unit/Makefile.am
===================================================================
--- trunk/tests/unit/Makefile.am 2015-11-30 10:06:15 UTC (rev 4122)
+++ trunk/tests/unit/Makefile.am 2015-11-30 12:01:42 UTC (rev 4123)
@@ -41,6 +41,7 @@
algorithm/CGAlgorithms/signedAreaTest.cpp \
algorithm/ConvexHullTest.cpp \
algorithm/distance/DiscreteHausdorffDistanceTest.cpp \
+ algorithm/MinimumDiameterTest.cpp \
algorithm/PointLocatorTest.cpp \
algorithm/RobustLineIntersectionTest.cpp \
algorithm/RobustLineIntersectorTest.cpp \
@@ -130,6 +131,8 @@
capi/GEOSInterruptTest.cpp \
capi/GEOSIntersectsTest.cpp \
capi/GEOSIntersectionTest.cpp \
+ capi/GEOSMinimumRectangleTest.cpp \
+ capi/GEOSMinimumDiameterTest.cpp \
capi/GEOSNearestPointsTest.cpp \
capi/GEOSWithinTest.cpp \
capi/GEOSSimplifyTest.cpp \
Added: trunk/tests/unit/algorithm/MinimumDiameterTest.cpp
===================================================================
--- trunk/tests/unit/algorithm/MinimumDiameterTest.cpp (rev 0)
+++ trunk/tests/unit/algorithm/MinimumDiameterTest.cpp 2015-11-30 12:01:42 UTC (rev 4123)
@@ -0,0 +1,236 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2015 Nyall Dawson <nyall dot dawson at gmail dot com>
+ *
+ * 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.
+ *
+ **********************************************************************/
+
+//
+// Test Suite for geos::algorithm::MinimumDiameter
+
+#include <tut.hpp>
+// geos
+#include <geos/geom/Coordinate.h>
+#include <geos/algorithm/MinimumDiameter.h>
+#include <geos/io/WKTReader.h>
+#include <geos/io/WKTWriter.h>
+#include <geos/geom/Geometry.h>
+// std
+#include <sstream>
+#include <string>
+#include <memory>
+
+namespace tut
+{
+ //
+ // Test Group
+ //
+
+ // dummy data, not used
+ struct test_minimumdiameter_data {
+ typedef geos::geom::Geometry Geometry;
+ typedef std::auto_ptr<geos::geom::Geometry> GeomPtr;
+
+ typedef geos::geom::Coordinate Coordinate;
+ typedef geos::algorithm::MinimumDiameter MinimumDiameter;
+
+ geos::io::WKTReader reader;
+ std::auto_ptr<Geometry> geom;
+
+ test_minimumdiameter_data()
+ {}
+
+ };
+
+ typedef test_group<test_minimumdiameter_data> group;
+ typedef group::object object;
+
+ group test_minimumdiameter_data_group("geos::algorithm::MinimumDiameter");
+
+ //
+ // Test Cases
+ //
+
+ // Test of getMinimumRectangle
+ template<>
+ template<>
+ void object::test<1>()
+ {
+ GeomPtr geom(reader.read("POLYGON ((0 0, 0 20, 20 20, 20 0, 0 0))"));
+ ensure(0 != geom.get());
+
+ geos::algorithm::MinimumDiameter m(geom.get());
+ GeomPtr minRect( m.getMinimumRectangle() );
+ ensure(0 != minRect.get());
+
+ GeomPtr expectedGeom(reader.read("POLYGON ((0 0, 20 0, 20 20, 0 20, 0 0))"));
+ ensure(0 != expectedGeom.get());
+
+ ensure( minRect.get()->equalsExact(expectedGeom.get()) );
+ }
+
+ // Test with expected rotated rectangle
+ template<>
+ template<>
+ void object::test<2>()
+ {
+ GeomPtr geom(reader.read("POLYGON ((0 5, 5 10, 10 5, 5 0, 0 5))"));
+ ensure(0 != geom.get());
+
+ geos::algorithm::MinimumDiameter m(geom.get());
+ GeomPtr minRect( m.getMinimumRectangle() );
+ ensure(0 != minRect.get());
+
+ GeomPtr expectedGeom(reader.read("POLYGON ((5 0, 10 5, 5 10, 0 5, 5 0))"));
+ ensure(0 != expectedGeom.get());
+
+ ensure( minRect.get()->equalsExact(expectedGeom.get()) );
+ }
+
+ // Test with EMPTY input
+ template<>
+ template<>
+ void object::test<3>()
+ {
+ GeomPtr geom(reader.read("POLYGON EMPTY"));
+ ensure(0 != geom.get());
+
+ geos::algorithm::MinimumDiameter m(geom.get());
+ GeomPtr minRect( m.getMinimumRectangle() );
+ ensure(0 != minRect.get());
+
+ GeomPtr expectedGeom(reader.read("POLYGON EMPTY"));
+ ensure(0 != expectedGeom.get());
+
+ ensure( minRect.get()->equalsExact(expectedGeom.get()) );
+ }
+
+ // Test with Point input
+ template<>
+ template<>
+ void object::test<4>()
+ {
+ GeomPtr geom(reader.read("Point(1 2)"));
+ ensure(0 != geom.get());
+
+ geos::algorithm::MinimumDiameter m(geom.get());
+ GeomPtr minRect( m.getMinimumRectangle() );
+ ensure(0 != minRect.get());
+
+ GeomPtr expectedGeom(reader.read("Point(1 2)"));
+ ensure(0 != expectedGeom.get());
+
+ ensure( minRect.get()->equalsExact(expectedGeom.get()) );
+ }
+
+ // Test with LineString input
+ template<>
+ template<>
+ void object::test<5>()
+ {
+ GeomPtr geom(reader.read("LineString(1 2, 2 4)"));
+ ensure(0 != geom.get());
+
+ geos::algorithm::MinimumDiameter m(geom.get());
+ GeomPtr minRect( m.getMinimumRectangle() );
+ ensure(0 != minRect.get());
+
+ GeomPtr expectedGeom(reader.read("LineString(1 2, 2 4)"));
+ ensure(0 != expectedGeom.get());
+
+ ensure( minRect.get()->equalsExact(expectedGeom.get()) );
+ }
+
+ // Test minimumDiameter with Point input
+ template<>
+ template<>
+ void object::test<6>()
+ {
+ GeomPtr geom(reader.read("POINT (0 240)"));
+ ensure(0 != geom.get());
+
+ GeomPtr minDiameter( geos::algorithm::MinimumDiameter::getMinimumDiameter( geom.get() ) );
+ ensure(0 != minDiameter.get());
+
+ GeomPtr expectedGeom(reader.read("LineString (0 240, 0 240)"));
+ ensure(0 != expectedGeom.get());
+
+ ensure( minDiameter.get()->equalsExact(expectedGeom.get()) );
+ }
+
+ // Test minimumDiameter with LineString input
+ template<>
+ template<>
+ void object::test<7>()
+ {
+ GeomPtr geom(reader.read("LINESTRING (0 240, 220 240)"));
+ ensure(0 != geom.get());
+
+ GeomPtr minDiameter( geos::algorithm::MinimumDiameter::getMinimumDiameter( geom.get() ) );
+ ensure(0 != minDiameter.get());
+
+ GeomPtr expectedGeom(reader.read("LINESTRING (0 240, 0 240)"));
+ ensure(0 != expectedGeom.get());
+
+ ensure( minDiameter.get()->equalsExact(expectedGeom.get()) );
+ }
+
+ // Test minimumDiameter with Polygon input
+ template<>
+ template<>
+ void object::test<8>()
+ {
+ GeomPtr geom(reader.read("POLYGON ((0 240, 220 240, 220 0, 0 0, 0 240))"));
+ ensure(0 != geom.get());
+
+ GeomPtr minDiameter( geos::algorithm::MinimumDiameter::getMinimumDiameter( geom.get() ) );
+ ensure(0 != minDiameter.get());
+
+ GeomPtr expectedGeom(reader.read("LINESTRING (0 0, 220 0)"));
+ ensure(0 != expectedGeom.get());
+
+ ensure( minDiameter.get()->equalsExact(expectedGeom.get()) );
+ }
+
+ // Test minimumDiameter with Polygon input
+ template<>
+ template<>
+ void object::test<9>()
+ {
+ GeomPtr geom(reader.read("POLYGON ((0 240, 160 140, 220 0, 0 0, 0 240))"));
+ ensure(0 != geom.get());
+
+ GeomPtr minDiameter( geos::algorithm::MinimumDiameter::getMinimumDiameter( geom.get() ) );
+ ensure(0 != minDiameter.get());
+
+ GeomPtr expectedGeom(reader.read("LINESTRING (185.86206896551724 79.65517241379311, 0 0)"));
+ ensure(0 != expectedGeom.get());
+
+ ensure( minDiameter.get()->equalsExact(expectedGeom.get(), 0.00000000001) );
+ }
+
+ // Test minimumDiameter with complex LineString
+ template<>
+ template<>
+ void object::test<10>()
+ {
+ GeomPtr geom(reader.read("LINESTRING ( 39 119, 162 197, 135 70, 95 35, 33 66, 111 82, 97 131, 48 160, -4 182, 57 195, 94 202, 90 174, 75 134, 47 114, 0 100, 59 81, 123 60, 136 43, 163 75, 145 114, 93 136, 92 159, 105 175 )"));
+ ensure(0 != geom.get());
+
+ GeomPtr minDiameter( geos::algorithm::MinimumDiameter::getMinimumDiameter( geom.get() ) );
+ ensure(0 != minDiameter.get());
+
+ GeomPtr expectedGeom(reader.read("LINESTRING (64.46262341325811 196.41184767277855, 95 35)"));
+ ensure(0 != expectedGeom.get());
+
+ ensure( minDiameter.get()->equalsExact(expectedGeom.get(), 0.00000000001) );
+ }
+
+} // namespace tut
Added: trunk/tests/unit/capi/GEOSMinimumDiameterTest.cpp
===================================================================
--- trunk/tests/unit/capi/GEOSMinimumDiameterTest.cpp (rev 0)
+++ trunk/tests/unit/capi/GEOSMinimumDiameterTest.cpp 2015-11-30 12:01:42 UTC (rev 4123)
@@ -0,0 +1,83 @@
+//
+// Test Suite for C-API GEOSMinimumDiameter
+#include <tut.hpp>
+// geos
+#include <geos_c.h>
+// std
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+
+namespace tut
+{
+ //
+ // Test Group
+ //
+
+ // Common data used in test cases.
+ struct test_capigeosminimumdiameter_data
+ {
+ GEOSGeometry* input_;
+ GEOSWKTWriter* wktw_;
+ char* wkt_;
+
+ static void notice(const char *fmt, ...)
+ {
+ std::fprintf( stdout, "NOTICE: ");
+
+ va_list ap;
+ va_start(ap, fmt);
+ std::vfprintf(stdout, fmt, ap);
+ va_end(ap);
+
+ std::fprintf(stdout, "\n");
+ }
+
+ test_capigeosminimumdiameter_data()
+ : input_(0), wkt_(0)
+ {
+ initGEOS(notice, notice);
+ wktw_ = GEOSWKTWriter_create();
+ GEOSWKTWriter_setTrim(wktw_, 1);
+ GEOSWKTWriter_setRoundingPrecision(wktw_, 8);
+ }
+
+ ~test_capigeosminimumdiameter_data()
+ {
+ GEOSGeom_destroy(input_);
+ input_ = 0;
+ GEOSWKTWriter_destroy(wktw_);
+ GEOSFree(wkt_);
+ wkt_ = 0;
+ finishGEOS();
+ }
+
+ };
+
+ typedef test_group<test_capigeosminimumdiameter_data> group;
+ typedef group::object object;
+
+ group test_capigeosminimumdiameter_group("capi::GEOSMinimumDiameter");
+
+ //
+ // Test Cases
+ //
+
+ template<>
+ template<>
+ void object::test<1>()
+ {
+ input_ = GEOSGeomFromWKT("POLYGON ((0 0, 0 15, 5 10, 5 0, 0 0))");
+ ensure( 0 != input_ );
+
+ GEOSGeometry* output = GEOSMinimumDiameter(input_);
+ ensure( 0 != output );
+ ensure( 0 == GEOSisEmpty(output) );
+
+ wkt_ = GEOSWKTWriter_write(wktw_, output);
+ ensure_equals(std::string(wkt_), std::string( "LINESTRING (0 0, 5 0)"));
+
+ GEOSGeom_destroy(output);
+ }
+
+} // namespace tut
Added: trunk/tests/unit/capi/GEOSMinimumRectangleTest.cpp
===================================================================
--- trunk/tests/unit/capi/GEOSMinimumRectangleTest.cpp (rev 0)
+++ trunk/tests/unit/capi/GEOSMinimumRectangleTest.cpp 2015-11-30 12:01:42 UTC (rev 4123)
@@ -0,0 +1,84 @@
+//
+// Test Suite for C-API GEOSMinimumRotatedRectangle
+
+#include <tut.hpp>
+// geos
+#include <geos_c.h>
+// std
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+
+namespace tut
+{
+ //
+ // Test Group
+ //
+
+ // Common data used in test cases.
+ struct test_capigeosminimumrectangle_data
+ {
+ GEOSGeometry* input_;
+ GEOSWKTWriter* wktw_;
+ char* wkt_;
+
+ static void notice(const char *fmt, ...)
+ {
+ std::fprintf( stdout, "NOTICE: ");
+
+ va_list ap;
+ va_start(ap, fmt);
+ std::vfprintf(stdout, fmt, ap);
+ va_end(ap);
+
+ std::fprintf(stdout, "\n");
+ }
+
+ test_capigeosminimumrectangle_data()
+ : input_(0), wkt_(0)
+ {
+ initGEOS(notice, notice);
+ wktw_ = GEOSWKTWriter_create();
+ GEOSWKTWriter_setTrim(wktw_, 1);
+ GEOSWKTWriter_setRoundingPrecision(wktw_, 8);
+ }
+
+ ~test_capigeosminimumrectangle_data()
+ {
+ GEOSGeom_destroy(input_);
+ input_ = 0;
+ GEOSWKTWriter_destroy(wktw_);
+ GEOSFree(wkt_);
+ wkt_ = 0;
+ finishGEOS();
+ }
+
+ };
+
+ typedef test_group<test_capigeosminimumrectangle_data> group;
+ typedef group::object object;
+
+ group test_capigeosminimumrectangle_group("capi::GEOSMinimumRotatedRectangle");
+
+ //
+ // Test Cases
+ //
+
+ template<>
+ template<>
+ void object::test<1>()
+ {
+ input_ = GEOSGeomFromWKT("POLYGON ((1 6, 6 11, 11 6, 6 1, 1 6))");
+ ensure( 0 != input_ );
+
+ GEOSGeometry* output = GEOSMinimumRotatedRectangle(input_);
+ ensure( 0 != output );
+ ensure( 0 == GEOSisEmpty(output) );
+
+ wkt_ = GEOSWKTWriter_write(wktw_, output);
+ ensure_equals(std::string(wkt_), std::string( "POLYGON ((6 1, 11 6, 6 11, 1 6, 6 1))"));
+
+ GEOSGeom_destroy(output);
+ }
+
+} // namespace tut
More information about the geos-commits
mailing list