[geos-commits] [SCM] GEOS branch master updated. a6edac73e4c958d27369f8750133cab1c453275d

git at osgeo.org git at osgeo.org
Sun Sep 15 12:23:56 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  a6edac73e4c958d27369f8750133cab1c453275d (commit)
      from  2fbaf5707f11ed364bceddfd1960b8be3c28bdc5 (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 a6edac73e4c958d27369f8750133cab1c453275d
Author: Daniel Baston <dbaston at gmail.com>
Date:   Sun Sep 15 15:23:27 2019 -0400

    Improve MinimumDiameter
    
    - Address TODO to avoid unnecessary heap-allocation of Coordinate and
    LineSegment
    - Use unique_ptr to return pointers owned by caller

diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp
index 8ef1e12..9c8853f 100644
--- a/capi/geos_ts_c.cpp
+++ b/capi/geos_ts_c.cpp
@@ -1929,8 +1929,7 @@ extern "C" {
         try {
             geos::algorithm::MinimumDiameter m(g);
 
-            Geometry* g3 = m.getMinimumRectangle();
-            return g3;
+            return m.getMinimumRectangle().release();
         }
         catch(const std::exception& e) {
             handle->ERROR_MESSAGE("%s", e.what());
@@ -1958,8 +1957,7 @@ extern "C" {
         try {
             geos::algorithm::MinimumDiameter m(g);
 
-            Geometry* g3 = m.getDiameter();
-            return g3;
+            return m.getDiameter().release();
         }
         catch(const std::exception& e) {
             handle->ERROR_MESSAGE("%s", e.what());
diff --git a/include/geos/algorithm/MinimumDiameter.h b/include/geos/algorithm/MinimumDiameter.h
index 4917f30..8fb0622 100644
--- a/include/geos/algorithm/MinimumDiameter.h
+++ b/include/geos/algorithm/MinimumDiameter.h
@@ -20,6 +20,9 @@
 #ifndef GEOS_ALGORITHM_MINIMUMDIAMETER_H
 #define GEOS_ALGORITHM_MINIMUMDIAMETER_H
 
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/LineSegment.h>
+
 #include <memory>
 #include <geos/export.h>
 
@@ -27,9 +30,7 @@
 namespace geos {
 namespace geom {
 class Geometry;
-class LineSegment;
 class LineString;
-class Coordinate;
 class CoordinateSequence;
 }
 }
@@ -66,9 +67,9 @@ private:
 
     std::unique_ptr<geom::CoordinateSequence> convexHullPts;
 
-    geom::LineSegment* minBaseSeg;
-    geom::Coordinate* minWidthPt;
-    int minPtIndex;
+    geom::LineSegment minBaseSeg;
+    geom::Coordinate minWidthPt;
+    size_t minPtIndex;
     double minWidth;
     void computeMinimumDiameter();
     void computeWidthConvex(const geom::Geometry* geom);
@@ -83,7 +84,7 @@ private:
     void computeConvexRingMinDiameter(const geom::CoordinateSequence* pts);
 
     unsigned int findMaxPerpDistance(const geom::CoordinateSequence* pts,
-                                     geom::LineSegment* seg, unsigned int startIndex);
+                                     const geom::LineSegment* seg, unsigned int startIndex);
 
     static unsigned int getNextIndex(const geom::CoordinateSequence* pts,
                                      unsigned int index);
@@ -93,7 +94,7 @@ private:
     static geom::LineSegment computeSegmentForLine(double a, double b, double c);
 
 public:
-    ~MinimumDiameter();
+    ~MinimumDiameter() = default;
 
     /** \brief
      * Compute a minimum diameter for a given [Geometry](@ref geom::Geometry).
@@ -126,21 +127,21 @@ public:
      *
      * @return a coordinate forming one end of the minimum diameter
      */
-    geom::Coordinate* getWidthCoordinate();
+    const geom::Coordinate& getWidthCoordinate();
 
     /** \brief
      * Gets the segment forming the base of the minimum diameter.
      *
      * @return the segment forming the base of the minimum diameter
      */
-    geom::LineString* getSupportingSegment();
+    std::unique_ptr<geom::LineString> getSupportingSegment();
 
     /** \brief
      * Gets a LineString which is a minimum diameter.
      *
      * @return a LineString which is a minimum diameter
      */
-    geom::LineString* getDiameter();
+    std::unique_ptr<geom::LineString> getDiameter();
 
     /** \brief
      * Gets the minimum rectangular Polygon which encloses the input geometry.
@@ -153,7 +154,7 @@ public:
      *
      * @return the minimum rectangle enclosing the input (or a line or point if degenerate)
      */
-    geom::Geometry* getMinimumRectangle();
+    std::unique_ptr<geom::Geometry> getMinimumRectangle();
 
     /** \brief
      * Gets the minimum rectangle enclosing a geometry.
@@ -161,14 +162,14 @@ public:
      * @param geom the geometry
      * @return the minimum rectangle enclosing the geometry
     */
-    static geom::Geometry* getMinimumRectangle(geom::Geometry* geom);
+    static std::unique_ptr<geom::Geometry> getMinimumRectangle(geom::Geometry* geom);
 
     /** \brief
      * 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);
+    static std::unique_ptr<geom::Geometry> getMinimumDiameter(geom::Geometry* geom);
 
 };
 
diff --git a/src/algorithm/MinimumDiameter.cpp b/src/algorithm/MinimumDiameter.cpp
index 31ceb24..e53ef17 100644
--- a/src/algorithm/MinimumDiameter.cpp
+++ b/src/algorithm/MinimumDiameter.cpp
@@ -15,11 +15,6 @@
  *
  * Last port: algorithm/MinimumDiameter.java r966
  *
- **********************************************************************
- *
- * TODO:
- * 	- avoid heap allocation for LineSegment and Coordinate
- *
  **********************************************************************/
 
 #include <geos/constants.h>
@@ -68,8 +63,7 @@ namespace algorithm { // geos.algorithm
  */
 MinimumDiameter::MinimumDiameter(const Geometry* newInputGeom)
 {
-    minBaseSeg = new LineSegment();
-    minWidthPt = nullptr;
+    minWidthPt = Coordinate::getNull();
     minPtIndex = 0;
     minWidth = 0.0;
     inputGeom = newInputGeom;
@@ -89,20 +83,13 @@ MinimumDiameter::MinimumDiameter(const Geometry* newInputGeom)
  */
 MinimumDiameter::MinimumDiameter(const Geometry* newInputGeom, const bool newIsConvex)
 {
-    minBaseSeg = new LineSegment();
-    minWidthPt = nullptr;
+    minWidthPt = Coordinate::getNull();
     minWidth = 0.0;
     inputGeom = newInputGeom;
     isConvex = newIsConvex;
     convexHullPts = nullptr;
 }
 
-MinimumDiameter::~MinimumDiameter()
-{
-    delete minBaseSeg;
-    delete minWidthPt;
-}
-
 /**
  * Gets the length of the minimum diameter of the input Geometry
  *
@@ -120,7 +107,7 @@ MinimumDiameter::getLength()
  *
  * @return a coordinate forming one end of the minimum diameter
  */
-Coordinate*
+const Coordinate&
 MinimumDiameter::getWidthCoordinate()
 {
     computeMinimumDiameter();
@@ -132,15 +119,12 @@ MinimumDiameter::getWidthCoordinate()
  *
  * @return the segment forming the base of the minimum diameter
  */
-LineString*
+std::unique_ptr<LineString>
 MinimumDiameter::getSupportingSegment()
 {
     computeMinimumDiameter();
     const GeometryFactory* fact = inputGeom->getFactory();
-    auto cl = fact->getCoordinateSequenceFactory()->create(2);
-    cl->setAt(minBaseSeg->p0, 0);
-    cl->setAt(minBaseSeg->p1, 1);
-    return fact->createLineString(cl.release());
+    return minBaseSeg.toGeometry(*fact);
 }
 
 /**
@@ -148,22 +132,22 @@ MinimumDiameter::getSupportingSegment()
  *
  * @return a LineString which is a minimum diameter
  */
-LineString*
+std::unique_ptr<LineString>
 MinimumDiameter::getDiameter()
 {
     computeMinimumDiameter();
     // return empty linestring if no minimum width calculated
-    if(minWidthPt == nullptr) {
-        return inputGeom->getFactory()->createLineString(nullptr);
+    if(minWidthPt.isNull()) {
+        return std::unique_ptr<LineString>(inputGeom->getFactory()->createLineString(nullptr));
     }
 
     Coordinate basePt;
-    minBaseSeg->project(*minWidthPt, basePt);
+    minBaseSeg.project(minWidthPt, basePt);
 
     auto cl = inputGeom->getFactory()->getCoordinateSequenceFactory()->create(2);
     cl->setAt(basePt, 0);
-    cl->setAt(*minWidthPt, 1);
-    return inputGeom->getFactory()->createLineString(cl.release());
+    cl->setAt(minWidthPt, 1);
+    return inputGeom->getFactory()->createLineString(std::move(cl));
 }
 
 /* private */
@@ -171,7 +155,7 @@ void
 MinimumDiameter::computeMinimumDiameter()
 {
     // check if computation is cached
-    if(minWidthPt != nullptr) {
+    if(minWidthPt.isNull()) {
         return;
     }
     if(isConvex) {
@@ -201,25 +185,20 @@ MinimumDiameter::computeWidthConvex(const Geometry* geom)
     switch(convexHullPts->getSize()) {
     case 0:
         minWidth = 0.0;
-        delete minWidthPt;
-        minWidthPt = nullptr;
-        delete minBaseSeg;
-        minBaseSeg = nullptr;
+        minWidthPt = Coordinate::getNull();
         break;
     case 1:
         minWidth = 0.0;
-        delete minWidthPt;
-        minWidthPt = new Coordinate(convexHullPts->getAt(0));
-        minBaseSeg->p0 = convexHullPts->getAt(0);
-        minBaseSeg->p1 = convexHullPts->getAt(0);
+        minWidthPt = convexHullPts->getAt(0);
+        minBaseSeg.p0 = convexHullPts->getAt(0);
+        minBaseSeg.p1 = convexHullPts->getAt(0);
         break;
     case 2:
     case 3:
         minWidth = 0.0;
-        delete minWidthPt;
-        minWidthPt = new Coordinate(convexHullPts->getAt(0));
-        minBaseSeg->p0 = convexHullPts->getAt(0);
-        minBaseSeg->p1 = convexHullPts->getAt(1);
+        minWidthPt = convexHullPts->getAt(0);
+        minBaseSeg.p0 = convexHullPts->getAt(0);
+        minBaseSeg.p1 = convexHullPts->getAt(1);
         break;
     default:
         computeConvexRingMinDiameter(convexHullPts.get());
@@ -251,7 +230,7 @@ MinimumDiameter::computeConvexRingMinDiameter(const CoordinateSequence* pts)
 
 unsigned int
 MinimumDiameter::findMaxPerpDistance(const CoordinateSequence* pts,
-                                     LineSegment* seg, unsigned int startIndex)
+                                     const LineSegment* seg, unsigned int startIndex)
 {
     double maxPerpDistance = seg->distancePerpendicular(pts->getAt(startIndex));
     double nextPerpDistance = maxPerpDistance;
@@ -268,12 +247,8 @@ MinimumDiameter::findMaxPerpDistance(const CoordinateSequence* pts,
     if(maxPerpDistance < minWidth) {
         minPtIndex = maxIndex;
         minWidth = maxPerpDistance;
-        delete minWidthPt;
-        minWidthPt = new Coordinate(pts->getAt(minPtIndex));
-        delete minBaseSeg;
-        minBaseSeg = new LineSegment(*seg);
-//      System.out.println(minBaseSeg);
-//      System.out.println(minWidth);
+        minWidthPt = pts->getAt(minPtIndex);
+        minBaseSeg = *seg;
     }
     return maxIndex;
 }
@@ -288,27 +263,27 @@ MinimumDiameter::getNextIndex(const CoordinateSequence* pts,
     return index;
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 MinimumDiameter::getMinimumRectangle()
 {
     computeMinimumDiameter();
 
-    if(!minBaseSeg || !convexHullPts) {
+    if(minWidthPt.isNull() || !convexHullPts) {
         //return empty polygon
-        return inputGeom->getFactory()->createPolygon();
+        return std::unique_ptr<Geometry>(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);
+        if(minBaseSeg.p0.equals2D(minBaseSeg.p1)) {
+            return std::unique_ptr<Geometry>(inputGeom->getFactory()->createPoint(minBaseSeg.p0));
         }
-        return minBaseSeg->toGeometry(*inputGeom->getFactory()).release();
+        return minBaseSeg.toGeometry(*inputGeom->getFactory());
     }
 
     // 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 dx = minBaseSeg.p1.x - minBaseSeg.p0.x;
+    double dy = minBaseSeg.p1.y - minBaseSeg.p0.y;
 
     double minPara = DoubleMax;
     double maxPara = -DoubleMax;
@@ -358,8 +333,8 @@ MinimumDiameter::getMinimumRectangle()
     seq->setAt(p3, 3);
     seq->setAt(p0, 4); // close
 
-    LinearRing* shell = inputGeom->getFactory()->createLinearRing(seq.release());
-    return inputGeom->getFactory()->createPolygon(shell, nullptr);
+    std::unique_ptr<LinearRing> shell = inputGeom->getFactory()->createLinearRing(std::move(seq));
+    return inputGeom->getFactory()->createPolygon(std::move(shell));
 }
 
 double
@@ -390,14 +365,14 @@ MinimumDiameter::computeSegmentForLine(double a, double b, double c)
 }
 
 
-Geometry*
+std::unique_ptr<Geometry>
 MinimumDiameter::getMinimumRectangle(Geometry* geom)
 {
     MinimumDiameter md(geom);
     return md.getMinimumRectangle();
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 MinimumDiameter::getMinimumDiameter(Geometry* geom)
 {
     MinimumDiameter md(geom);

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

Summary of changes:
 capi/geos_ts_c.cpp                       |  6 +--
 include/geos/algorithm/MinimumDiameter.h | 27 +++++-----
 src/algorithm/MinimumDiameter.cpp        | 93 ++++++++++++--------------------
 3 files changed, 50 insertions(+), 76 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list