[geos-commits] [SCM] GEOS branch master updated. 60583394172397a47e444443175d06d7dbb17f1c

git at osgeo.org git at osgeo.org
Thu Sep 26 10:01:32 PDT 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  60583394172397a47e444443175d06d7dbb17f1c (commit)
      from  8c837b6e821cf5bebd4f6561c5947aed3c7f1d51 (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 60583394172397a47e444443175d06d7dbb17f1c
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Thu Sep 26 10:01:13 2019 -0700

    Expose MinimumBoundingCircle to CAPI
    Closes #735

diff --git a/NEWS b/NEWS
index a4dcd2b..40c9961 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,7 @@ Changes in 3.8.0
   - CAPI: GEOSCoverageUnion (Dan Baston)
   - CAPI: GEOSCoordSeq_setXY, GEOSCoordSeq_setXYZ,
           GEOSCoordSeq_getXY, GEOSCoordSeq_getXYZ (Dan Baston)
+  - CAPI: GEOSMinimumBoundingCircle (#735)
 
 - Improvements:
   - Improve performance and robustness of GEOSPointOnSurface (Martin Davis)
diff --git a/capi/geos_c.cpp b/capi/geos_c.cpp
index 2974eca..ad8584f 100644
--- a/capi/geos_c.cpp
+++ b/capi/geos_c.cpp
@@ -706,6 +706,12 @@ extern "C" {
     }
 
     Geometry*
+    GEOSMinimumBoundingCircle(const Geometry* g, double* radius, Geometry** center)
+    {
+        return GEOSMinimumBoundingCircle_r(handle, g, radius, center);
+    }
+
+    Geometry*
     GEOSGeom_createCollection(int type, Geometry** geoms, unsigned int ngeoms)
     {
         return GEOSGeom_createCollection_r(handle, type, geoms, ngeoms);
diff --git a/capi/geos_c.h.in b/capi/geos_c.h.in
index 73207e3..31da35e 100644
--- a/capi/geos_c.h.in
+++ b/capi/geos_c.h.in
@@ -602,6 +602,9 @@ extern GEOSGeometry GEOS_DLL *GEOSPointOnSurface_r(GEOSContextHandle_t handle,
                                                    const GEOSGeometry* g);
 extern GEOSGeometry GEOS_DLL *GEOSGetCentroid_r(GEOSContextHandle_t handle,
                                                 const GEOSGeometry* g);
+extern GEOSGeometry GEOS_DLL *GEOSMinimumBoundingCircle_r(GEOSContextHandle_t handle,
+                                                const GEOSGeometry* g, double* radius,
+                                                GEOSGeometry** center);
 extern GEOSGeometry GEOS_DLL *GEOSNode_r(GEOSContextHandle_t handle,
                                          const GEOSGeometry* g);
 /* Fast, non-robust intersection between an arbitrary geometry and
@@ -1642,8 +1645,10 @@ extern GEOSGeometry GEOS_DLL *GEOSCoverageUnion(const GEOSGeometry *g);
 
 /* @deprecated in 3.3.0: use GEOSUnaryUnion instead */
 extern GEOSGeometry GEOS_DLL *GEOSUnionCascaded(const GEOSGeometry* g);
+
 extern GEOSGeometry GEOS_DLL *GEOSPointOnSurface(const GEOSGeometry* g);
 extern GEOSGeometry GEOS_DLL *GEOSGetCentroid(const GEOSGeometry* g);
+extern GEOSGeometry GEOS_DLL *GEOSMinimumBoundingCircle(const GEOSGeometry* g, double* radius, GEOSGeometry** center);
 extern GEOSGeometry GEOS_DLL *GEOSNode(const GEOSGeometry* g);
 extern GEOSGeometry GEOS_DLL *GEOSClipByRect(const GEOSGeometry* g, double xmin, double ymin, double xmax, double ymax);
 
diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp
index c2a1b80..828f01e 100644
--- a/capi/geos_ts_c.cpp
+++ b/capi/geos_ts_c.cpp
@@ -44,7 +44,7 @@
 #include <geos/io/WKTWriter.h>
 #include <geos/io/WKBWriter.h>
 #include <geos/algorithm/BoundaryNodeRule.h>
-#include <geos/algorithm/Orientation.h>
+#include <geos/algorithm/MinimumBoundingCircle.h>
 #include <geos/algorithm/MinimumDiameter.h>
 #include <geos/algorithm/Orientation.h>
 #include <geos/algorithm/distance/DiscreteHausdorffDistance.h>
@@ -3000,6 +3000,44 @@ extern "C" {
     }
 
     Geometry*
+    GEOSMinimumBoundingCircle_r(GEOSContextHandle_t extHandle, const Geometry* g,
+        double* radius, Geometry** center)
+    {
+        if(0 == extHandle) {
+            return NULL;
+        }
+
+        GEOSContextHandleInternal_t* handle = 0;
+        handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
+        if(0 == handle->initialized) {
+            return NULL;
+        }
+
+        try {
+            geos::algorithm::MinimumBoundingCircle mc(g);
+            std::unique_ptr<Geometry> ret = mc.getCircle();
+            const GeometryFactory* gf = handle->geomFactory;
+            if(!ret) {
+                if (center) *center = NULL;
+                if (radius) *radius = 0.0;
+                return gf->createPolygon().release();
+            }
+            if (center) *center = static_cast<Geometry*>(gf->createPoint(mc.getCentre()));
+            if (radius) *radius = mc.getRadius();
+            ret->setSRID(g->getSRID());
+            return ret.release();
+        }
+        catch(const std::exception& e) {
+            handle->ERROR_MESSAGE("%s", e.what());
+        }
+        catch(...) {
+            handle->ERROR_MESSAGE("Unknown exception thrown");
+        }
+
+        return NULL;
+    }
+
+    Geometry*
     GEOSGeom_createEmptyCollection_r(GEOSContextHandle_t extHandle, int type)
     {
         if(0 == extHandle) {
diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am
index 40973c5..88c4816 100644
--- a/tests/unit/Makefile.am
+++ b/tests/unit/Makefile.am
@@ -87,6 +87,7 @@ geos_unit_SOURCES = \
 	capi/GEOSisValidDetailTest.cpp \
 	capi/GEOSLineString_PointTest.cpp \
 	capi/GEOSMakeValidTest.cpp \
+	capi/GEOSMinimumBoundingCircleTest.cpp \
 	capi/GEOSMinimumClearanceTest.cpp \
 	capi/GEOSMinimumRectangleTest.cpp \
 	capi/GEOSMinimumWidthTest.cpp \
diff --git a/tests/unit/capi/GEOSMinimumBoundingCircleTest.cpp b/tests/unit/capi/GEOSMinimumBoundingCircleTest.cpp
new file mode 100644
index 0000000..87165c3
--- /dev/null
+++ b/tests/unit/capi/GEOSMinimumBoundingCircleTest.cpp
@@ -0,0 +1,160 @@
+// $Id$
+//
+// Test Suite for C-API GEOSGetCentroid
+
+#include <tut/tut.hpp>
+// geos
+#include <geos_c.h>
+// std
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+namespace tut {
+//
+// Test Group
+//
+
+// Common data used in test cases.
+struct test_capiminimumboundingcircle_data {
+    GEOSGeometry* geom1_;
+    GEOSGeometry* geom2_;
+    GEOSGeometry* geom3_;
+    GEOSWKTWriter* wktw_;
+    char* wkt_;
+    double area_;
+
+    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_capiminimumboundingcircle_data()
+        : geom1_(nullptr), geom2_(nullptr), geom3_(nullptr), wkt_(nullptr)
+    {
+        initGEOS(notice, notice);
+        wktw_ = GEOSWKTWriter_create();
+        GEOSWKTWriter_setTrim(wktw_, 1);
+        GEOSWKTWriter_setRoundingPrecision(wktw_, 8);
+    }
+
+    ~test_capiminimumboundingcircle_data()
+    {
+        GEOSGeom_destroy(geom1_);
+        GEOSGeom_destroy(geom2_);
+        GEOSGeom_destroy(geom3_);
+        GEOSWKTWriter_destroy(wktw_);
+        GEOSFree(wkt_);
+        geom1_ = nullptr;
+        geom2_ = nullptr;
+        geom3_ = nullptr;
+        wkt_ = nullptr;
+        finishGEOS();
+    }
+
+};
+
+typedef test_group<test_capiminimumboundingcircle_data> group;
+typedef group::object object;
+
+group test_capiminimumboundingcircle_group("capi::GEOSMinimumBoundingCircle");
+
+//
+// Test Cases
+//
+
+// Single point
+template<>
+template<>
+void object::test<1>
+()
+{
+    geom1_ = GEOSGeomFromWKT("POINT(10 10)");
+    ensure(nullptr != geom1_);
+    geom2_ = GEOSMinimumBoundingCircle(geom1_, NULL, NULL);
+    ensure(nullptr != geom2_);
+
+    wkt_ = GEOSWKTWriter_write(wktw_, geom2_);
+
+    ensure_equals(std::string(wkt_), std::string("POINT (10 10)"));
+}
+
+template<>
+template<>
+void object::test<2>
+()
+{
+    geom1_ = GEOSGeomFromWKT("LINESTRING(0 10, 0 20)");
+    ensure(nullptr != geom1_);
+    geom2_ = GEOSMinimumBoundingCircle(geom1_, NULL, NULL);
+    ensure(nullptr != geom2_);
+    geom3_ = GEOSGeomFromWKT("POLYGON ((5 15, 4.9039264 14.024548, 4.6193977 13.086583, 4.1573481 12.222149, 3.5355339 11.464466, 2.7778512 10.842652, 1.9134172 10.380602, 0.97545161 10.096074, 8.0777229e-15 10, -0.97545161 10.096074, -1.9134172 10.380602, -2.7778512 10.842652, -3.5355339 11.464466, -4.1573481 12.222149, -4.6193977 13.086583, -4.9039264 14.024548, -5 15, -4.9039264 15.975452, -4.6193977 16.913417, -4.1573481 17.777851, -3.5355339 18.535534, -2.7778512 19.157348, -1.9134172 19.619398, -0.97545161 19.903926, -1.8682053e-14 20, 0.97545161 19.903926, 1.9134172 19.619398, 2.7778512 19.157348, 3.5355339 18.535534, 4.1573481 17.777851, 4.6193977 16.913417, 4.9039264 15.975452, 5 15))");
+    ensure(nullptr != geom3_);
+
+    // wkt_ = GEOSWKTWriter_write(wktw_, geom2_);
+
+    bool eq = GEOSEqualsExact(geom2_, geom3_, 0.0001);
+    ensure(eq);
+}
+
+template<>
+template<>
+void object::test<3>
+()
+{
+    geom1_ = GEOSGeomFromWKT("LINESTRING EMPTY");
+    ensure(nullptr != geom1_);
+    geom2_ = GEOSMinimumBoundingCircle(geom1_, NULL, NULL);
+    ensure(nullptr != geom2_);
+    geom3_ = GEOSGeomFromWKT("POLYGON EMPTY");
+    ensure(nullptr != geom3_);
+
+    // wkt_ = GEOSWKTWriter_write(wktw_, geom2_);
+    // std::cout << wkt_ << std::endl;
+
+    bool eq = GEOSEqualsExact(geom2_, geom3_, 0.0001);
+    ensure(eq);
+}
+
+template<>
+template<>
+void object::test<4>
+()
+{
+    GEOSGeometry* center;
+    GEOSGeometry* center_expected;
+    double radius;
+    geom1_ = GEOSGeomFromWKT("LINESTRING(0 10, 0 20)");
+    ensure(nullptr != geom1_);
+    geom2_ = GEOSMinimumBoundingCircle(geom1_, &radius, &center);
+    ensure(nullptr != geom2_);
+    geom3_ = GEOSGeomFromWKT("POLYGON ((5 15, 4.9039264 14.024548, 4.6193977 13.086583, 4.1573481 12.222149, 3.5355339 11.464466, 2.7778512 10.842652, 1.9134172 10.380602, 0.97545161 10.096074, 8.0777229e-15 10, -0.97545161 10.096074, -1.9134172 10.380602, -2.7778512 10.842652, -3.5355339 11.464466, -4.1573481 12.222149, -4.6193977 13.086583, -4.9039264 14.024548, -5 15, -4.9039264 15.975452, -4.6193977 16.913417, -4.1573481 17.777851, -3.5355339 18.535534, -2.7778512 19.157348, -1.9134172 19.619398, -0.97545161 19.903926, -1.8682053e-14 20, 0.97545161 19.903926, 1.9134172 19.619398, 2.7778512 19.157348, 3.5355339 18.535534, 4.1573481 17.777851, 4.6193977 16.913417, 4.9039264 15.975452, 5 15))");
+    ensure(nullptr != geom3_);
+    center_expected = GEOSGeomFromWKT("POINT(0 15)");
+
+    // wkt_ = GEOSWKTWriter_write(wktw_, geom2_);
+    // std::cout << wkt_ << std::endl;
+
+    bool eq;
+    eq = GEOSEqualsExact(geom2_, geom3_, 0.0001);
+    ensure(eq);
+
+    eq = GEOSEqualsExact(center, center_expected, 0.0001);
+    ensure(eq);
+    GEOSGeom_destroy(center);
+    GEOSGeom_destroy(center_expected);
+
+    ensure(fabs(radius) - 5.0 < 0.001);
+}
+
+} // namespace tut
+

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

Summary of changes:
 NEWS                                              |   1 +
 capi/geos_c.cpp                                   |   6 +
 capi/geos_c.h.in                                  |   5 +
 capi/geos_ts_c.cpp                                |  40 +++++-
 tests/unit/Makefile.am                            |   1 +
 tests/unit/capi/GEOSMinimumBoundingCircleTest.cpp | 160 ++++++++++++++++++++++
 6 files changed, 212 insertions(+), 1 deletion(-)
 create mode 100644 tests/unit/capi/GEOSMinimumBoundingCircleTest.cpp


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list