[geos-commits] [SCM] GEOS branch master updated. 9f2a3599a2977ea8ce0658395f8f668cfb1c4ca3

git at osgeo.org git at osgeo.org
Wed May 29 11:33:43 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  9f2a3599a2977ea8ce0658395f8f668cfb1c4ca3 (commit)
       via  90255637d901193bf98df0277c623d5f29a81047 (commit)
       via  5e30698c1fa0af43fa478724ac2aad32fb7d8207 (commit)
       via  76f5141f726cfa0837e340b787a6599e48b9028c (commit)
       via  8dbb4b3e3dccba5aec12871c7370bbee0c50673d (commit)
       via  5f3878a0a69e67a814e3fdcf1e897174269ac337 (commit)
       via  ff168c6e41ba7463f856b33af83c722c001361aa (commit)
       via  f6a46726cad6748f0304c1748701fc63f8d7ce3c (commit)
       via  fc8ff4b33182759608e5a54ace7461d22246240c (commit)
       via  a7a25f45cc563172ff64d5ad0f6190090c53f723 (commit)
      from  2084a8033f1644460bc832b84e3a3d30174658ce (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 9f2a3599a2977ea8ce0658395f8f668cfb1c4ca3
Author: Daniel Baston <dbaston at gmail.com>
Date:   Wed May 29 14:05:06 2019 -0400

    Fix compilation with gcc 4.8

diff --git a/src/algorithm/ConvexHull.cpp b/src/algorithm/ConvexHull.cpp
index 069fd81..addadb4 100644
--- a/src/algorithm/ConvexHull.cpp
+++ b/src/algorithm/ConvexHull.cpp
@@ -352,7 +352,7 @@ ConvexHull::lineOrPolygon(const Coordinate::ConstVect& input)
     if(cleaned.size() == 3) { // shouldn't this be 2 ??
         cleaned.resize(2);
         auto cl1 = toCoordinateSequence(cleaned);
-        std::unique_ptr<LineString> ret(geomFactory->createLineString(cl1.release()));
+        std::unique_ptr<Geometry> ret(geomFactory->createLineString(cl1.release()));
         return ret;
     }
     auto cl2 = toCoordinateSequence(cleaned);

commit 90255637d901193bf98df0277c623d5f29a81047
Author: Daniel Baston <dbaston at gmail.com>
Date:   Wed May 29 14:01:49 2019 -0400

    Fix compilation of example.cpp

diff --git a/doc/example.cpp b/doc/example.cpp
index 081d711..a7c18fa 100644
--- a/doc/example.cpp
+++ b/doc/example.cpp
@@ -105,7 +105,7 @@ WKBtest(vector<Geometry*>* geoms)
 #endif
 
 
-    unsigned int ngeoms = geoms->size();
+    size_t ngeoms = geoms->size();
     for(unsigned int i = 0; i < ngeoms; ++i) {
         Geometry* gin = (*geoms)[i];
 
@@ -467,7 +467,7 @@ do_all()
     newgeoms = new vector<Geometry*>;
     for(unsigned int i = 0; i < geoms->size(); i++) {
         Geometry* g = (*geoms)[i];
-        newgeoms->push_back(g->getCentroid());
+        newgeoms->push_back(g->getCentroid().release());
     }
 
     // Print all convex hulls
@@ -488,7 +488,7 @@ do_all()
     for(unsigned int i = 0; i < geoms->size(); i++) {
         Geometry* g = (*geoms)[i];
         try {
-            Geometry* g2 = g->buffer(10);
+            Geometry* g2 = g->buffer(10).release();
             newgeoms->push_back(g2);
         }
         catch(const GEOSException& exc) {
@@ -512,7 +512,7 @@ do_all()
     newgeoms = new vector<Geometry*>;
     for(unsigned int i = 0; i < geoms->size(); i++) {
         Geometry* g = (*geoms)[i];
-        newgeoms->push_back(g->convexHull());
+        newgeoms->push_back(g->convexHull().release());
     }
 
     // Print all convex hulls
@@ -790,7 +790,6 @@ do_all()
         cout << "      [" << i << "]\t";
         for(unsigned int j = 0; j < geoms->size(); j++) {
             Geometry* g2 = (*geoms)[j];
-            IntersectionMatrix* im = NULL;
             try {
                 // second argument is intersectionPattern
                 string pattern = "212101212";
@@ -802,8 +801,7 @@ do_all()
                 }
 
                 // get the intersectionMatrix itself
-                im = g1->relate(g2);
-                delete im; // delete afterwards
+                auto im = g1->relate(g2);
             }
             // Geometry Collection is not a valid argument
             catch(const IllegalArgumentException& exc) {
@@ -944,7 +942,7 @@ do_all()
         for(unsigned int j = i + 1; j < geoms->size(); j++) {
             Geometry* g2 = (*geoms)[j];
             try {
-                Geometry* g3 = g1->Union(g2);
+                Geometry* g3 = g1->Union(g2).release();
                 newgeoms->push_back(g3);
             }
             // It's illegal to union a collection ...
@@ -979,7 +977,7 @@ do_all()
         for(unsigned int j = i + 1; j < geoms->size(); j++) {
             Geometry* g2 = (*geoms)[j];
             try {
-                Geometry* g3 = g1->intersection(g2);
+                Geometry* g3 = g1->intersection(g2).release();
                 newgeoms->push_back(g3);
             }
             // Collection are illegal as intersection argument
@@ -1012,7 +1010,7 @@ do_all()
         for(unsigned int j = i + 1; j < geoms->size(); j++) {
             Geometry* g2 = (*geoms)[j];
             try {
-                Geometry* g3 = g1->difference(g2);
+                Geometry* g3 = g1->difference(g2).release();
                 newgeoms->push_back(g3);
             }
             // Collection are illegal as difference argument
@@ -1045,7 +1043,7 @@ do_all()
         for(unsigned int j = i + 1; j < geoms->size(); j++) {
             Geometry* g2 = (*geoms)[j];
             try {
-                Geometry* g3 = g1->symDifference(g2);
+                Geometry* g3 = g1->symDifference(g2).release();
                 newgeoms->push_back(g3);
             }
             // Collection are illegal as symdifference argument

commit 5e30698c1fa0af43fa478724ac2aad32fb7d8207
Author: Daniel Baston <dbaston at gmail.com>
Date:   Tue May 28 21:37:09 2019 -0400

    Return unique_ptr from Geometry overlay, buffer methods
    
    Also make these methods non-virtual, since Geometry subclasses have no
    overriding implementations.

diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp
index b824506..896ce1d 100644
--- a/capi/geos_ts_c.cpp
+++ b/capi/geos_ts_c.cpp
@@ -1703,7 +1703,7 @@ extern "C" {
         }
 
         try {
-            return g1->intersection(g2);
+            return g1->intersection(g2).release();
         }
         catch(const std::exception& e) {
             handle->ERROR_MESSAGE("%s", e.what());
@@ -1729,7 +1729,7 @@ extern "C" {
         }
 
         try {
-            Geometry* g3 = g1->buffer(width, quadrantsegments);
+            Geometry* g3 = g1->buffer(width, quadrantsegments).release();
             return g3;
         }
         catch(const std::exception& e) {
@@ -2040,7 +2040,7 @@ extern "C" {
         }
 
         try {
-            return g1->difference(g2);
+            return g1->difference(g2).release();
         }
         catch(const std::exception& e) {
             handle->ERROR_MESSAGE("%s", e.what());
@@ -2093,7 +2093,7 @@ extern "C" {
         }
 
         try {
-            return g1->symDifference(g2);
+            return g1->symDifference(g2).release();
         }
         catch(const std::exception& e) {
             handle->ERROR_MESSAGE("%s", e.what());
@@ -2120,7 +2120,7 @@ extern "C" {
         }
 
         try {
-            return g1->Union(g2);
+            return g1->Union(g2).release();
         }
         catch(const std::exception& e) {
 #if VERBOSE_EXCEPTIONS
diff --git a/include/geos/algorithm/MinimumBoundingCircle.h b/include/geos/algorithm/MinimumBoundingCircle.h
index cc99891..1e62c56 100644
--- a/include/geos/algorithm/MinimumBoundingCircle.h
+++ b/include/geos/algorithm/MinimumBoundingCircle.h
@@ -81,7 +81,7 @@ public:
     *
     * @return a Geometry representing the Minimum Bounding Circle.
     */
-    geom::Geometry* getCircle();
+    std::unique_ptr<geom::Geometry> getCircle();
 
     /**
     * Gets a geometry representing a line between the two farthest points
diff --git a/include/geos/geom/BinaryOp.h b/include/geos/geom/BinaryOp.h
index b136627..d0f81ae 100644
--- a/include/geos/geom/BinaryOp.h
+++ b/include/geos/geom/BinaryOp.h
@@ -298,8 +298,10 @@ SnapOp(const Geometry* g0, const Geometry* g1, BinOp _Op)
 #endif
 
     // Now remove common bits
-    GeomPtr rG0(cbr.removeCommonBits(g0->clone().release()));
-    GeomPtr rG1(cbr.removeCommonBits(g1->clone().release()));
+    GeomPtr rG0 = g0->clone();
+    cbr.removeCommonBits(rG0.get());
+    GeomPtr rG1 = g1->clone();
+    cbr.removeCommonBits(rG1.get());
 
 #if GEOS_DEBUG_BINARYOP
     check_valid(*rG0, "CBR: removed-bits geom 0");
@@ -399,8 +401,11 @@ BinaryOp(const Geometry* g0, const Geometry* g1, BinOp _Op)
         cbr.add(g0);
         cbr.add(g1);
 
-        rG0.reset(cbr.removeCommonBits(g0->clone().release()));
-        rG1.reset(cbr.removeCommonBits(g1->clone().release()));
+        rG0 = g0->clone();
+        cbr.removeCommonBits(rG0.get());
+
+        rG1 = g1->clone();
+        cbr.removeCommonBits(rG1.get());
 
 #if GEOS_DEBUG_BINARYOP
         check_valid(*rG0, "CBR: geom 0 (after common-bits removal)");
diff --git a/include/geos/geom/Geometry.h b/include/geos/geom/Geometry.h
index ec474a9..f6fa6e3 100644
--- a/include/geos/geom/Geometry.h
+++ b/include/geos/geom/Geometry.h
@@ -573,19 +573,19 @@ public:
     virtual std::string toText() const;
 
     /// Returns a buffer region around this Geometry having the given width.
-    //
+    ///
     /// @throws util::TopologyException if a robustness error occurs
     ///
-    virtual Geometry* buffer(double distance) const;
+    std::unique_ptr<Geometry> buffer(double distance) const;
 
     /// \brief
     /// Returns a buffer region around this Geometry having the
     /// given width and with a specified number of segments used
     /// to approximate curves.
-    //
+    ///
     /// @throws util::TopologyException if a robustness error occurs
     ///
-    virtual Geometry* buffer(double distance, int quadrantSegments) const;
+    std::unique_ptr<Geometry> buffer(double distance, int quadrantSegments) const;
 
     /** \brief
      * Computes a buffer area around this geometry having the given
@@ -623,7 +623,7 @@ public:
      *
      * @see BufferOp
      */
-    virtual Geometry* buffer(double distance, int quadrantSegments,
+    std::unique_ptr<Geometry> buffer(double distance, int quadrantSegments,
                              int endCapStyle) const;
 
     /// \brief
@@ -648,7 +648,7 @@ public:
      *         non-empty GeometryCollection
      *
      */
-    virtual Geometry* intersection(const Geometry* other) const;
+    std::unique_ptr<Geometry> intersection(const Geometry* other) const;
 
     /** \brief
      * Returns a Geometry representing all the points in this Geometry
@@ -659,7 +659,7 @@ public:
      *         non-empty GeometryCollection
      *
      */
-    Geometry* Union(const Geometry* other) const;
+    std::unique_ptr<Geometry> Union(const Geometry* other) const;
     // throw(IllegalArgumentException *, TopologyException *);
 
     /**
@@ -692,7 +692,7 @@ public:
      *         non-empty GeometryCollection
      *
      */
-    virtual Geometry* difference(const Geometry* other) const;
+    std::unique_ptr<Geometry> difference(const Geometry* other) const;
 
     /** \brief
      * Returns a set combining the points in this Geometry not in other,
@@ -703,7 +703,7 @@ public:
      *         non-empty GeometryCollection
      *
      */
-    virtual Geometry* symDifference(const Geometry* other) const;
+    std::unique_ptr<Geometry> symDifference(const Geometry* other) const;
 
     /** \brief
      * Returns true iff the two Geometrys are of the same type and their
@@ -873,15 +873,6 @@ protected:
                double tolerance) const;
     int SRID;
 
-    /// @deprecated
-    //Geometry* toInternalGeometry(const Geometry *g) const;
-
-    /// @deprecated
-    //Geometry* fromInternalGeometry(const Geometry *g) const;
-
-    /// Polygon overrides to check for actual rectangle
-    //virtual bool isRectangle() const { return false; } -- moved to public
-
     Geometry(const Geometry& geom);
 
     /** \brief
@@ -911,7 +902,7 @@ private:
     static GeometryChangedFilter geometryChangedFilter;
 
     /// The GeometryFactory used to create this Geometry
-    //
+    ///
     /// Externally owned
     ///
     const GeometryFactory* _factory;
diff --git a/include/geos/geom/util/Densifier.h b/include/geos/geom/util/Densifier.h
index c577bc6..c78144a 100644
--- a/include/geos/geom/util/Densifier.h
+++ b/include/geos/geom/util/Densifier.h
@@ -76,7 +76,7 @@ private:
         CoordinateSequence::Ptr transformCoordinates(const CoordinateSequence* coords, const Geometry* parent) override;
         Geometry::Ptr transformPolygon(const Polygon* geom, const Geometry* parent) override;
         Geometry::Ptr transformMultiPolygon(const MultiPolygon* geom, const Geometry* parent) override;
-        Geometry* createValidArea(const Geometry* roughAreaGeom);
+        Geometry::Ptr createValidArea(const Geometry* roughAreaGeom);
     };
 
 }; // Densifier
diff --git a/include/geos/precision/CommonBitsOp.h b/include/geos/precision/CommonBitsOp.h
index 9240388..435c6c9 100644
--- a/include/geos/precision/CommonBitsOp.h
+++ b/include/geos/precision/CommonBitsOp.h
@@ -63,7 +63,7 @@ private:
      * @return a copy of the input Geometry with common bits removed
      *         (caller takes responsibility of its deletion)
      */
-    geom::Geometry* removeCommonBits(const geom::Geometry* geom0);
+    std::unique_ptr<geom::Geometry> removeCommonBits(const geom::Geometry* geom0);
 
     /** \brief
      *
@@ -98,7 +98,7 @@ public:
      * @return the Geometry representing the set-theoretic
      *  intersection of the input Geometries.
      */
-    geom::Geometry* intersection(
+    std::unique_ptr<geom::Geometry> intersection(
         const geom::Geometry* geom0,
         const geom::Geometry* geom1);
 
@@ -110,7 +110,7 @@ public:
      * @return the Geometry representing the set-theoretic union
      * of the input Geometries.
      */
-    geom::Geometry* Union(
+    std::unique_ptr<geom::Geometry> Union(
         const geom::Geometry* geom0,
         const geom::Geometry* geom1);
 
@@ -122,7 +122,7 @@ public:
      * @return the Geometry representing the set-theoretic difference
      * of the input Geometries.
      */
-    geom::Geometry* difference(
+    std::unique_ptr<geom::Geometry> difference(
         const geom::Geometry* geom0,
         const geom::Geometry* geom1);
 
@@ -134,7 +134,7 @@ public:
      * @return the Geometry representing the set-theoretic symmetric
      * difference of the input Geometries.
      */
-    geom::Geometry* symDifference(
+    std::unique_ptr<geom::Geometry> symDifference(
         const geom::Geometry* geom0,
         const geom::Geometry* geom1);
 
@@ -145,7 +145,7 @@ public:
      * @param distance the buffer distance
      * @return the Geometry representing the buffer of the input Geometry.
      */
-    geom::Geometry* buffer(
+    std::unique_ptr<geom::Geometry> buffer(
         const geom::Geometry* geom0,
         double distance);
 
@@ -160,8 +160,8 @@ public:
      * @param result the result Geometry to modify
      * @return the result Geometry with the required precision
      */
-    geom::Geometry* computeResultPrecision(
-        geom::Geometry* result);
+    std::unique_ptr<geom::Geometry> computeResultPrecision(
+        std::unique_ptr<geom::Geometry> result);
 };
 
 } // namespace geos.precision
diff --git a/include/geos/precision/CommonBitsRemover.h b/include/geos/precision/CommonBitsRemover.h
index a723b1f..a493b93 100644
--- a/include/geos/precision/CommonBitsRemover.h
+++ b/include/geos/precision/CommonBitsRemover.h
@@ -74,7 +74,7 @@ public:
      *             coordinate bits
      * @return the shifted Geometry
      */
-    geom::Geometry* removeCommonBits(geom::Geometry* geom);
+    void removeCommonBits(geom::Geometry* geom);
 
     /** \brief
      * Adds the common coordinate bits back into a Geometry.
diff --git a/include/geos/precision/EnhancedPrecisionOp.h b/include/geos/precision/EnhancedPrecisionOp.h
index df8ba79..6860be8 100644
--- a/include/geos/precision/EnhancedPrecisionOp.h
+++ b/include/geos/precision/EnhancedPrecisionOp.h
@@ -21,13 +21,9 @@
 
 #include <geos/export.h>
 #include <geos/constants.h> // for int64
+#include <geos/geom/Geometry.h>
 
-// Forward declarations
-namespace geos {
-namespace geom {
-class Geometry;
-}
-}
+#include <memory>
 
 namespace geos {
 namespace precision { // geos.precision
@@ -50,7 +46,7 @@ public:
      * @return the Geometry representing the set-theoretic
      * intersection of the input Geometries.
      */
-    static geom::Geometry* intersection(
+    static std::unique_ptr<geom::Geometry> intersection(
         const geom::Geometry* geom0,
         const geom::Geometry* geom1);
 
@@ -62,7 +58,7 @@ public:
      * @return the Geometry representing the set-theoretic
      * union of the input Geometries.
      */
-    static geom::Geometry* Union(
+    static std::unique_ptr<geom::Geometry> Union(
         const geom::Geometry* geom0,
         const geom::Geometry* geom1);
 
@@ -74,7 +70,7 @@ public:
      * @return the Geometry representing the set-theoretic
      * difference of the input Geometries.
      */
-    static geom::Geometry* difference(
+    static std::unique_ptr<geom::Geometry> difference(
         const geom::Geometry* geom0,
         const geom::Geometry* geom1);
 
@@ -86,7 +82,7 @@ public:
      * @return the Geometry representing the set-theoretic symmetric
      * difference of the input Geometries.
      */
-    static geom::Geometry* symDifference(
+    static std::unique_ptr<geom::Geometry> symDifference(
         const geom::Geometry* geom0,
         const geom::Geometry* geom1);
 
@@ -99,7 +95,7 @@ public:
      * @param distance the buffer distance
      * @return the Geometry representing the buffer of the input Geometry.
      */
-    static geom::Geometry* buffer(
+    static std::unique_ptr<geom::Geometry> buffer(
         const geom::Geometry* geom,
         double distance);
 };
diff --git a/src/algorithm/MinimumBoundingCircle.cpp b/src/algorithm/MinimumBoundingCircle.cpp
index 57f6776..6594537 100644
--- a/src/algorithm/MinimumBoundingCircle.cpp
+++ b/src/algorithm/MinimumBoundingCircle.cpp
@@ -42,7 +42,7 @@ namespace geos {
 namespace algorithm { // geos.algorithm
 
 /*public*/
-Geometry*
+std::unique_ptr<Geometry>
 MinimumBoundingCircle::getCircle()
 {
     //TODO: ensure the output circle contains the extermal points.
@@ -50,9 +50,9 @@ MinimumBoundingCircle::getCircle()
 
     compute();
     if(centre.isNull()) {
-        return input->getFactory()->createPolygon();
+        return std::unique_ptr<Geometry>(input->getFactory()->createPolygon());
     }
-    Point* centrePoint = input->getFactory()->createPoint(centre);
+    std::unique_ptr<Geometry> centrePoint(input->getFactory()->createPoint(centre));
     if(radius == 0.0) {
         return centrePoint;
     }
diff --git a/src/geom/Geometry.cpp b/src/geom/Geometry.cpp
index 9db27b6..c466552 100644
--- a/src/geom/Geometry.cpp
+++ b/src/geom/Geometry.cpp
@@ -521,22 +521,22 @@ Geometry::toText() const
     return writer.write(this);
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 Geometry::buffer(double p_distance) const
 {
-    return BufferOp::bufferOp(this, p_distance);
+    return std::unique_ptr<Geometry>(BufferOp::bufferOp(this, p_distance));
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 Geometry::buffer(double p_distance, int quadrantSegments) const
 {
-    return BufferOp::bufferOp(this, p_distance, quadrantSegments);
+    return std::unique_ptr<Geometry>(BufferOp::bufferOp(this, p_distance, quadrantSegments));
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 Geometry::buffer(double p_distance, int quadrantSegments, int endCapStyle) const
 {
-    return BufferOp::bufferOp(this, p_distance, quadrantSegments, endCapStyle);
+    return std::unique_ptr<Geometry>(BufferOp::bufferOp(this, p_distance, quadrantSegments, endCapStyle));
 }
 
 std::unique_ptr<Geometry>
@@ -545,7 +545,7 @@ Geometry::convexHull() const
     return ConvexHull(this).getConvexHull();
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 Geometry::intersection(const Geometry* other) const
 {
     /**
@@ -554,7 +554,7 @@ Geometry::intersection(const Geometry* other) const
 
     // special case: if one input is empty ==> empty
     if(isEmpty() || other->isEmpty()) {
-        return getFactory()->createGeometryCollection();
+        return std::unique_ptr<Geometry>(getFactory()->createGeometryCollection());
     }
 
 #ifdef USE_RECTANGLE_INTERSECTION
@@ -575,24 +575,20 @@ Geometry::intersection(const Geometry* other) const
     }
 #endif
 
-    return BinaryOp(this, other, overlayOp(OverlayOp::opINTERSECTION)).release();
+    return BinaryOp(this, other, overlayOp(OverlayOp::opINTERSECTION));
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 Geometry::Union(const Geometry* other) const
-//throw(TopologyException *, IllegalArgumentException *)
 {
-
     // special case: if one input is empty ==> other input
     if(isEmpty()) {
-        return other->clone().release();
+        return other->clone();
     }
     if(other->isEmpty()) {
-        return clone().release();
+        return clone();
     }
 
-    Geometry* out = nullptr;
-
 #ifdef SHORTCIRCUIT_PREDICATES
     // if envelopes are disjoint return a MULTI geom or
     // a geometrycollection
@@ -626,12 +622,12 @@ Geometry::Union(const Geometry* other) const
             v->push_back(other->clone().release());
         }
 
-        out = _factory->buildGeometry(v);
+        std::unique_ptr<Geometry>out(_factory->buildGeometry(v));
         return out;
     }
 #endif
 
-    return BinaryOp(this, other, overlayOp(OverlayOp::opUNION)).release();
+    return BinaryOp(this, other, overlayOp(OverlayOp::opUNION));
 }
 
 /* public */
@@ -642,30 +638,30 @@ Geometry::Union() const
     return UnaryUnionOp::Union(*this);
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 Geometry::difference(const Geometry* other) const
 //throw(IllegalArgumentException *)
 {
     // special case: if A.isEmpty ==> empty; if B.isEmpty ==> A
     if(isEmpty()) {
-        return getFactory()->createGeometryCollection();
+        return std::unique_ptr<Geometry>(getFactory()->createGeometryCollection());
     }
     if(other->isEmpty()) {
-        return clone().release();
+        return clone();
     }
 
-    return BinaryOp(this, other, overlayOp(OverlayOp::opDIFFERENCE)).release();
+    return BinaryOp(this, other, overlayOp(OverlayOp::opDIFFERENCE));
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 Geometry::symDifference(const Geometry* other) const
 {
     // special case: if either input is empty ==> other input
     if(isEmpty()) {
-        return other->clone().release();
+        return other->clone();
     }
     if(other->isEmpty()) {
-        return clone().release();
+        return clone();
     }
 
     // if envelopes are disjoint return a MULTI geom or
@@ -699,10 +695,10 @@ Geometry::symDifference(const Geometry* other) const
             v->push_back(other->clone().release());
         }
 
-        return _factory->buildGeometry(v);
+        return std::unique_ptr<Geometry>(_factory->buildGeometry(v));
     }
 
-    return BinaryOp(this, other, overlayOp(OverlayOp::opSYMDIFFERENCE)).release();
+    return BinaryOp(this, other, overlayOp(OverlayOp::opSYMDIFFERENCE));
 }
 
 int
diff --git a/src/geom/util/Densifier.cpp b/src/geom/util/Densifier.cpp
index a9e4616..5154888 100644
--- a/src/geom/util/Densifier.cpp
+++ b/src/geom/util/Densifier.cpp
@@ -88,7 +88,7 @@ Densifier::DensifyTransformer::transformMultiPolygon(const MultiPolygon* geom, c
     return validGeom;
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 Densifier::DensifyTransformer::createValidArea(const Geometry* roughAreaGeom)
 {
     return roughAreaGeom->buffer(0.0);
diff --git a/src/operation/overlay/snap/GeometrySnapper.cpp b/src/operation/overlay/snap/GeometrySnapper.cpp
index 87e9e68..cefbcae 100644
--- a/src/operation/overlay/snap/GeometrySnapper.cpp
+++ b/src/operation/overlay/snap/GeometrySnapper.cpp
@@ -139,7 +139,7 @@ GeometrySnapper::snapToSelf(double snapTolerance, bool cleanResult)
     if(cleanResult && (dynamic_cast<const Polygon*>(result.get()) ||
                        dynamic_cast<const MultiPolygon*>(result.get()))) {
         // TODO: use better cleaning approach
-        result.reset(result->buffer(0));
+        result = result->buffer(0);
     }
 
     return result;
diff --git a/src/operation/overlay/snap/SnapOverlayOp.cpp b/src/operation/overlay/snap/SnapOverlayOp.cpp
index 0d1bf25..ed2f3f6 100644
--- a/src/operation/overlay/snap/SnapOverlayOp.cpp
+++ b/src/operation/overlay/snap/SnapOverlayOp.cpp
@@ -91,8 +91,10 @@ SnapOverlayOp::removeCommonBits(const geom::Geometry& p_geom0,
     cbr->add(&p_geom0);
     cbr->add(&p_geom1);
 
-    remGeom.first.reset(cbr->removeCommonBits(p_geom0.clone().release()));
-    remGeom.second.reset(cbr->removeCommonBits(p_geom1.clone().release()));
+    remGeom.first = p_geom0.clone();
+    cbr->removeCommonBits(remGeom.first.get());
+    remGeom.second = p_geom1.clone();
+    cbr->removeCommonBits(remGeom.second.get());
 }
 
 /*private*/
diff --git a/src/operation/union/CascadedUnion.cpp b/src/operation/union/CascadedUnion.cpp
index 960367c..2dbc52c 100644
--- a/src/operation/union/CascadedUnion.cpp
+++ b/src/operation/union/CascadedUnion.cpp
@@ -201,7 +201,7 @@ CascadedUnion::extractByEnvelope(geom::Envelope const& env,
 geom::Geometry*
 CascadedUnion::unionActual(geom::Geometry* g0, geom::Geometry* g1)
 {
-    return g0->Union(g1);
+    return g0->Union(g1).release();
 }
 
 } // namespace geos.operation.union
diff --git a/src/operation/union/UnaryUnionOp.cpp b/src/operation/union/UnaryUnionOp.cpp
index aa1ec63..1158329 100644
--- a/src/operation/union/UnaryUnionOp.cpp
+++ b/src/operation/union/UnaryUnionOp.cpp
@@ -58,7 +58,7 @@ UnaryUnionOp::unionWithNull(std::unique_ptr<geom::Geometry> g0,
         return g0;
     }
 
-    ret.reset(g0->Union(g1.get()));
+    ret = g0->Union(g1.get());
     return ret;
 }
 
diff --git a/src/operation/valid/MakeValid.cpp b/src/operation/valid/MakeValid.cpp
index 4114276..b10ea95 100644
--- a/src/operation/valid/MakeValid.cpp
+++ b/src/operation/valid/MakeValid.cpp
@@ -68,22 +68,20 @@ nodeLineWithFirstCoordinate(const geom::Geometry* geom)
   const auto geomType = geom->getGeometryTypeId();
   assert( geomType == GEOS_LINESTRING || geomType == GEOS_MULTILINESTRING );
 
-  geom::Geometry* point;
+  std::unique_ptr<geom::Geometry> point;
   if( geomType == GEOS_LINESTRING ) {
       auto line = dynamic_cast<const geom::LineString*>(geom);
       assert(line);
-      point = line->getPointN(0);
+      point.reset(line->getPointN(0));
   } else {
       auto mls = dynamic_cast<const geom::MultiLineString*>(geom);
       assert(mls);
       auto line = dynamic_cast<const geom::LineString*>(mls->getGeometryN(0));
       assert(line);
-      point = line->getPointN(0);
+      point.reset(line->getPointN(0));
   }
-  auto noded = geom->Union(point);
-  delete point;
 
-  return std::unique_ptr<geom::Geometry>(noded);
+  return geom->Union(point.get());
 }
 
 
diff --git a/src/precision/CommonBitsOp.cpp b/src/precision/CommonBitsOp.cpp
index f616de4..45d5aa7 100644
--- a/src/precision/CommonBitsOp.cpp
+++ b/src/precision/CommonBitsOp.cpp
@@ -62,7 +62,7 @@ CommonBitsOp::CommonBitsOp(bool nReturnToOriginalPrecision)
 }
 
 /*public*/
-Geometry*
+std::unique_ptr<Geometry>
 CommonBitsOp::intersection(
     const Geometry* geom0,
     const Geometry* geom1)
@@ -74,7 +74,7 @@ CommonBitsOp::intersection(
 }
 
 /*public*/
-Geometry*
+std::unique_ptr<Geometry>
 CommonBitsOp::Union(
     const Geometry* geom0,
     const Geometry* geom1)
@@ -86,7 +86,7 @@ CommonBitsOp::Union(
 }
 
 /*public*/
-Geometry*
+std::unique_ptr<Geometry>
 CommonBitsOp::difference(
     const Geometry* geom0,
     const Geometry* geom1)
@@ -98,7 +98,7 @@ CommonBitsOp::difference(
 }
 
 /*public*/
-Geometry*
+std::unique_ptr<Geometry>
 CommonBitsOp::symDifference(
     const Geometry* geom0,
     const Geometry* geom1)
@@ -110,7 +110,7 @@ CommonBitsOp::symDifference(
 }
 
 /*public*/
-Geometry*
+std::unique_ptr<Geometry>
 CommonBitsOp::buffer(const Geometry* geom0, double distance)
 {
     unique_ptr<Geometry> rgeom0(removeCommonBits(geom0));
@@ -118,18 +118,18 @@ CommonBitsOp::buffer(const Geometry* geom0, double distance)
 }
 
 /*public*/
-Geometry*
-CommonBitsOp::computeResultPrecision(Geometry* result)
+std::unique_ptr<Geometry>
+CommonBitsOp::computeResultPrecision(std::unique_ptr<Geometry> result)
 {
     assert(cbr.get());
     if(returnToOriginalPrecision) {
-        cbr->addCommonBits(result);
+        cbr->addCommonBits(result.get());
     }
     return result;
 }
 
 /*private*/
-Geometry*
+std::unique_ptr<Geometry>
 CommonBitsOp::removeCommonBits(const Geometry* geom0)
 {
     cbr.reset(new CommonBitsRemover());
@@ -140,7 +140,9 @@ CommonBitsOp::removeCommonBits(const Geometry* geom0)
     cerr << "CommonBitsRemover bits: " << commonCoord.x << ", " << commonCoord.y << endl;
 #endif
 
-    Geometry* geom = cbr->removeCommonBits(geom0->clone().release());
+    auto geom = geom0->clone();
+    cbr->removeCommonBits(geom.get());
+
     return geom;
 }
 
@@ -163,9 +165,11 @@ CommonBitsOp::removeCommonBits(
     cerr << "CommonBitsRemover bits: " << commonCoord.x << ", " << commonCoord.y << endl;
 #endif
 
-    rgeom0.reset(cbr->removeCommonBits(geom0->clone().release()));
-    rgeom1.reset(cbr->removeCommonBits(geom1->clone().release()));
+    rgeom0 = geom0->clone();
+    cbr->removeCommonBits(rgeom0.get());
 
+    rgeom1 = geom1->clone();
+    cbr->removeCommonBits(rgeom1.get());
 }
 
 } // namespace geos.precision
diff --git a/src/precision/CommonBitsRemover.cpp b/src/precision/CommonBitsRemover.cpp
index 1289e6e..a4bf787 100644
--- a/src/precision/CommonBitsRemover.cpp
+++ b/src/precision/CommonBitsRemover.cpp
@@ -137,11 +137,11 @@ CommonBitsRemover::getCommonCoordinate()
  * @param geom the Geometry from which to remove the common coordinate bits
  * @return the shifted Geometry
  */
-Geometry*
+void
 CommonBitsRemover::removeCommonBits(Geometry* geom)
 {
     if(commonCoord.x == 0.0 && commonCoord.y == 0.0) {
-        return geom;
+        return;
     }
 
     Coordinate invCoord(commonCoord);
@@ -155,8 +155,6 @@ CommonBitsRemover::removeCommonBits(Geometry* geom)
 #if GEOS_DEBUG
     std::cerr << "CommonBits removed: " << *geom << std::endl;
 #endif
-
-    return geom;
 }
 
 /**
diff --git a/src/precision/EnhancedPrecisionOp.cpp b/src/precision/EnhancedPrecisionOp.cpp
index 974541e..740584f 100644
--- a/src/precision/EnhancedPrecisionOp.cpp
+++ b/src/precision/EnhancedPrecisionOp.cpp
@@ -37,7 +37,7 @@ namespace geos {
 namespace precision { // geos.precision
 
 /*public static*/
-Geometry*
+std::unique_ptr<Geometry>
 EnhancedPrecisionOp::intersection(
     const Geometry* geom0,
     const Geometry* geom1)
@@ -45,8 +45,7 @@ EnhancedPrecisionOp::intersection(
     util::GEOSException originalEx;
 
     try {
-        Geometry* result = geom0->intersection(geom1);
-        return result;
+        return geom0->intersection(geom1);
     }
     catch(const util::GEOSException& ex) {
         originalEx = ex;
@@ -59,7 +58,7 @@ EnhancedPrecisionOp::intersection(
      */
     try {
         CommonBitsOp cbo(true);
-        Geometry* resultEP = cbo.intersection(geom0, geom1);
+        auto resultEP = cbo.intersection(geom0, geom1);
 
         // check that result is a valid geometry after
         // the reshift to orginal precision
@@ -84,15 +83,14 @@ EnhancedPrecisionOp::intersection(
 }
 
 /*public static*/
-Geometry*
+std::unique_ptr<Geometry>
 EnhancedPrecisionOp::Union(
     const Geometry* geom0,
     const Geometry* geom1)
 {
     util::GEOSException originalEx;
     try {
-        Geometry* result = geom0->Union(geom1);
-        return result;
+        return geom0->Union(geom1);
     }
     catch(const util::GEOSException& ex) {
         originalEx = ex;
@@ -105,7 +103,7 @@ EnhancedPrecisionOp::Union(
      */
     try {
         CommonBitsOp cbo(true);
-        Geometry* resultEP = cbo.Union(geom0, geom1);
+        auto resultEP = cbo.Union(geom0, geom1);
 
         // check that result is a valid geometry after
         // the reshift to orginal precision
@@ -120,7 +118,7 @@ EnhancedPrecisionOp::Union(
 }
 
 /*public static*/
-Geometry*
+std::unique_ptr<Geometry>
 EnhancedPrecisionOp::difference(
     const Geometry* geom0,
     const Geometry* geom1)
@@ -128,8 +126,7 @@ EnhancedPrecisionOp::difference(
     util::GEOSException originalEx;
 
     try {
-        Geometry* result = geom0->difference(geom1);
-        return result;
+        return geom0->difference(geom1);
     }
     catch(const util::GEOSException& ex) {
         originalEx = ex;
@@ -142,7 +139,7 @@ EnhancedPrecisionOp::difference(
      */
     try {
         CommonBitsOp cbo(true);
-        Geometry* resultEP = cbo.difference(geom0, geom1);
+        auto resultEP = cbo.difference(geom0, geom1);
 
         // check that result is a valid geometry after
         // the reshift to orginal precision
@@ -157,15 +154,14 @@ EnhancedPrecisionOp::difference(
 }
 
 /*public static*/
-Geometry*
+std::unique_ptr<Geometry>
 EnhancedPrecisionOp::symDifference(
     const Geometry* geom0,
     const Geometry* geom1)
 {
     util::GEOSException originalEx;
     try {
-        Geometry* result = geom0->symDifference(geom1);
-        return result;
+        return geom0->symDifference(geom1);
     }
     catch(const util::GEOSException& ex) {
         originalEx = ex;
@@ -178,7 +174,7 @@ EnhancedPrecisionOp::symDifference(
      */
     try {
         CommonBitsOp cbo(true);
-        Geometry* resultEP = cbo.symDifference(geom0, geom1);
+        auto resultEP = cbo.symDifference(geom0, geom1);
 
         // check that result is a valid geometry after
         // the reshift to orginal precision
@@ -193,13 +189,12 @@ EnhancedPrecisionOp::symDifference(
 }
 
 /*public static*/
-Geometry*
+std::unique_ptr<Geometry>
 EnhancedPrecisionOp::buffer(const Geometry* geom, double distance)
 {
     util::GEOSException originalEx;
     try {
-        Geometry* result = geom->buffer(distance);
-        return result;
+        return geom->buffer(distance);
     }
     catch(const util::GEOSException& ex) {
         originalEx = ex;
@@ -212,7 +207,7 @@ EnhancedPrecisionOp::buffer(const Geometry* geom, double distance)
      */
     try {
         CommonBitsOp cbo(true);
-        Geometry* resultEP = cbo.buffer(geom, distance);
+        auto resultEP = cbo.buffer(geom, distance);
 
         // check that result is a valid geometry
         // after the reshift to orginal precision
diff --git a/src/triangulate/VoronoiDiagramBuilder.cpp b/src/triangulate/VoronoiDiagramBuilder.cpp
index e2d8c76..a65b7c8 100644
--- a/src/triangulate/VoronoiDiagramBuilder.cpp
+++ b/src/triangulate/VoronoiDiagramBuilder.cpp
@@ -138,7 +138,7 @@ VoronoiDiagramBuilder::clipGeometryCollection(const geom::GeometryCollection& ge
             // TODO: check if userData is correctly cloned here?
         }
         else if(clipEnv.intersects(g->getEnvelopeInternal())) {
-            result.reset(clipPoly->intersection(g));
+            result = clipPoly->intersection(g);
             result->setUserData(((Geometry*)g)->getUserData()); // TODO: needed ?
         }
 
diff --git a/tests/unit/operation/union/CascadedPolygonUnionTest.cpp b/tests/unit/operation/union/CascadedPolygonUnionTest.cpp
index 6f5c1d7..0ebb2d4 100644
--- a/tests/unit/operation/union/CascadedPolygonUnionTest.cpp
+++ b/tests/unit/operation/union/CascadedPolygonUnionTest.cpp
@@ -52,7 +52,7 @@ unionIterated(
             unionAll = p->clone();
         }
         else {
-            unionAll.reset(unionAll->Union(p));
+            unionAll = unionAll->Union(p);
         }
     }
     return unionAll.release();
@@ -126,13 +126,13 @@ create_discs(geos::geom::GeometryFactory& gf, int num, double radius,
         for(int j = 0; j < num; ++j) {
             std::unique_ptr<geos::geom::Point> pt(
                 gf.createPoint(geos::geom::Coordinate(i, j)));
-            g->push_back(dynamic_cast<geos::geom::Polygon*>(pt->buffer(radius)));
+            g->push_back(dynamic_cast<geos::geom::Polygon*>(pt->buffer(radius).release()));
         }
     }
 }
 
 // these tests currently fail because the geometries generated by the different
-// union algoritms are slightly different. In order to make those tests pass
+// union algorithms are slightly different. In order to make those tests pass
 // we need to port the similarity measure classes from JTS, allowing to
 // approximately compare the two results
 
diff --git a/tests/xmltester/XMLTester.cpp b/tests/xmltester/XMLTester.cpp
index 98da320..9033659 100644
--- a/tests/xmltester/XMLTester.cpp
+++ b/tests/xmltester/XMLTester.cpp
@@ -943,7 +943,7 @@ XMLTester::parseTest(const tinyxml2::XMLNode* node)
             GeomPtr gRealRes;
             if(gB) {
 #ifndef USE_BINARYOP
-                gRealRes.reset(gA->Union(gB));
+                gRealRes = gA->Union(gB);
 #else
                 gRealRes = BinaryOp(gA, gB, overlayOp(OverlayOp::opUNION));
 #endif

commit 76f5141f726cfa0837e340b787a6599e48b9028c
Author: Daniel Baston <dbaston at gmail.com>
Date:   Tue May 28 21:04:40 2019 -0400

    Make Geometry::getInteriorPoint non-virtual
    
    Subclasses have no overriding implementations.

diff --git a/include/geos/geom/Geometry.h b/include/geos/geom/Geometry.h
index 4d269ec..ec474a9 100644
--- a/include/geos/geom/Geometry.h
+++ b/include/geos/geom/Geometry.h
@@ -813,7 +813,7 @@ public:
      * @return a Point which is in the interior of this Geometry, or
      *         null if the geometry doesn't have an interior (empty)
      */
-    virtual std::unique_ptr<Point> getInteriorPoint() const;
+    std::unique_ptr<Point> getInteriorPoint() const;
 
     /*
      * \brief

commit 8dbb4b3e3dccba5aec12871c7370bbee0c50673d
Author: Daniel Baston <dbaston at gmail.com>
Date:   Tue May 28 21:04:07 2019 -0400

    Return unique_ptr from Geometry::getInteriorPoint

diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp
index 0e90510..b824506 100644
--- a/capi/geos_ts_c.cpp
+++ b/capi/geos_ts_c.cpp
@@ -2280,13 +2280,13 @@ extern "C" {
         }
 
         try {
-            Geometry* ret = g1->getInteriorPoint();
-            if(! ret) {
+            auto ret = g1->getInteriorPoint();
+            if(ret == nullptr) {
                 const GeometryFactory* gf = handle->geomFactory;
                 // return an empty point
                 return gf->createPoint();
             }
-            return ret;
+            return ret.release();
         }
         catch(const std::exception& e) {
             handle->ERROR_MESSAGE("%s", e.what());
diff --git a/include/geos/geom/Geometry.h b/include/geos/geom/Geometry.h
index 151f7fa..4d269ec 100644
--- a/include/geos/geom/Geometry.h
+++ b/include/geos/geom/Geometry.h
@@ -813,7 +813,7 @@ public:
      * @return a Point which is in the interior of this Geometry, or
      *         null if the geometry doesn't have an interior (empty)
      */
-    virtual Point* getInteriorPoint() const;
+    virtual std::unique_ptr<Point> getInteriorPoint() const;
 
     /*
      * \brief
diff --git a/src/geom/Geometry.cpp b/src/geom/Geometry.cpp
index 13d3c9a..9db27b6 100644
--- a/src/geom/Geometry.cpp
+++ b/src/geom/Geometry.cpp
@@ -218,7 +218,7 @@ Geometry::getCentroid(Coordinate& ret) const
     return true;
 }
 
-Point*
+std::unique_ptr<Point>
 Geometry::getInteriorPoint() const
 {
     Coordinate interiorPt;
@@ -241,7 +241,7 @@ Geometry::getInteriorPoint() const
             return nullptr;
         }
     }
-    Point* p = getFactory()->createPointFromInternalCoord(&interiorPt, this);
+    std::unique_ptr<Point> p(getFactory()->createPointFromInternalCoord(&interiorPt, this));
     return p;
 }
 

commit 5f3878a0a69e67a814e3fdcf1e897174269ac337
Author: Daniel Baston <dbaston at gmail.com>
Date:   Tue May 28 21:00:01 2019 -0400

    Make Geometry::relate non-virtual
    
    Subclasses have no overriding implementations.

diff --git a/include/geos/geom/Geometry.h b/include/geos/geom/Geometry.h
index d9b52b7..151f7fa 100644
--- a/include/geos/geom/Geometry.h
+++ b/include/geos/geom/Geometry.h
@@ -466,7 +466,7 @@ public:
      * @throws util::IllegalArgumentException if either arg is a collection
      *
      */
-    virtual bool relate(const Geometry* g,
+    bool relate(const Geometry* g,
                         const std::string& intersectionPattern) const;
 
     bool
@@ -476,7 +476,7 @@ public:
     }
 
     /// Returns the DE-9IM intersection matrix for the two Geometrys.
-    virtual std::unique_ptr<IntersectionMatrix> relate(const Geometry* g) const;
+    std::unique_ptr<IntersectionMatrix> relate(const Geometry* g) const;
 
     std::unique_ptr<IntersectionMatrix> relate(const Geometry& g) const
     {

commit ff168c6e41ba7463f856b33af83c722c001361aa
Author: Daniel Baston <dbaston at gmail.com>
Date:   Tue May 28 20:59:09 2019 -0400

    Return unique_ptr from Geometry::relate

diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp
index fa9dc32..0e90510 100644
--- a/capi/geos_ts_c.cpp
+++ b/capi/geos_ts_c.cpp
@@ -761,16 +761,13 @@ extern "C" {
         try {
             using geos::geom::IntersectionMatrix;
 
-            IntersectionMatrix* im = g1->relate(g2);
-            if(0 == im) {
+            auto im = g1->relate(g2);
+            if(im == nullptr) {
                 return 0;
             }
 
             char* result = gstrdup(im->toString());
 
-            delete im;
-            im = 0;
-
             return result;
         }
         catch(const std::exception& e) {
@@ -801,7 +798,7 @@ extern "C" {
             using geos::geom::IntersectionMatrix;
             using geos::algorithm::BoundaryNodeRule;
 
-            IntersectionMatrix* im;
+            std::unique_ptr<IntersectionMatrix> im;
             switch(bnr) {
             case GEOSRELATE_BNR_MOD2: /* same as OGC */
                 im = RelateOp::relate(g1, g2,
@@ -831,9 +828,6 @@ extern "C" {
 
             char* result = gstrdup(im->toString());
 
-            delete im;
-            im = 0;
-
             return result;
         }
         catch(const std::exception& e) {
diff --git a/include/geos/geom/Geometry.h b/include/geos/geom/Geometry.h
index 6cc82be..d9b52b7 100644
--- a/include/geos/geom/Geometry.h
+++ b/include/geos/geom/Geometry.h
@@ -36,6 +36,7 @@
 #include <geos/geom/Envelope.h>
 #include <geos/geom/Dimension.h> // for Dimension::DimensionType
 #include <geos/geom/GeometryComponentFilter.h> // for inheritance
+#include <geos/geom/IntersectionMatrix.h>
 
 #include <string>
 #include <iostream>
@@ -58,7 +59,6 @@ class CoordinateSequenceFilter;
 class GeometryComponentFilter;
 class GeometryFactory;
 class GeometryFilter;
-class IntersectionMatrix;
 class PrecisionModel;
 class Point;
 }
@@ -476,9 +476,9 @@ public:
     }
 
     /// Returns the DE-9IM intersection matrix for the two Geometrys.
-    virtual IntersectionMatrix* relate(const Geometry* g) const;
-    IntersectionMatrix*
-    relate(const Geometry& g) const
+    virtual std::unique_ptr<IntersectionMatrix> relate(const Geometry* g) const;
+
+    std::unique_ptr<IntersectionMatrix> relate(const Geometry& g) const
     {
         return relate(&g);
     }
diff --git a/include/geos/operation/relate/RelateComputer.h b/include/geos/operation/relate/RelateComputer.h
index 874ae2b..66f91c5 100644
--- a/include/geos/operation/relate/RelateComputer.h
+++ b/include/geos/operation/relate/RelateComputer.h
@@ -27,6 +27,7 @@
 #include <geos/algorithm/LineIntersector.h> // for RelateComputer composition
 #include <geos/geomgraph/NodeMap.h> // for RelateComputer composition
 #include <geos/geom/Coordinate.h> // for RelateComputer composition
+#include <geos/geom/IntersectionMatrix.h>
 
 #include <vector>
 #include <memory>
@@ -39,7 +40,6 @@
 // Forward declarations
 namespace geos {
 namespace geom {
-class IntersectionMatrix;
 class Geometry;
 }
 namespace geomgraph {
@@ -77,7 +77,7 @@ public:
     RelateComputer(std::vector<geomgraph::GeometryGraph*>* newArg);
     ~RelateComputer();
 
-    geom::IntersectionMatrix* computeIM();
+    std::unique_ptr<geom::IntersectionMatrix> computeIM();
 private:
 
     algorithm::LineIntersector li;
diff --git a/include/geos/operation/relate/RelateOp.h b/include/geos/operation/relate/RelateOp.h
index 389dae6..9b41950 100644
--- a/include/geos/operation/relate/RelateOp.h
+++ b/include/geos/operation/relate/RelateOp.h
@@ -21,6 +21,7 @@
 
 #include <geos/export.h>
 
+#include <geos/geom/IntersectionMatrix.h>
 #include <geos/operation/GeometryGraphOperation.h> // for inheritance
 #include <geos/operation/relate/RelateComputer.h> // for composition
 
@@ -30,7 +31,6 @@ namespace algorithm {
 class BoundaryNodeRule;
 }
 namespace geom {
-class IntersectionMatrix;
 class Geometry;
 }
 }
@@ -69,7 +69,7 @@ public:
      * @return the IntersectonMatrix for the spatial relationship
      *         between the geometries. Ownership transferred.
      */
-    static geom::IntersectionMatrix* relate(
+    static std::unique_ptr<geom::IntersectionMatrix> relate(
         const geom::Geometry* a,
         const geom::Geometry* b);
 
@@ -85,7 +85,7 @@ public:
      * @return the IntersectonMatrix for the spatial relationship
      *         between the geometries. Ownership transferred.
      */
-    static geom::IntersectionMatrix* relate(
+    static std::unique_ptr<geom::IntersectionMatrix> relate(
         const geom::Geometry* a,
         const geom::Geometry* b,
         const algorithm::BoundaryNodeRule& boundaryNodeRule);
@@ -122,7 +122,7 @@ public:
      *         relationship between the input geometries.
      *         Ownership transferred.
      */
-    geom::IntersectionMatrix* getIntersectionMatrix();
+    std::unique_ptr<geom::IntersectionMatrix> getIntersectionMatrix();
 
 private:
 
diff --git a/src/geom/Geometry.cpp b/src/geom/Geometry.cpp
index 28da086..13d3c9a 100644
--- a/src/geom/Geometry.cpp
+++ b/src/geom/Geometry.cpp
@@ -494,9 +494,8 @@ Geometry::equals(const Geometry* g) const
     return res;
 }
 
-IntersectionMatrix*
+std::unique_ptr<IntersectionMatrix>
 Geometry::relate(const Geometry* other) const
-//throw(IllegalArgumentException *)
 {
     return RelateOp::relate(this, other);
 }
diff --git a/src/operation/relate/RelateComputer.cpp b/src/operation/relate/RelateComputer.cpp
index 2547b48..edc010e 100644
--- a/src/operation/relate/RelateComputer.cpp
+++ b/src/operation/relate/RelateComputer.cpp
@@ -69,7 +69,7 @@ RelateComputer::~RelateComputer()
 {
 }
 
-IntersectionMatrix*
+std::unique_ptr<IntersectionMatrix>
 RelateComputer::computeIM()
 {
     // since Geometries are finite and embedded in a 2-D space, the EE element must always be 2
@@ -79,7 +79,7 @@ RelateComputer::computeIM()
     const Envelope* e2 = (*arg)[1]->getGeometry()->getEnvelopeInternal();
     if(!e1->intersects(e2)) {
         computeDisjointIM(im.get());
-        return im.release();
+        return std::move(im);
     }
 
 #if GEOS_DEBUG
@@ -237,7 +237,7 @@ RelateComputer::computeIM()
     labelIsolatedEdges(1, 0);
     // update the IM from all components
     updateIM(*im);
-    return im.release();
+    return std::move(im);
 }
 
 void
diff --git a/src/operation/relate/RelateOp.cpp b/src/operation/relate/RelateOp.cpp
index 88b6996..d5dc261 100644
--- a/src/operation/relate/RelateOp.cpp
+++ b/src/operation/relate/RelateOp.cpp
@@ -35,14 +35,14 @@ namespace geos {
 namespace operation { // geos.operation
 namespace relate { // geos.operation.relate
 
-IntersectionMatrix*
+std::unique_ptr<IntersectionMatrix>
 RelateOp::relate(const Geometry* a, const Geometry* b)
 {
     RelateOp relOp(a, b);
     return relOp.getIntersectionMatrix();
 }
 
-IntersectionMatrix*
+std::unique_ptr<IntersectionMatrix>
 RelateOp::relate(const Geometry* a, const Geometry* b,
                  const algorithm::BoundaryNodeRule& boundaryNodeRule)
 {
@@ -68,7 +68,7 @@ RelateOp::~RelateOp()
 {
 }
 
-IntersectionMatrix*
+std::unique_ptr<IntersectionMatrix>
 RelateOp::getIntersectionMatrix()
 {
     return relateComp.computeIM();

commit f6a46726cad6748f0304c1748701fc63f8d7ce3c
Author: Daniel Baston <dbaston at gmail.com>
Date:   Tue May 28 17:10:59 2019 -0400

    Return unique_ptr from Geometry::getEnvelope, getBoundary, getCentroid

diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp
index 55d3cba..fa9dc32 100644
--- a/capi/geos_ts_c.cpp
+++ b/capi/geos_ts_c.cpp
@@ -1682,7 +1682,7 @@ extern "C" {
         }
 
         try {
-            Geometry* g3 = g1->getEnvelope();
+            Geometry* g3 = g1->getEnvelope().release();
             return g3;
         }
         catch(const std::exception& e) {
@@ -2072,7 +2072,7 @@ extern "C" {
         }
 
         try {
-            Geometry* g3 = g1->getBoundary();
+            Geometry* g3 = g1->getBoundary().release();
             return g3;
         }
         catch(const std::exception& e) {
@@ -2988,7 +2988,7 @@ extern "C" {
         }
 
         try {
-            Geometry* ret = g->getCentroid();
+            Geometry* ret = g->getCentroid().release();
             if(0 == ret) {
                 const GeometryFactory* gf = handle->geomFactory;
                 return gf->createPoint();
diff --git a/include/geos/geom/Geometry.h b/include/geos/geom/Geometry.h
index 3b44a72..6cc82be 100644
--- a/include/geos/geom/Geometry.h
+++ b/include/geos/geom/Geometry.h
@@ -371,13 +371,13 @@ public:
      *          of this <code>Geometry</code>.
      *          Ownershipof the returned object transferred to caller.
      */
-    virtual Geometry* getBoundary() const = 0; //Abstract
+    virtual std::unique_ptr<Geometry> getBoundary() const = 0; //Abstract
 
     /// Returns the dimension of this Geometrys inherent boundary.
     virtual int getBoundaryDimension() const = 0; //Abstract
 
     /// Returns this Geometrys bounding box.
-    virtual Geometry* getEnvelope() const;
+    virtual std::unique_ptr<Geometry> getEnvelope() const;
 
     /** \brief
      * Returns the minimum and maximum x and y values in this Geometry,
@@ -795,7 +795,7 @@ public:
      *
      * @return a {@link Point} which is the centroid of this Geometry
      */
-    virtual Point* getCentroid() const;
+    virtual std::unique_ptr<Point> getCentroid() const;
 
     /// Computes the centroid of this Geometry as a Coordinate
     //
diff --git a/include/geos/geom/GeometryCollection.h b/include/geos/geom/GeometryCollection.h
index efa040f..2163ef9 100644
--- a/include/geos/geom/GeometryCollection.h
+++ b/include/geos/geom/GeometryCollection.h
@@ -110,7 +110,7 @@ public:
     /// Returns coordinate dimension.
     int getCoordinateDimension() const override;
 
-    Geometry* getBoundary() const override;
+    std::unique_ptr<Geometry> getBoundary() const override;
 
     /**
      * \brief
diff --git a/include/geos/geom/LineString.h b/include/geos/geom/LineString.h
index 3c057a3..fd0f51e 100644
--- a/include/geos/geom/LineString.h
+++ b/include/geos/geom/LineString.h
@@ -111,7 +111,7 @@ public:
      * Returns a MultiPoint.
      * Empty for closed LineString, a Point for each vertex otherwise.
      */
-    Geometry* getBoundary() const override;
+    std::unique_ptr<Geometry> getBoundary() const override;
 
     bool isEmpty() const override;
 
diff --git a/include/geos/geom/MultiLineString.h b/include/geos/geom/MultiLineString.h
index ab12e6f..fcf9e20 100644
--- a/include/geos/geom/MultiLineString.h
+++ b/include/geos/geom/MultiLineString.h
@@ -67,7 +67,7 @@ public:
     int getBoundaryDimension() const override;
 
     /// Returns a (possibly empty) MultiPoint
-    Geometry* getBoundary() const override;
+    std::unique_ptr<Geometry> getBoundary() const override;
 
     std::string getGeometryType() const override;
 
diff --git a/include/geos/geom/MultiPoint.h b/include/geos/geom/MultiPoint.h
index 8d30dc8..8d08a3c 100644
--- a/include/geos/geom/MultiPoint.h
+++ b/include/geos/geom/MultiPoint.h
@@ -74,7 +74,7 @@ public:
      * @return an empty GeometryCollection
      * @see Geometry#getBoundary
      */
-    Geometry* getBoundary() const override;
+    std::unique_ptr<Geometry> getBoundary() const override;
 
     std::string getGeometryType() const override;
 
diff --git a/include/geos/geom/MultiPolygon.h b/include/geos/geom/MultiPolygon.h
index a0a4f54..fc3805f 100644
--- a/include/geos/geom/MultiPolygon.h
+++ b/include/geos/geom/MultiPolygon.h
@@ -75,7 +75,7 @@ public:
      * @return a lineal geometry (which may be empty)
      * @see Geometry#getBoundary
      */
-    Geometry* getBoundary() const override;
+    std::unique_ptr<Geometry> getBoundary() const override;
 
     std::string getGeometryType() const override;
 
diff --git a/include/geos/geom/Point.h b/include/geos/geom/Point.h
index 4406205..2aef1f3 100644
--- a/include/geos/geom/Point.h
+++ b/include/geos/geom/Point.h
@@ -111,7 +111,7 @@ public:
      * @return an empty GeometryCollection
      * @see Geometry::getBoundary
      */
-    Geometry* getBoundary() const override;
+    std::unique_ptr<Geometry> getBoundary() const override;
 
     double getX() const;
     double getY() const;
diff --git a/include/geos/geom/Polygon.h b/include/geos/geom/Polygon.h
index 17c0b67..5013830 100644
--- a/include/geos/geom/Polygon.h
+++ b/include/geos/geom/Polygon.h
@@ -104,7 +104,7 @@ public:
      * @return a lineal geometry (which may be empty)
      * @see Geometry#getBoundary
      */
-    Geometry* getBoundary() const override;
+    std::unique_ptr<Geometry> getBoundary() const override;
 
     bool isEmpty() const override;
 
diff --git a/src/geom/Geometry.cpp b/src/geom/Geometry.cpp
index e10163a..28da086 100644
--- a/src/geom/Geometry.cpp
+++ b/src/geom/Geometry.cpp
@@ -191,7 +191,7 @@ Geometry::isWithinDistance(const Geometry* geom, double cDistance) const
 }
 
 /*public*/
-Point*
+std::unique_ptr<Point>
 Geometry::getCentroid() const
 {
     Coordinate centPt;
@@ -201,8 +201,7 @@ Geometry::getCentroid() const
 
     // We don't use createPointFromInternalCoord here
     // because ::getCentroid() takes care about rounding
-    Point* pt = getFactory()->createPoint(centPt);
-    return pt;
+    return std::unique_ptr<Point>(getFactory()->createPoint(centPt));
 }
 
 /*public*/
@@ -276,10 +275,10 @@ Geometry::isValid() const
     return IsValidOp(this).isValid();
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 Geometry::getEnvelope() const
 {
-    return getFactory()->toGeometry(getEnvelopeInternal());
+    return std::unique_ptr<Geometry>(getFactory()->toGeometry(getEnvelopeInternal()));
 }
 
 const Envelope*
diff --git a/src/geom/GeometryCollection.cpp b/src/geom/GeometryCollection.cpp
index b3217a5..e00a63f 100644
--- a/src/geom/GeometryCollection.cpp
+++ b/src/geom/GeometryCollection.cpp
@@ -177,7 +177,7 @@ GeometryCollection::getGeometryType() const
     return "GeometryCollection";
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 GeometryCollection::getBoundary() const
 {
     throw util::IllegalArgumentException("Operation not supported by GeometryCollection\n");
diff --git a/src/geom/LineString.cpp b/src/geom/LineString.cpp
index 7d5193f..be5e22d 100644
--- a/src/geom/LineString.cpp
+++ b/src/geom/LineString.cpp
@@ -215,23 +215,23 @@ LineString::getGeometryType() const
     return "LineString";
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 LineString::getBoundary() const
 {
     if(isEmpty()) {
-        return getFactory()->createMultiPoint();
+        return std::unique_ptr<Geometry>(getFactory()->createMultiPoint());
     }
 
     // using the default OGC_SFS MOD2 rule, the boundary of a
     // closed LineString is empty
     if(isClosed()) {
-        return getFactory()->createMultiPoint();
+        return std::unique_ptr<Geometry>(getFactory()->createMultiPoint());
     }
     vector<Geometry*>* pts = new vector<Geometry*>();
     pts->push_back(getStartPoint());
     pts->push_back(getEndPoint());
     MultiPoint* mp = getFactory()->createMultiPoint(pts);
-    return mp;
+    return std::unique_ptr<Geometry>(mp);
 }
 
 bool
diff --git a/src/geom/MultiLineString.cpp b/src/geom/MultiLineString.cpp
index ff7e583..f32ff30 100644
--- a/src/geom/MultiLineString.cpp
+++ b/src/geom/MultiLineString.cpp
@@ -86,17 +86,16 @@ MultiLineString::isClosed() const
     return true;
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 MultiLineString::getBoundary() const
 {
     if(isEmpty()) {
-        return getFactory()->createGeometryCollection(nullptr);
+        return std::unique_ptr<Geometry>(getFactory()->createGeometryCollection(nullptr));
     }
-    //Geometry *in = toInternalGeometry(this);
+
     GeometryGraph gg(0, this);
     CoordinateSequence* pts = gg.getBoundaryPoints();
-    Geometry* ret = getFactory()->createMultiPoint(*pts);
-    return ret;
+    return std::unique_ptr<Geometry>(getFactory()->createMultiPoint(*pts));
 }
 
 bool
diff --git a/src/geom/MultiPoint.cpp b/src/geom/MultiPoint.cpp
index fc4abc0..ebc28f3 100644
--- a/src/geom/MultiPoint.cpp
+++ b/src/geom/MultiPoint.cpp
@@ -60,10 +60,10 @@ MultiPoint::getGeometryType() const
     return "MultiPoint";
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 MultiPoint::getBoundary() const
 {
-    return getFactory()->createGeometryCollection();
+    return std::unique_ptr<Geometry>(getFactory()->createGeometryCollection());
 }
 
 bool
diff --git a/src/geom/MultiPolygon.cpp b/src/geom/MultiPolygon.cpp
index 7bd2df8..2d57353 100644
--- a/src/geom/MultiPolygon.cpp
+++ b/src/geom/MultiPolygon.cpp
@@ -65,35 +65,33 @@ MultiPolygon::getGeometryType() const
     return "MultiPolygon";
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 MultiPolygon::getBoundary() const
 {
     if(isEmpty()) {
-        return getFactory()->createMultiLineString();
+        return std::unique_ptr<Geometry>(getFactory()->createMultiLineString());
     }
     vector<Geometry*>* allRings = new vector<Geometry*>();
     for(size_t i = 0; i < geometries->size(); i++) {
         Polygon* pg = dynamic_cast<Polygon*>((*geometries)[i]);
         assert(pg);
-        Geometry* g = pg->getBoundary();
-        if(LineString* ls = dynamic_cast<LineString*>(g)) {
+        auto g = pg->getBoundary();
+        if(LineString* ls = dynamic_cast<LineString*>(g.get())) {
             allRings->push_back(ls);
+            g.release();
         }
         else {
-            GeometryCollection* rings = dynamic_cast<GeometryCollection*>(g);
+            GeometryCollection* rings = dynamic_cast<GeometryCollection*>(g.get());
             for(size_t j = 0, jn = rings->getNumGeometries();
                     j < jn; ++j) {
-                //allRings->push_back(new LineString(*(LineString*)rings->getGeometryN(j)));
                 allRings->push_back(rings->getGeometryN(j)->clone().release());
             }
-            delete g;
         }
     }
 
     Geometry* ret = getFactory()->createMultiLineString(allRings);
-    //for (int i=0; i<allRings->size(); i++) delete (*allRings)[i];
-    //delete allRings;
-    return ret;
+
+    return std::unique_ptr<Geometry>(ret);
 }
 
 bool
diff --git a/src/geom/Point.cpp b/src/geom/Point.cpp
index 1d4928c..ca665eb 100644
--- a/src/geom/Point.cpp
+++ b/src/geom/Point.cpp
@@ -146,10 +146,10 @@ Point::getGeometryType() const
     return "Point";
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 Point::getBoundary() const
 {
-    return getFactory()->createGeometryCollection(nullptr);
+    return std::unique_ptr<Geometry>(getFactory()->createGeometryCollection(nullptr));
 }
 
 Envelope::Ptr
diff --git a/src/geom/Polygon.cpp b/src/geom/Polygon.cpp
index 5d09d16..fae5f20 100644
--- a/src/geom/Polygon.cpp
+++ b/src/geom/Polygon.cpp
@@ -198,7 +198,7 @@ Polygon::getGeometryType() const
 
 // Returns a newly allocated Geometry object
 /*public*/
-Geometry*
+std::unique_ptr<Geometry>
 Polygon::getBoundary() const
 {
     /*
@@ -210,11 +210,11 @@ Polygon::getBoundary() const
     const GeometryFactory* gf = getFactory();
 
     if(isEmpty()) {
-        return gf->createMultiLineString();
+        return std::unique_ptr<Geometry>(gf->createMultiLineString());
     }
 
     if(! holes->size()) {
-        return gf->createLineString(*shell).release();
+        return std::unique_ptr<Geometry>(gf->createLineString(*shell).release());
     }
 
     vector<Geometry*>* rings = new vector<Geometry*>(holes->size() + 1);
@@ -227,7 +227,7 @@ Polygon::getBoundary() const
         (*rings)[i + 1] = ls;
     }
     MultiLineString* ret = getFactory()->createMultiLineString(rings);
-    return ret;
+    return std::unique_ptr<Geometry>(ret);
 }
 
 Envelope::Ptr
diff --git a/src/operation/overlay/validate/FuzzyPointLocator.cpp b/src/operation/overlay/validate/FuzzyPointLocator.cpp
index 649e2ba..4abac71 100644
--- a/src/operation/overlay/validate/FuzzyPointLocator.cpp
+++ b/src/operation/overlay/validate/FuzzyPointLocator.cpp
@@ -71,7 +71,7 @@ FuzzyPointLocator::extractLineWork(const geom::Geometry& geom)
 
             // only get linework for polygonal components
             if(gComp->getDimension() == 2) {
-                lineGeom = gComp->getBoundary();
+                lineGeom = gComp->getBoundary().release();
                 lineGeoms->push_back(lineGeom);
             }
         }
@@ -101,7 +101,7 @@ FuzzyPointLocator::getLineWork(const geom::Geometry& geom)
             const Geometry* gComp = g.getGeometryN(i);
             Geometry* lineGeom;
             if(gComp->getDimension() == 2) {
-                lineGeom = gComp->getBoundary();
+                lineGeom = gComp->getBoundary().release();
             }
             else {
                 lineGeom = gComp->clone().release();
diff --git a/src/operation/polygonize/BuildArea.cpp b/src/operation/polygonize/BuildArea.cpp
index 99a2c28..f120332 100644
--- a/src/operation/polygonize/BuildArea.cpp
+++ b/src/operation/polygonize/BuildArea.cpp
@@ -69,7 +69,7 @@ struct Face {
 static std::unique_ptr<Face> newFace(const geom::Polygon* p) {
     auto f = std::unique_ptr<Face>(new Face());
     f->poly = p;
-    f->env.reset(p->getEnvelope());
+    f->env = p->getEnvelope();
     f->envarea = f->env->getArea();
     return f;
 }
diff --git a/src/operation/valid/MakeValid.cpp b/src/operation/valid/MakeValid.cpp
index 9064ba8..4114276 100644
--- a/src/operation/valid/MakeValid.cpp
+++ b/src/operation/valid/MakeValid.cpp
@@ -237,7 +237,7 @@ static std::unique_ptr<geom::Geometry> MakeValidPoly(const geom::Geometry* geom)
 
         // We succeeded in building a ring !
         // Save the new ring boundaries first (to compute further cut edges later)
-        std::unique_ptr<geom::Geometry> new_area_bound(new_area->getBoundary());
+        std::unique_ptr<geom::Geometry> new_area_bound = new_area->getBoundary();
         assert(new_area_bound);
 
         // Now symdif new and old area
diff --git a/tests/unit/geom/GeometryFactoryTest.cpp b/tests/unit/geom/GeometryFactoryTest.cpp
index 05a140b..4635239 100644
--- a/tests/unit/geom/GeometryFactoryTest.cpp
+++ b/tests/unit/geom/GeometryFactoryTest.cpp
@@ -258,21 +258,18 @@ void object::test<8>
     ensure(pt->getCentroid() == nullptr);
     ensure(pt->getCoordinate() == nullptr);
 
-    GeometryPtr geo = nullptr;
+    std::unique_ptr<geos::geom::Geometry> geo;
     geo = pt->getEnvelope();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     geo = pt->getBoundary();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
-    geo = pt->convexHull().release();
+    geo = pt->convexHull();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     ensure_equals(pt->getGeometryTypeId(), geos::geom::GEOS_POINT);
     ensure_equals(pt->getDimension(), geos::geom::Dimension::P);
@@ -307,26 +304,22 @@ void object::test<9>
     ensure_equals(pcoord->y, y_);
     ensure_equals(pcoord->z, z_);
 
-    GeometryPtr geo = nullptr;
+    std::unique_ptr<geos::geom::Geometry> geo;
     geo = pt->getEnvelope();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     geo = pt->getCentroid();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     geo = pt->getBoundary();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
-    geo = pt->convexHull().release();
+    geo = pt->convexHull();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     ensure_equals(pt->getGeometryTypeId(), geos::geom::GEOS_POINT);
     ensure_equals(pt->getDimension(), geos::geom::Dimension::P);
@@ -366,26 +359,22 @@ void object::test<10>
     ensure_equals(pcoord->y, y_);
     ensure_equals(pcoord->z, z_);
 
-    GeometryPtr geo = nullptr;
+    std::unique_ptr<geos::geom::Geometry> geo;
     geo = pt->getEnvelope();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     geo = pt->getCentroid();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     geo = pt->getBoundary();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
-    geo = pt->convexHull().release();
+    geo = pt->convexHull();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     ensure_equals(pt->getGeometryTypeId(), geos::geom::GEOS_POINT);
     ensure_equals(pt->getDimension(), geos::geom::Dimension::P);
@@ -423,26 +412,22 @@ void object::test<11>
     ensure_equals(pcoord->y, y_);
     ensure_equals(pcoord->z, z_);
 
-    GeometryPtr geo = nullptr;
+    std::unique_ptr<geos::geom::Geometry> geo;
     geo = pt->getEnvelope();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     geo = pt->getCentroid();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     geo = pt->getBoundary();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
-    geo = pt->convexHull().release();
+    geo = pt->convexHull();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     ensure_equals(pt->getGeometryTypeId(), geos::geom::GEOS_POINT);
     ensure_equals(pt->getDimension(), geos::geom::Dimension::P);
@@ -565,21 +550,18 @@ void object::test<15>
     // http://geos.osgeo.org/pipermail/geos-devel/2006-March/002006.html
     //ensure( line->getCoordinate() == 0 );
 
-    GeometryPtr geo = nullptr;
+    std::unique_ptr<geos::geom::Geometry> geo;
     geo = line->getEnvelope();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     geo = line->getBoundary();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
-    geo = line->convexHull().release();
+    geo = line->convexHull();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     ensure_equals(line->getGeometryTypeId(), geos::geom::GEOS_LINESTRING);
     ensure_equals(line->getDimension(), geos::geom::Dimension::L);
@@ -667,7 +649,7 @@ void object::test<18>
     // http://geos.osgeo.org/pipermail/geos-devel/2006-March/002006.html
     //ensure( poly->getCoordinate() == 0 );
 
-    GeometryPtr geo = nullptr;
+    std::unique_ptr<geos::geom::Geometry> geo;
     // TODO - mloskot - waiting for resolution
     // http://geos.osgeo.org/pipermail/geos-devel/2006-March/002011.html
     //geo = poly->getEnvelope();
@@ -678,12 +660,10 @@ void object::test<18>
     geo = poly->getBoundary();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
-    geo = poly->convexHull().release();
+    geo = poly->convexHull();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     ensure_equals(poly->getGeometryTypeId(), geos::geom::GEOS_POLYGON);
     ensure_equals(poly->getDimension(), geos::geom::Dimension::A);
@@ -933,7 +913,7 @@ void object::test<24>
     ensure(mp->isValid());
     ensure(mp->getCentroid() == nullptr);
 
-    GeometryPtr geo = nullptr;
+    std::unique_ptr<geos::geom::Geometry> geo;
 
     // TODO - mloskot - waiting for resolution
     // http://geos.osgeo.org/pipermail/geos-devel/2006-March/002011.html
@@ -945,12 +925,10 @@ void object::test<24>
     geo = mp->getBoundary();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
-    geo = mp->convexHull().release();
+    geo = mp->convexHull();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     ensure_equals(mp->getGeometryTypeId(), geos::geom::GEOS_MULTIPOINT);
     ensure_equals(mp->getDimension(), geos::geom::Dimension::P);
@@ -1089,7 +1067,7 @@ void object::test<28>
     ensure(mls->isValid());
     ensure(mls->getCentroid() == nullptr);
 
-    GeometryPtr geo = nullptr;
+    std::unique_ptr<geos::geom::Geometry> geo;
 
     // TODO - mloskot - waiting for resolution
     // http://geos.osgeo.org/pipermail/geos-devel/2006-March/002011.html
@@ -1101,12 +1079,10 @@ void object::test<28>
     geo = mls->getBoundary();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
-    geo = mls->convexHull().release();
+    geo = mls->convexHull();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     ensure_equals(mls->getGeometryTypeId(), geos::geom::GEOS_MULTILINESTRING);
     ensure_equals(mls->getDimension(), geos::geom::Dimension::L);
diff --git a/tests/unit/geom/LineStringTest.cpp b/tests/unit/geom/LineStringTest.cpp
index a55148a..91d640f 100644
--- a/tests/unit/geom/LineStringTest.cpp
+++ b/tests/unit/geom/LineStringTest.cpp
@@ -111,21 +111,18 @@ void object::test<2>
     ensure(!ls->isClosed());
     ensure(!ls->isRing());
 
-    GeometryPtr geo = nullptr;
+    std::unique_ptr<geos::geom::Geometry> geo;
     geo = ls->getEnvelope();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     geo = ls->getBoundary();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
-    geo = ls->convexHull().release();
+    geo = ls->convexHull();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     ensure_equals(ls->getGeometryTypeId(), geos::geom::GEOS_LINESTRING);
     ensure_equals(ls->getDimension(), geos::geom::Dimension::L);
@@ -199,21 +196,18 @@ void object::test<4>
     ensure(!copy->isClosed());
     ensure(!copy->isRing());
 
-    GeometryPtr geo = nullptr;
+    std::unique_ptr<geos::geom::Geometry> geo;
     geo = copy->getEnvelope();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     geo = copy->getBoundary();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
-    geo = copy->convexHull().release();
+    geo = copy->convexHull();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
-    factory_->destroyGeometry(geo);
 
     ensure_equals(copy->getGeometryTypeId(), geos::geom::GEOS_LINESTRING);
     ensure_equals(copy->getDimension(), geos::geom::Dimension::L);
@@ -239,11 +233,9 @@ template<>
 void object::test<6>
 ()
 {
-    GeometryPtr geo = nullptr;
-    geo = empty_line_->getEnvelope();
+    auto geo = empty_line_->getEnvelope();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 }
 
 // Test of getBoundary() for empty linestring
@@ -252,11 +244,9 @@ template<>
 void object::test<7>
 ()
 {
-    GeometryPtr geo = nullptr;
-    geo = empty_line_->getBoundary();
+    auto geo = empty_line_->getBoundary();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 }
 
 // Test of convexHull() for empty linestring
@@ -265,11 +255,9 @@ template<>
 void object::test<8>
 ()
 {
-    GeometryPtr geo = nullptr;
-    geo = empty_line_->convexHull().release();
+    auto geo = empty_line_->convexHull();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
-    factory_->destroyGeometry(geo);
 }
 
 // Test of getGeometryTypeId() for empty linestring
@@ -359,13 +347,11 @@ void object::test<16>
     LineStringPtr line = dynamic_cast<LineStringPtr>(geo);
     ensure(line != nullptr);
 
-    GeometryPtr envelope = line->getEnvelope();
+    auto envelope = line->getEnvelope();
     ensure(envelope != nullptr);
     ensure(!envelope->isEmpty());
     ensure_equals(envelope->getDimension(), geos::geom::Dimension::A);
 
-    factory_->destroyGeometry(envelope);
-
     // FREE TESTED LINESTRING
     factory_->destroyGeometry(line);
 }
@@ -382,12 +368,11 @@ void object::test<17>
     LineStringPtr line = dynamic_cast<LineStringPtr>(geo);
     ensure(line != nullptr);
 
-    GeometryPtr boundary = line->getBoundary();
+    auto boundary = line->getBoundary();
     ensure(boundary != nullptr);
     ensure(!boundary->isEmpty());
     ensure_equals(boundary->getGeometryTypeId(), geos::geom::GEOS_MULTIPOINT);
     ensure_equals(boundary->getDimension(), geos::geom::Dimension::P);
-    factory_->destroyGeometry(boundary);
 
     // FREE TESTED LINESTRING
     factory_->destroyGeometry(line);
@@ -405,12 +390,11 @@ void object::test<18>
     LineStringPtr line = dynamic_cast<LineStringPtr>(geo);
     ensure(line != nullptr);
 
-    GeometryPtr hull = line->convexHull().release();
+    auto hull = line->convexHull();
     ensure(hull != nullptr);
     ensure(!hull->isEmpty());
     ensure_equals(hull->getGeometryTypeId(), geos::geom::GEOS_POLYGON);
     ensure_equals(hull->getDimension(), geos::geom::Dimension::A);
-    factory_->destroyGeometry(hull);
 
     // FREE TESTED LINESTRING
     factory_->destroyGeometry(line);
diff --git a/tests/unit/geom/LinearRingTest.cpp b/tests/unit/geom/LinearRingTest.cpp
index 3c9643c..42600d6 100644
--- a/tests/unit/geom/LinearRingTest.cpp
+++ b/tests/unit/geom/LinearRingTest.cpp
@@ -178,10 +178,9 @@ template<>
 void object::test<8>
 ()
 {
-    GeometryPtr envelope = empty_ring_.getEnvelope();
+    auto envelope = empty_ring_.getEnvelope();
     ensure(envelope != nullptr);
     ensure(envelope->isEmpty());
-    factory_->destroyGeometry(envelope);
 }
 
 // Test of getBoundary() for empty LinearRing
@@ -190,10 +189,9 @@ template<>
 void object::test<9>
 ()
 {
-    GeometryPtr boundary = empty_ring_.getBoundary();
+    auto boundary = empty_ring_.getBoundary();
     ensure(boundary != nullptr);
     ensure(boundary->isEmpty());
-    factory_->destroyGeometry(boundary);
 }
 
 // Test of convexHull() for empty LinearRing
@@ -290,13 +288,10 @@ void object::test<19>
 {
     ensure(ring_ != nullptr);
 
-    GeometryPtr envelope = ring_->getEnvelope();
+    auto envelope = ring_->getEnvelope();
     ensure(envelope != nullptr);
     ensure(!envelope->isEmpty());
     ensure_equals(envelope->getDimension(), geos::geom::Dimension::A);
-
-    // FREE MEMORY
-    factory_->destroyGeometry(envelope);
 }
 
 // Test of getBoundary() for non-empty LinearRing
@@ -307,14 +302,11 @@ void object::test<20>
 {
     ensure(ring_ != nullptr);
 
-    GeometryPtr boundary = ring_->getBoundary();
+    auto boundary = ring_->getBoundary();
     ensure(boundary != nullptr);
 
     // OGC 05-126, Version: 1.1.0, Chapter 6.1.6 Curve
     ensure("[OGC] The boundary of a closed Curve must be empty.", boundary->isEmpty());
-
-    // FREE MEMORY
-    factory_->destroyGeometry(boundary);
 }
 
 // Test of convexHull() for non-empty LinearRing
diff --git a/tests/unit/geom/MultiPointTest.cpp b/tests/unit/geom/MultiPointTest.cpp
index 41b9fb6..1202587 100644
--- a/tests/unit/geom/MultiPointTest.cpp
+++ b/tests/unit/geom/MultiPointTest.cpp
@@ -154,10 +154,9 @@ template<>
 void object::test<7>
 ()
 {
-    GeometryPtr envelope = empty_mp_->getEnvelope();
+    auto envelope = empty_mp_->getEnvelope();
     ensure(envelope != nullptr);
     ensure(envelope->isEmpty());
-    factory_->destroyGeometry(envelope);
 }
 
 // Test of getBoundary() for empty MultiPoint
@@ -166,10 +165,9 @@ template<>
 void object::test<8>
 ()
 {
-    GeometryPtr boundary = empty_mp_->getBoundary();
+    auto boundary = empty_mp_->getBoundary();
     ensure(boundary != nullptr);
     ensure(boundary->isEmpty());
-    factory_->destroyGeometry(boundary);
 }
 
 // Test of convexHull() for empty MultiPoint
@@ -265,13 +263,10 @@ void object::test<18>
 {
     ensure(mp_ != nullptr);
 
-    GeometryPtr envelope = mp_->getEnvelope();
+    auto envelope = mp_->getEnvelope();
     ensure(envelope != nullptr);
     ensure(!envelope->isEmpty());
     ensure_equals(envelope->getDimension(), geos::geom::Dimension::A);
-
-    // FREE MEMORY
-    factory_->destroyGeometry(envelope);
 }
 
 // Test of getBoundary() for non-empty LinearRing
@@ -282,14 +277,11 @@ void object::test<19>
 {
     ensure(mp_ != nullptr);
 
-    GeometryPtr boundary = mp_->getBoundary();
+    auto boundary = mp_->getBoundary();
     ensure(boundary != nullptr);
 
     // OGC 05-126, Version: 1.1.0, Chapter 6.1.5 MultiPoint
     ensure("[OGC] The boundary of a MultiPoint is the empty set.", boundary->isEmpty());
-
-    // FREE MEMORY
-    factory_->destroyGeometry(boundary);
 }
 
 // Test of convexHull() for non-empty LinearRing
diff --git a/tests/unit/geom/PointTest.cpp b/tests/unit/geom/PointTest.cpp
index be7bd77..346dfba 100644
--- a/tests/unit/geom/PointTest.cpp
+++ b/tests/unit/geom/PointTest.cpp
@@ -171,10 +171,9 @@ template<>
 void object::test<8>
 ()
 {
-    GeometryPtr envelope = empty_point_->getEnvelope();
+    auto envelope = empty_point_->getEnvelope();
     ensure(envelope != nullptr);
     ensure(envelope->isEmpty());
-    factory_->destroyGeometry(envelope);
 }
 
 // Test of getBoundary() for empty Point
@@ -183,10 +182,9 @@ template<>
 void object::test<9>
 ()
 {
-    GeometryPtr boundary = empty_point_->getBoundary();
+    auto boundary = empty_point_->getBoundary();
     ensure(boundary != nullptr);
     ensure(boundary->isEmpty());
-    factory_->destroyGeometry(boundary);
 }
 
 // Test of convexHull() for empty Point
@@ -297,10 +295,9 @@ template<>
 void object::test<21>
 ()
 {
-    GeometryPtr envelope = point_->getEnvelope();
+    auto envelope = point_->getEnvelope();
     ensure(envelope != nullptr);
     ensure(!envelope->isEmpty());
-    factory_->destroyGeometry(envelope);
 }
 
 // Test of getBoundary() for non-empty Point
@@ -309,10 +306,9 @@ template<>
 void object::test<22>
 ()
 {
-    GeometryPtr boundary = point_->getBoundary();
+    auto boundary = point_->getBoundary();
     ensure(boundary != nullptr);
     ensure(boundary->isEmpty());
-    factory_->destroyGeometry(boundary);
 }
 
 // Test of convexHull() for non-empty Point
diff --git a/tests/unit/geom/PolygonTest.cpp b/tests/unit/geom/PolygonTest.cpp
index 15196ea..8713e0d 100644
--- a/tests/unit/geom/PolygonTest.cpp
+++ b/tests/unit/geom/PolygonTest.cpp
@@ -190,10 +190,9 @@ template<>
 void object::test<7>
 ()
 {
-    GeometryPtr boundary = empty_poly_->getBoundary();
+    auto boundary = empty_poly_->getBoundary();
     ensure(boundary != nullptr);
     ensure(boundary->isEmpty());
-    factory_->destroyGeometry(boundary);
 }
 
 // Test of convexHull() for empty Polygon
@@ -279,13 +278,10 @@ void object::test<17>
 {
     ensure(poly_ != nullptr);
 
-    GeometryPtr envelope = poly_->getEnvelope();
+    auto envelope = poly_->getEnvelope();
     ensure(envelope != nullptr);
     ensure(!envelope->isEmpty());
     ensure_equals(envelope->getDimension(), geos::geom::Dimension::A);
-
-    // FREE MEMORY
-    factory_->destroyGeometry(envelope);
 }
 
 // Test of getBoundary() for non-empty Polygon
@@ -296,14 +292,11 @@ void object::test<18>
 {
     ensure(poly_ != nullptr);
 
-    GeometryPtr boundary = poly_->getBoundary();
+    auto boundary = poly_->getBoundary();
     ensure(boundary != nullptr);
 
     // OGC 05-126, Version: 1.1.0, Chapter 6.1.10 Surface
     ensure("[OGC] The boundary of Polygin is the set of closed Curves.", !boundary->isEmpty());
-
-    // FREE MEMORY
-    factory_->destroyGeometry(boundary);
 }
 
 // Test of convexHull() for non-empty Polygon
@@ -522,7 +515,7 @@ template<>
 void object::test<34>
 ()
 {
-    PointPtr point = empty_poly_->getCentroid();
+    auto point = empty_poly_->getCentroid();
     ensure(point == nullptr);
 }
 
@@ -543,13 +536,10 @@ template<>
 void object::test<36>
 ()
 {
-    PointPtr point = poly_->getCentroid();
+    auto point = poly_->getCentroid();
     ensure(point != nullptr);
     ensure(!point->isEmpty());
     ensure_equals(point->getGeometryTypeId(), geos::geom::GEOS_POINT);
-
-    // FREE MEMORY
-    factory_->destroyGeometry(point);
 }
 
 // Test of Geometry::getCentroid(Coordinate& ret) const for non-empty Polygon
@@ -570,7 +560,7 @@ void object::test<38>
 ()
 {
     // First centroid
-    PointPtr point = poly_->getCentroid();
+    auto point = poly_->getCentroid();
     ensure(point != nullptr);
     ensure(!point->isEmpty());
     ensure_equals(point->getGeometryTypeId(), geos::geom::GEOS_POINT);
@@ -578,8 +568,6 @@ void object::test<38>
     CoordinateCPtr pointCoord = point->getCoordinate();
     ensure(pointCoord != nullptr);
     geos::geom::Coordinate pointCentr(*pointCoord);
-    // FREE MEMORY
-    factory_->destroyGeometry(point);
 
     // Second centroid
     geos::geom::Coordinate coordCentr;

commit fc8ff4b33182759608e5a54ace7461d22246240c
Author: Daniel Baston <dbaston at gmail.com>
Date:   Tue May 28 16:57:34 2019 -0400

    Return unique_ptr from Geometry::convexHull()

diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp
index f2d2931..55d3cba 100644
--- a/capi/geos_ts_c.cpp
+++ b/capi/geos_ts_c.cpp
@@ -1903,7 +1903,7 @@ extern "C" {
         }
 
         try {
-            Geometry* g3 = g1->convexHull();
+            Geometry* g3 = g1->convexHull().release();
             return g3;
         }
         catch(const std::exception& e) {
diff --git a/include/geos/algorithm/ConvexHull.h b/include/geos/algorithm/ConvexHull.h
index 3b7b0ef..c611a45 100644
--- a/include/geos/algorithm/ConvexHull.h
+++ b/include/geos/algorithm/ConvexHull.h
@@ -139,7 +139,7 @@ private:
      *                   collinear; otherwise, a Polygon with unnecessary
      *                   (collinear) vertices removed
      */
-    geom::Geometry* lineOrPolygon(const geom::Coordinate::ConstVect& vertices);
+    std::unique_ptr<geom::Geometry> lineOrPolygon(const geom::Coordinate::ConstVect& vertices);
 
     /**
      * Write in 'cleaned' a version of 'input' with collinear
@@ -176,7 +176,7 @@ public:
      *         a Polygon; 2 points, a LineString;
      *         1 point, a Point; 0 points, an empty GeometryCollection.
      */
-    geom::Geometry* getConvexHull();
+    std::unique_ptr<geom::Geometry> getConvexHull();
 };
 
 } // namespace geos::algorithm
diff --git a/include/geos/geom/Geometry.h b/include/geos/geom/Geometry.h
index eef2633..3b44a72 100644
--- a/include/geos/geom/Geometry.h
+++ b/include/geos/geom/Geometry.h
@@ -629,7 +629,7 @@ public:
     /// \brief
     /// Returns the smallest convex Polygon that contains
     /// all the points in the Geometry.
-    virtual Geometry* convexHull() const;
+    virtual std::unique_ptr<Geometry> convexHull() const;
 
     /**
      * Computes a new geometry which has all component coordinate sequences
diff --git a/include/geos/geom/Polygon.h b/include/geos/geom/Polygon.h
index f53114f..17c0b67 100644
--- a/include/geos/geom/Polygon.h
+++ b/include/geos/geom/Polygon.h
@@ -129,7 +129,7 @@ public:
     void apply_rw(GeometryComponentFilter* filter) override;
     void apply_ro(GeometryComponentFilter* filter) const override;
 
-    Geometry* convexHull() const override;
+    std::unique_ptr<Geometry> convexHull() const override;
 
     void normalize() override;
 
diff --git a/src/algorithm/ConvexHull.cpp b/src/algorithm/ConvexHull.cpp
index d0e4573..069fd81 100644
--- a/src/algorithm/ConvexHull.cpp
+++ b/src/algorithm/ConvexHull.cpp
@@ -227,24 +227,24 @@ ConvexHull::padArray3(geom::Coordinate::ConstVect& pts)
     }
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 ConvexHull::getConvexHull()
 {
     size_t nInputPts = inputPts.size();
 
     if(nInputPts == 0) { // Return an empty geometry
-        return geomFactory->createEmptyGeometry();
+        return std::unique_ptr<Geometry>(geomFactory->createEmptyGeometry());
     }
 
     if(nInputPts == 1) { // Return a Point
         // Copy the Coordinate from the ConstVect
-        return geomFactory->createPoint(*(inputPts[0]));
+        return std::unique_ptr<Geometry>(geomFactory->createPoint(*(inputPts[0])));
     }
 
     if(nInputPts == 2) { // Return a LineString
         // Copy all Coordinates from the ConstVect
         auto cs = toCoordinateSequence(inputPts);
-        return geomFactory->createLineString(cs.release());
+        return std::unique_ptr<Geometry>(geomFactory->createLineString(cs.release()));
     }
 
     // use heuristic to reduce points, if large
@@ -266,7 +266,6 @@ ConvexHull::getConvexHull()
     GEOS_CHECK_FOR_INTERRUPTS();
 
     return lineOrPolygon(cHS);
-
 }
 
 /* private */
@@ -343,7 +342,7 @@ ConvexHull::isBetween(const Coordinate& c1, const Coordinate& c2, const Coordina
 
 
 /* private */
-Geometry*
+std::unique_ptr<Geometry>
 ConvexHull::lineOrPolygon(const Coordinate::ConstVect& input)
 {
     Coordinate::ConstVect cleaned;
@@ -353,12 +352,12 @@ ConvexHull::lineOrPolygon(const Coordinate::ConstVect& input)
     if(cleaned.size() == 3) { // shouldn't this be 2 ??
         cleaned.resize(2);
         auto cl1 = toCoordinateSequence(cleaned);
-        LineString* ret = geomFactory->createLineString(cl1.release());
+        std::unique_ptr<LineString> ret(geomFactory->createLineString(cl1.release()));
         return ret;
     }
     auto cl2 = toCoordinateSequence(cleaned);
     LinearRing* linearRing = geomFactory->createLinearRing(cl2.release());
-    return geomFactory->createPolygon(linearRing, nullptr);
+    return std::unique_ptr<Geometry>(geomFactory->createPolygon(linearRing, nullptr));
 }
 
 /*private*/
diff --git a/src/algorithm/MinimumDiameter.cpp b/src/algorithm/MinimumDiameter.cpp
index 08eead9..65884d6 100644
--- a/src/algorithm/MinimumDiameter.cpp
+++ b/src/algorithm/MinimumDiameter.cpp
@@ -179,9 +179,8 @@ MinimumDiameter::computeMinimumDiameter()
     }
     else {
         ConvexHull ch(inputGeom);
-        Geometry* convexGeom = ch.getConvexHull();
-        computeWidthConvex(convexGeom);
-        delete convexGeom;
+        std::unique_ptr<Geometry> convexGeom = ch.getConvexHull();
+        computeWidthConvex(convexGeom.get());
     }
 }
 
diff --git a/src/geom/Geometry.cpp b/src/geom/Geometry.cpp
index 238ea61..e10163a 100644
--- a/src/geom/Geometry.cpp
+++ b/src/geom/Geometry.cpp
@@ -541,7 +541,7 @@ Geometry::buffer(double p_distance, int quadrantSegments, int endCapStyle) const
     return BufferOp::bufferOp(this, p_distance, quadrantSegments, endCapStyle);
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 Geometry::convexHull() const
 {
     return ConvexHull(this).getConvexHull();
diff --git a/src/geom/Polygon.cpp b/src/geom/Polygon.cpp
index b46fa95..5d09d16 100644
--- a/src/geom/Polygon.cpp
+++ b/src/geom/Polygon.cpp
@@ -297,7 +297,7 @@ Polygon::apply_ro(GeometryFilter* filter) const
     filter->filter_ro(this);
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 Polygon::convexHull() const
 {
     return getExteriorRing()->convexHull();
diff --git a/tests/unit/algorithm/ConvexHullTest.cpp b/tests/unit/algorithm/ConvexHullTest.cpp
index 8116308..6116524 100644
--- a/tests/unit/algorithm/ConvexHullTest.cpp
+++ b/tests/unit/algorithm/ConvexHullTest.cpp
@@ -34,7 +34,7 @@ namespace tut {
 
 // dummy data, not used
 struct test_convexhull_data {
-    GeometryPtr geom_;
+    std::unique_ptr<Geometry> geom_;
     geos::geom::PrecisionModel pm_;
     geos::geom::GeometryFactory::Ptr factory_;
     geos::io::WKTReader reader_;
@@ -44,12 +44,6 @@ struct test_convexhull_data {
     {
         assert(nullptr == geom_);
     }
-
-    ~test_convexhull_data()
-    {
-        factory_->destroyGeometry(geom_);
-        geom_ = nullptr;
-    }
 };
 
 typedef test_group<test_convexhull_data> group;
@@ -78,7 +72,7 @@ void object::test<1>
     ensure(nullptr != convexHull.get());
 
     geom_ = line->convexHull();
-    ensure(convexHull->equalsExact(geom_));
+    ensure(convexHull->equalsExact(geom_.get()));
 }
 
 // 2 - Test convex hull of multipoint
@@ -97,7 +91,7 @@ void object::test<2>
     ensure(nullptr != convexHull.get());
 
     geom_ = geom->convexHull();
-    ensure(convexHull->equalsExact(geom_));
+    ensure(convexHull->equalsExact(geom_.get()));
 }
 
 // 3 - Test convex hull of multipoint
@@ -116,7 +110,7 @@ void object::test<3>
     ensure(nullptr != convexHull.get());
 
     geom_ = geom->convexHull();
-    ensure(convexHull->equalsExact(geom_));
+    ensure(convexHull->equalsExact(geom_.get()));
 }
 
 // 4 - Test convex hull of multipoint
@@ -135,7 +129,7 @@ void object::test<4>
     ensure(nullptr != convexHull.get());
 
     geom_ = geom->convexHull();
-    ensure(convexHull->equalsExact(geom_));
+    ensure(convexHull->equalsExact(geom_.get()));
 }
 
 // 5 - Test convex hull of multipoint
@@ -154,7 +148,7 @@ void object::test<5>
     ensure(nullptr != convexHull.get());
 
     geom_ = geom->convexHull();
-    ensure(convexHull->equalsExact(geom_));
+    ensure(convexHull->equalsExact(geom_.get()));
 }
 
 // 6 - Test convex hull of multipoint exported to string form
@@ -193,7 +187,7 @@ void object::test<7>
     ensure(nullptr != convexHull.get());
 
     geom_ = geom->convexHull();
-    ensure(convexHull->equalsExact(geom_));
+    ensure(convexHull->equalsExact(geom_.get()));
 }
 
 } // namespace tut
diff --git a/tests/unit/geom/GeometryFactoryTest.cpp b/tests/unit/geom/GeometryFactoryTest.cpp
index 7a8b041..05a140b 100644
--- a/tests/unit/geom/GeometryFactoryTest.cpp
+++ b/tests/unit/geom/GeometryFactoryTest.cpp
@@ -269,7 +269,7 @@ void object::test<8>
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
 
-    geo = pt->convexHull();
+    geo = pt->convexHull().release();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
@@ -323,7 +323,7 @@ void object::test<9>
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
 
-    geo = pt->convexHull();
+    geo = pt->convexHull().release();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
     factory_->destroyGeometry(geo);
@@ -382,7 +382,7 @@ void object::test<10>
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
 
-    geo = pt->convexHull();
+    geo = pt->convexHull().release();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
     factory_->destroyGeometry(geo);
@@ -439,7 +439,7 @@ void object::test<11>
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
 
-    geo = pt->convexHull();
+    geo = pt->convexHull().release();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
     factory_->destroyGeometry(geo);
@@ -576,7 +576,7 @@ void object::test<15>
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
 
-    geo = line->convexHull();
+    geo = line->convexHull().release();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
@@ -680,7 +680,7 @@ void object::test<18>
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
 
-    geo = poly->convexHull();
+    geo = poly->convexHull().release();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
@@ -947,7 +947,7 @@ void object::test<24>
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
 
-    geo = mp->convexHull();
+    geo = mp->convexHull().release();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
@@ -1103,7 +1103,7 @@ void object::test<28>
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
 
-    geo = mls->convexHull();
+    geo = mls->convexHull().release();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
diff --git a/tests/unit/geom/LineStringTest.cpp b/tests/unit/geom/LineStringTest.cpp
index 56abf10..a55148a 100644
--- a/tests/unit/geom/LineStringTest.cpp
+++ b/tests/unit/geom/LineStringTest.cpp
@@ -122,7 +122,7 @@ void object::test<2>
     ensure(!geo->isEmpty());
     factory_->destroyGeometry(geo);
 
-    geo = ls->convexHull();
+    geo = ls->convexHull().release();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
     factory_->destroyGeometry(geo);
@@ -210,7 +210,7 @@ void object::test<4>
     ensure(!geo->isEmpty());
     factory_->destroyGeometry(geo);
 
-    geo = copy->convexHull();
+    geo = copy->convexHull().release();
     ensure(geo != nullptr);
     ensure(!geo->isEmpty());
     factory_->destroyGeometry(geo);
@@ -266,7 +266,7 @@ void object::test<8>
 ()
 {
     GeometryPtr geo = nullptr;
-    geo = empty_line_->convexHull();
+    geo = empty_line_->convexHull().release();
     ensure(geo != nullptr);
     ensure(geo->isEmpty());
     factory_->destroyGeometry(geo);
@@ -405,7 +405,7 @@ void object::test<18>
     LineStringPtr line = dynamic_cast<LineStringPtr>(geo);
     ensure(line != nullptr);
 
-    GeometryPtr hull = line->convexHull();
+    GeometryPtr hull = line->convexHull().release();
     ensure(hull != nullptr);
     ensure(!hull->isEmpty());
     ensure_equals(hull->getGeometryTypeId(), geos::geom::GEOS_POLYGON);
diff --git a/tests/unit/geom/LinearRingTest.cpp b/tests/unit/geom/LinearRingTest.cpp
index 08717aa..3c9643c 100644
--- a/tests/unit/geom/LinearRingTest.cpp
+++ b/tests/unit/geom/LinearRingTest.cpp
@@ -202,10 +202,9 @@ template<>
 void object::test<10>
 ()
 {
-    GeometryPtr hull = empty_ring_.convexHull();
+    auto hull = empty_ring_.convexHull();
     ensure(hull != nullptr);
     ensure(hull->isEmpty());
-    factory_->destroyGeometry(hull);
 }
 
 // Test of getGeometryTypeId() for empty LinearRing
@@ -326,14 +325,11 @@ void object::test<21>
 {
     ensure(ring_ != nullptr);
 
-    GeometryPtr hull = ring_->convexHull();
+    auto hull = ring_->convexHull();
     ensure(hull != nullptr);
     ensure(!hull->isEmpty());
     ensure_equals(hull->getGeometryTypeId(), geos::geom::GEOS_POLYGON);
     ensure_equals(hull->getDimension(), geos::geom::Dimension::A);
-
-    // FREE MEMORY
-    factory_->destroyGeometry(hull);
 }
 
 // Test of getGeometryTypeId() for non-empty LinearRing
diff --git a/tests/unit/geom/MultiPointTest.cpp b/tests/unit/geom/MultiPointTest.cpp
index 2fb4fc8..41b9fb6 100644
--- a/tests/unit/geom/MultiPointTest.cpp
+++ b/tests/unit/geom/MultiPointTest.cpp
@@ -178,10 +178,9 @@ template<>
 void object::test<9>
 ()
 {
-    GeometryPtr hull = empty_mp_->convexHull();
+    auto hull = empty_mp_->convexHull();
     ensure(hull != nullptr);
     ensure(hull->isEmpty());
-    factory_->destroyGeometry(hull);
 }
 
 // Test of getGeometryTypeId() for empty MultiPoint
@@ -301,14 +300,11 @@ void object::test<20>
 {
     ensure(mp_ != nullptr);
 
-    GeometryPtr hull = mp_->convexHull();
+    auto hull = mp_->convexHull();
     ensure(hull != nullptr);
     ensure(!hull->isEmpty());
     ensure_equals(hull->getGeometryTypeId(), geos::geom::GEOS_LINESTRING);
     ensure_equals(hull->getDimension(), geos::geom::Dimension::L);
-
-    // FREE MEMORY
-    factory_->destroyGeometry(hull);
 }
 
 // Test of getGeometryTypeId() for non-empty LinearRing
diff --git a/tests/unit/geom/PointTest.cpp b/tests/unit/geom/PointTest.cpp
index 3334c0c..be7bd77 100644
--- a/tests/unit/geom/PointTest.cpp
+++ b/tests/unit/geom/PointTest.cpp
@@ -195,10 +195,9 @@ template<>
 void object::test<10>
 ()
 {
-    GeometryPtr hull = empty_point_->convexHull();
+    auto hull = empty_point_->convexHull();
     ensure(hull != nullptr);
     ensure(hull->isEmpty());
-    factory_->destroyGeometry(hull);
 }
 
 // Test of getGeometryTypeId() for empty Point
@@ -322,10 +321,9 @@ template<>
 void object::test<23>
 ()
 {
-    GeometryPtr hull = point_->convexHull();
+    auto hull = point_->convexHull();
     ensure(hull != nullptr);
     ensure(!hull->isEmpty());
-    factory_->destroyGeometry(hull);
 }
 
 // Test of getGeometryTypeId() for non-empty Point
diff --git a/tests/unit/geom/PolygonTest.cpp b/tests/unit/geom/PolygonTest.cpp
index 2436ee3..15196ea 100644
--- a/tests/unit/geom/PolygonTest.cpp
+++ b/tests/unit/geom/PolygonTest.cpp
@@ -202,10 +202,9 @@ template<>
 void object::test<8>
 ()
 {
-    GeometryPtr hull = empty_poly_->convexHull();
+    auto hull = empty_poly_->convexHull();
     ensure(hull != nullptr);
     ensure(hull->isEmpty());
-    factory_->destroyGeometry(hull);
 }
 
 // Test of getGeometryTypeId() for empty Polygon
@@ -315,14 +314,11 @@ void object::test<19>
 {
     ensure(poly_ != nullptr);
 
-    GeometryPtr hull = poly_->convexHull();
+    auto hull = poly_->convexHull();
     ensure(hull != nullptr);
     ensure(!hull->isEmpty());
     ensure_equals(hull->getGeometryTypeId(), geos::geom::GEOS_POLYGON);
     ensure_equals(hull->getDimension(), geos::geom::Dimension::A);
-
-    // FREE MEMORY
-    factory_->destroyGeometry(hull);
 }
 
 // Test of getGeometryTypeId() for non-empty Polygon

commit a7a25f45cc563172ff64d5ad0f6190090c53f723
Author: Daniel Baston <dbaston at gmail.com>
Date:   Tue May 28 16:47:15 2019 -0400

    Return unique_ptr from Geometry::clone and Geometry::reverse

diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp
index b7355fc..f2d2931 100644
--- a/capi/geos_ts_c.cpp
+++ b/capi/geos_ts_c.cpp
@@ -3332,7 +3332,7 @@ extern "C" {
             std::vector<Geometry*>* linevec = new std::vector<Geometry*>(lines.size());
 
             for(std::size_t i = 0, n = lines.size(); i < n; ++i) {
-                (*linevec)[i] = lines[i]->clone();
+                (*linevec)[i] = lines[i]->clone().release();
             }
 
             const GeometryFactory* gf = handle->geomFactory;
@@ -3383,7 +3383,7 @@ extern "C" {
                 const std::vector<const LineString*>& lines = plgnzr.getCutEdges();
                 std::vector<Geometry*>* linevec = new std::vector<Geometry*>(lines.size());
                 for(std::size_t i = 0, n = lines.size(); i < n; ++i) {
-                    (*linevec)[i] = lines[i]->clone();
+                    (*linevec)[i] = lines[i]->clone().release();
                 }
 
                 // The below takes ownership of the passed vector,
@@ -3396,7 +3396,7 @@ extern "C" {
                 const std::vector<const LineString*>& lines = plgnzr.getDangles();
                 std::vector<Geometry*>* linevec = new std::vector<Geometry*>(lines.size());
                 for(std::size_t i = 0, n = lines.size(); i < n; ++i) {
-                    (*linevec)[i] = lines[i]->clone();
+                    (*linevec)[i] = lines[i]->clone().release();
                 }
 
                 // The below takes ownership of the passed vector,
@@ -3409,7 +3409,7 @@ extern "C" {
                 const std::vector<LineString*>& lines = plgnzr.getInvalidRingLines();
                 std::vector<Geometry*>* linevec = new std::vector<Geometry*>(lines.size());
                 for(std::size_t i = 0, n = lines.size(); i < n; ++i) {
-                    (*linevec)[i] = lines[i]->clone();
+                    (*linevec)[i] = lines[i]->clone().release();
                 }
 
                 // The below takes ownership of the passed vector,
@@ -3502,7 +3502,7 @@ extern "C" {
         }
 
         try {
-            return g->reverse();
+            return g->reverse().release();
         }
         catch(const std::exception& e) {
             handle->ERROR_MESSAGE("%s", e.what());
@@ -4225,7 +4225,7 @@ extern "C" {
         }
 
         try {
-            return g->clone();
+            return g->clone().release();
         }
         catch(const std::exception& e) {
             handle->ERROR_MESSAGE("%s", e.what());
diff --git a/include/geos/geom/BinaryOp.h b/include/geos/geom/BinaryOp.h
index c973900..b136627 100644
--- a/include/geos/geom/BinaryOp.h
+++ b/include/geos/geom/BinaryOp.h
@@ -298,8 +298,8 @@ SnapOp(const Geometry* g0, const Geometry* g1, BinOp _Op)
 #endif
 
     // Now remove common bits
-    GeomPtr rG0(cbr.removeCommonBits(g0->clone()));
-    GeomPtr rG1(cbr.removeCommonBits(g1->clone()));
+    GeomPtr rG0(cbr.removeCommonBits(g0->clone().release()));
+    GeomPtr rG1(cbr.removeCommonBits(g1->clone().release()));
 
 #if GEOS_DEBUG_BINARYOP
     check_valid(*rG0, "CBR: removed-bits geom 0");
@@ -399,8 +399,8 @@ BinaryOp(const Geometry* g0, const Geometry* g1, BinOp _Op)
         cbr.add(g0);
         cbr.add(g1);
 
-        rG0.reset(cbr.removeCommonBits(g0->clone()));
-        rG1.reset(cbr.removeCommonBits(g1->clone()));
+        rG0.reset(cbr.removeCommonBits(g0->clone().release()));
+        rG1.reset(cbr.removeCommonBits(g1->clone().release()));
 
 #if GEOS_DEBUG_BINARYOP
         check_valid(*rG0, "CBR: geom 0 (after common-bits removal)");
diff --git a/include/geos/geom/Geometry.h b/include/geos/geom/Geometry.h
index 10f223d..eef2633 100644
--- a/include/geos/geom/Geometry.h
+++ b/include/geos/geom/Geometry.h
@@ -200,7 +200,7 @@ public:
     using Ptr = std::unique_ptr<Geometry> ;
 
     /// Make a deep-copy of this Geometry
-    virtual Geometry* clone() const = 0;
+    virtual std::unique_ptr<Geometry> clone() const = 0;
 
     /// Destroy Geometry and all components
     virtual ~Geometry();
@@ -637,7 +637,7 @@ public:
      *
      * @return a reversed geometry
      */
-    virtual Geometry* reverse() const = 0;
+    virtual std::unique_ptr<Geometry> reverse() const = 0;
 
     /** \brief
      * Returns a Geometry representing the points shared by
diff --git a/include/geos/geom/GeometryCollection.h b/include/geos/geom/GeometryCollection.h
index 60acc7d..efa040f 100644
--- a/include/geos/geom/GeometryCollection.h
+++ b/include/geos/geom/GeometryCollection.h
@@ -71,10 +71,10 @@ public:
      *
      * @return a clone of this instance
      */
-    Geometry*
+    std::unique_ptr<Geometry>
     clone() const override
     {
-        return new GeometryCollection(*this);
+        return std::unique_ptr<Geometry>(new GeometryCollection(*this));
     }
 
     ~GeometryCollection() override;
@@ -167,7 +167,7 @@ public:
      *
      * @return a GeometryCollection in the reverse order
      */
-    Geometry* reverse() const override;
+    std::unique_ptr<Geometry> reverse() const override;
 
 protected:
 
diff --git a/include/geos/geom/LineString.h b/include/geos/geom/LineString.h
index 0352460..3c057a3 100644
--- a/include/geos/geom/LineString.h
+++ b/include/geos/geom/LineString.h
@@ -84,7 +84,7 @@ public:
      *
      * @return A clone of this instance
      */
-    Geometry* clone() const override;
+    std::unique_ptr<Geometry> clone() const override;
 
     std::unique_ptr<CoordinateSequence> getCoordinates() const override;
 
@@ -182,7 +182,7 @@ public:
      *
      * @return a LineString with coordinates in the reverse order
      */
-    Geometry* reverse() const override;
+    std::unique_ptr<Geometry> reverse() const override;
 
 protected:
 
@@ -222,10 +222,10 @@ struct GEOS_DLL  LineStringLT {
 };
 
 
-inline Geometry*
+inline std::unique_ptr<Geometry>
 LineString::clone() const
 {
-    return new LineString(*this);
+    return std::unique_ptr<Geometry>(new LineString(*this));
 }
 
 } // namespace geos::geom
diff --git a/include/geos/geom/LinearRing.h b/include/geos/geom/LinearRing.h
index 11cb494..4b5a7be 100644
--- a/include/geos/geom/LinearRing.h
+++ b/include/geos/geom/LinearRing.h
@@ -84,10 +84,10 @@ public:
     LinearRing(CoordinateSequence::Ptr points,
                const GeometryFactory* newFactory);
 
-    Geometry*
+    std::unique_ptr<Geometry>
     clone() const override
     {
-        return new LinearRing(*this);
+        return std::unique_ptr<Geometry>(new LinearRing(*this));
     }
 
     ~LinearRing() override;
@@ -108,7 +108,7 @@ public:
 
     void setPoints(const CoordinateSequence* cl);
 
-    Geometry* reverse() const override;
+    std::unique_ptr<Geometry> reverse() const override;
 
 protected:
 
diff --git a/include/geos/geom/MultiLineString.h b/include/geos/geom/MultiLineString.h
index 95cd362..ab12e6f 100644
--- a/include/geos/geom/MultiLineString.h
+++ b/include/geos/geom/MultiLineString.h
@@ -77,7 +77,7 @@ public:
 
     bool equalsExact(const Geometry* other, double tolerance = 0) const override;
 
-    Geometry* clone() const override;
+    std::unique_ptr<Geometry> clone() const override;
 
     /**
      * Creates a MultiLineString in the reverse
@@ -88,7 +88,7 @@ public:
      *
      * @return a MultiLineString in the reverse order
      */
-    Geometry* reverse() const override;
+    std::unique_ptr<Geometry> reverse() const override;
 
 protected:
 
diff --git a/include/geos/geom/MultiLineString.inl b/include/geos/geom/MultiLineString.inl
index 3820859..e37596e 100644
--- a/include/geos/geom/MultiLineString.inl
+++ b/include/geos/geom/MultiLineString.inl
@@ -36,10 +36,10 @@ MultiLineString::MultiLineString(const MultiLineString& mp)
 {
 }
 
-INLINE Geometry*
+INLINE std::unique_ptr<Geometry>
 MultiLineString::clone() const
 {
-    return new MultiLineString(*this);
+    return std::unique_ptr<Geometry>(new MultiLineString(*this));
 }
 
 } // namespace geos::geom
diff --git a/include/geos/geom/MultiPoint.h b/include/geos/geom/MultiPoint.h
index 3f2e227..8d30dc8 100644
--- a/include/geos/geom/MultiPoint.h
+++ b/include/geos/geom/MultiPoint.h
@@ -82,13 +82,13 @@ public:
 
     bool equalsExact(const Geometry* other, double tolerance = 0) const override;
 
-    Geometry*
+    std::unique_ptr<Geometry>
     clone() const override
     {
-        return new MultiPoint(*this);
+        return std::unique_ptr<Geometry>(new MultiPoint(*this));
     }
 
-    Geometry*
+    std::unique_ptr<Geometry>
     reverse() const override
     {
         return clone();
diff --git a/include/geos/geom/MultiPolygon.h b/include/geos/geom/MultiPolygon.h
index 57e72e6..a0a4f54 100644
--- a/include/geos/geom/MultiPolygon.h
+++ b/include/geos/geom/MultiPolygon.h
@@ -83,9 +83,9 @@ public:
 
     bool equalsExact(const Geometry* other, double tolerance = 0) const override;
 
-    Geometry* clone() const override;
+    std::unique_ptr<Geometry> clone() const override;
 
-    Geometry* reverse() const override;
+    std::unique_ptr<Geometry> reverse() const override;
 
 protected:
 
diff --git a/include/geos/geom/MultiPolygon.inl b/include/geos/geom/MultiPolygon.inl
index e37a7e2..4ddb9bc 100644
--- a/include/geos/geom/MultiPolygon.inl
+++ b/include/geos/geom/MultiPolygon.inl
@@ -33,10 +33,10 @@ MultiPolygon::MultiPolygon(const MultiPolygon& mp)
 {
 }
 
-INLINE Geometry*
+INLINE std::unique_ptr<Geometry>
 MultiPolygon::clone() const
 {
-    return new MultiPolygon(*this);
+    return std::unique_ptr<Geometry>(new MultiPolygon(*this));
 }
 
 } // namespace geos::geom
diff --git a/include/geos/geom/Point.h b/include/geos/geom/Point.h
index 8d8741e..4406205 100644
--- a/include/geos/geom/Point.h
+++ b/include/geos/geom/Point.h
@@ -80,10 +80,10 @@ public:
      *
      * @return a clone of this instance
      */
-    Geometry*
+    std::unique_ptr<Geometry>
     clone() const override
     {
-        return new Point(*this);
+        return std::unique_ptr<Geometry>(new Point(*this));
     }
 
     std::unique_ptr<CoordinateSequence> getCoordinates(void) const override;
@@ -136,7 +136,7 @@ public:
         // a Point is always in normalized form
     }
 
-    Geometry*
+    std::unique_ptr<Geometry>
     reverse() const override
     {
         return clone();
diff --git a/include/geos/geom/Polygon.h b/include/geos/geom/Polygon.h
index 7c06522..f53114f 100644
--- a/include/geos/geom/Polygon.h
+++ b/include/geos/geom/Polygon.h
@@ -79,10 +79,10 @@ public:
      *
      * @return a clone of this instance
      */
-    Geometry*
+    std::unique_ptr<Geometry>
     clone() const override
     {
-        return new Polygon(*this);
+        return std::unique_ptr<Geometry>(new Polygon(*this));
     }
 
     std::unique_ptr<CoordinateSequence> getCoordinates() const override;
@@ -133,7 +133,7 @@ public:
 
     void normalize() override;
 
-    Geometry* reverse() const override;
+    std::unique_ptr<Geometry> reverse() const override;
 
     int compareToSameClass(const Geometry* p) const override; //was protected
 
diff --git a/include/geos/linearref/ExtractLineByLocation.h b/include/geos/linearref/ExtractLineByLocation.h
index 43e9968..b278dc1 100644
--- a/include/geos/linearref/ExtractLineByLocation.h
+++ b/include/geos/linearref/ExtractLineByLocation.h
@@ -35,7 +35,7 @@ class ExtractLineByLocation {
 
 private:
     const geom::Geometry* line;
-    geom::Geometry* reverse(const geom::Geometry* linear);
+    std::unique_ptr<geom::Geometry> reverse(const geom::Geometry* linear);
 
     /**
      * Assumes input is valid (e.g. start <= end)
@@ -44,7 +44,7 @@ private:
      * @param end
      * @return a linear geometry
      */
-    geom::LineString* computeLine(const LinearLocation& start, const LinearLocation& end);
+    std::unique_ptr<geom::LineString> computeLine(const LinearLocation& start, const LinearLocation& end);
 
     /**
      * Assumes input is valid (e.g. start <= end)
@@ -53,7 +53,7 @@ private:
      * @param end
      * @return a linear geometry
      */
-    geom::Geometry* computeLinear(const LinearLocation& start, const LinearLocation& end);
+    std::unique_ptr<geom::Geometry> computeLinear(const LinearLocation& start, const LinearLocation& end);
 
 public:
     /**
@@ -67,7 +67,7 @@ public:
      * @param end the end location
      * @return the extracted subline
      */
-    static geom::Geometry* extract(const geom::Geometry* line, const LinearLocation& start, const LinearLocation& end);
+    static std::unique_ptr<geom::Geometry> extract(const geom::Geometry* line, const LinearLocation& start, const LinearLocation& end);
 
     ExtractLineByLocation(const geom::Geometry* line);
 
@@ -79,7 +79,7 @@ public:
      * @param end the end location
      * @return a linear geometry
      */
-    geom::Geometry* extract(const LinearLocation& start, const LinearLocation& end);
+    std::unique_ptr<geom::Geometry> extract(const LinearLocation& start, const LinearLocation& end);
 
 };
 }
diff --git a/include/geos/linearref/LengthIndexedLine.h b/include/geos/linearref/LengthIndexedLine.h
index d0c74b3..09ed091 100644
--- a/include/geos/linearref/LengthIndexedLine.h
+++ b/include/geos/linearref/LengthIndexedLine.h
@@ -102,7 +102,7 @@ public:
      * @param endIndex the index of the end of the interval
      * @return the linear interval between the indices
      */
-    geom::Geometry* extractLine(double startIndex, double endIndex) const;
+    std::unique_ptr<geom::Geometry> extractLine(double startIndex, double endIndex) const;
 
 
     /**
diff --git a/include/geos/linearref/LocationIndexedLine.h b/include/geos/linearref/LocationIndexedLine.h
index 3ea639c..5b857f4 100644
--- a/include/geos/linearref/LocationIndexedLine.h
+++ b/include/geos/linearref/LocationIndexedLine.h
@@ -125,7 +125,7 @@ public:
      * @param endIndex the index of the end of the interval
      * @return the linear interval between the indices
      */
-    geom::Geometry*
+    std::unique_ptr<geom::Geometry>
     extractLine(const LinearLocation& startIndex,
                 const LinearLocation& endIndex) const
     {
diff --git a/src/geom/Geometry.cpp b/src/geom/Geometry.cpp
index 1ffacbe..238ea61 100644
--- a/src/geom/Geometry.cpp
+++ b/src/geom/Geometry.cpp
@@ -587,10 +587,10 @@ Geometry::Union(const Geometry* other) const
 
     // special case: if one input is empty ==> other input
     if(isEmpty()) {
-        return other->clone();
+        return other->clone().release();
     }
     if(other->isEmpty()) {
-        return clone();
+        return clone().release();
     }
 
     Geometry* out = nullptr;
@@ -612,20 +612,20 @@ Geometry::Union(const Geometry* other) const
 
         if(nullptr != (coll = dynamic_cast<const GeometryCollection*>(this))) {
             for(size_t i = 0; i < ngeomsThis; ++i) {
-                v->push_back(coll->getGeometryN(i)->clone());
+                v->push_back(coll->getGeometryN(i)->clone().release());
             }
         }
         else {
-            v->push_back(this->clone());
+            v->push_back(this->clone().release());
         }
 
         if(nullptr != (coll = dynamic_cast<const GeometryCollection*>(other))) {
             for(size_t i = 0; i < ngeomsOther; ++i) {
-                v->push_back(coll->getGeometryN(i)->clone());
+                v->push_back(coll->getGeometryN(i)->clone().release());
             }
         }
         else {
-            v->push_back(other->clone());
+            v->push_back(other->clone().release());
         }
 
         out = _factory->buildGeometry(v);
@@ -653,7 +653,7 @@ Geometry::difference(const Geometry* other) const
         return getFactory()->createGeometryCollection();
     }
     if(other->isEmpty()) {
-        return clone();
+        return clone().release();
     }
 
     return BinaryOp(this, other, overlayOp(OverlayOp::opDIFFERENCE)).release();
@@ -664,10 +664,10 @@ Geometry::symDifference(const Geometry* other) const
 {
     // special case: if either input is empty ==> other input
     if(isEmpty()) {
-        return other->clone();
+        return other->clone().release();
     }
     if(other->isEmpty()) {
-        return clone();
+        return clone().release();
     }
 
     // if envelopes are disjoint return a MULTI geom or
@@ -685,20 +685,20 @@ Geometry::symDifference(const Geometry* other) const
 
         if(nullptr != (coll = dynamic_cast<const GeometryCollection*>(this))) {
             for(size_t i = 0; i < ngeomsThis; ++i) {
-                v->push_back(coll->getGeometryN(i)->clone());
+                v->push_back(coll->getGeometryN(i)->clone().release());
             }
         }
         else {
-            v->push_back(this->clone());
+            v->push_back(this->clone().release());
         }
 
         if(nullptr != (coll = dynamic_cast<const GeometryCollection*>(other))) {
             for(size_t i = 0; i < ngeomsOther; ++i) {
-                v->push_back(coll->getGeometryN(i)->clone());
+                v->push_back(coll->getGeometryN(i)->clone().release());
             }
         }
         else {
-            v->push_back(other->clone());
+            v->push_back(other->clone().release());
         }
 
         return _factory->buildGeometry(v);
diff --git a/src/geom/GeometryCollection.cpp b/src/geom/GeometryCollection.cpp
index a026cad..b3217a5 100644
--- a/src/geom/GeometryCollection.cpp
+++ b/src/geom/GeometryCollection.cpp
@@ -50,7 +50,7 @@ GeometryCollection::GeometryCollection(const GeometryCollection& gc)
 
     geometries = new vector<Geometry*>(ngeoms);
     for(size_t i = 0; i < ngeoms; ++i) {
-        (*geometries)[i] = (*gc.geometries)[i]->clone();
+        (*geometries)[i] = (*gc.geometries)[i]->clone().release();
     }
 }
 
@@ -374,7 +374,7 @@ GeometryCollection::getGeometryTypeId() const
     return GEOS_GEOMETRYCOLLECTION;
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 GeometryCollection::reverse() const
 {
     if(isEmpty()) {
@@ -387,10 +387,10 @@ GeometryCollection::reverse() const
                    geometries->end(),
                    reversed->begin(),
     [](const Geometry * g) {
-        return g->reverse();
+        return g->reverse().release();
     });
 
-    return getFactory()->createGeometryCollection(reversed);
+    return std::unique_ptr<Geometry>(getFactory()->createGeometryCollection(reversed));
 }
 
 } // namespace geos::geom
diff --git a/src/geom/GeometryFactory.cpp b/src/geom/GeometryFactory.cpp
index 47bc368..8877b7a 100644
--- a/src/geom/GeometryFactory.cpp
+++ b/src/geom/GeometryFactory.cpp
@@ -414,7 +414,7 @@ GeometryFactory::createGeometryCollection(const vector<Geometry*>& fromGeoms) co
 {
     vector<Geometry*>* newGeoms = new vector<Geometry*>(fromGeoms.size());
     for(size_t i = 0; i < fromGeoms.size(); i++) {
-        (*newGeoms)[i] = fromGeoms[i]->clone();
+        (*newGeoms)[i] = fromGeoms[i]->clone().release();
     }
     GeometryCollection* g = nullptr;
     try {
@@ -450,7 +450,7 @@ GeometryFactory::createMultiPolygon(const vector<Geometry*>& fromPolys) const
 {
     vector<Geometry*>* newGeoms = new vector<Geometry*>(fromPolys.size());
     for(size_t i = 0; i < fromPolys.size(); i++) {
-        (*newGeoms)[i] = fromPolys[i]->clone();
+        (*newGeoms)[i] = fromPolys[i]->clone().release();
     }
     MultiPolygon* g = nullptr;
     try {
@@ -511,7 +511,7 @@ GeometryFactory::createMultiPoint(const vector<Geometry*>& fromPoints) const
 {
     vector<Geometry*>* newGeoms = new vector<Geometry*>(fromPoints.size());
     for(size_t i = 0; i < fromPoints.size(); i++) {
-        (*newGeoms)[i] = fromPoints[i]->clone();
+        (*newGeoms)[i] = fromPoints[i]->clone().release();
     }
 
     MultiPoint* g = nullptr;
@@ -605,10 +605,10 @@ Polygon*
 GeometryFactory::createPolygon(const LinearRing& shell, const vector<Geometry*>& holes)
 const
 {
-    LinearRing* newRing = dynamic_cast<LinearRing*>(shell.clone());
+    LinearRing* newRing = dynamic_cast<LinearRing*>(shell.clone().release());
     vector<Geometry*>* newHoles = new vector<Geometry*>(holes.size());
     for(size_t i = 0; i < holes.size(); i++) {
-        (*newHoles)[i] = holes[i]->clone();
+        (*newHoles)[i] = holes[i]->clone().release();
     }
     Polygon* g = nullptr;
     try {
@@ -731,7 +731,7 @@ GeometryFactory::buildGeometry(const vector<Geometry*>& fromGeoms) const
     }
 
     if(geomsSize == 1) {
-        return fromGeoms[0]->clone();
+        return fromGeoms[0]->clone().release();
     }
 
     bool isHeterogeneous = false;
@@ -760,8 +760,8 @@ GeometryFactory::buildGeometry(const vector<Geometry*>& fromGeoms) const
     else if(type == GEOS_POINT) {
         return createMultiPoint(fromGeoms);
     }
-    geos::util::GEOSException("GeometryFactory::buildGeometry encountered an unknown geometry type!");
-    return fromGeoms[0]->clone();
+
+    throw geos::util::GEOSException("GeometryFactory::buildGeometry encountered an unknown geometry type!");
 }
 
 /*public*/
diff --git a/src/geom/LineString.cpp b/src/geom/LineString.cpp
index 6141728..7d5193f 100644
--- a/src/geom/LineString.cpp
+++ b/src/geom/LineString.cpp
@@ -54,7 +54,7 @@ LineString::LineString(const LineString& ls)
     //points=ls.points->clone();
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 LineString::reverse() const
 {
     if(isEmpty()) {
@@ -65,7 +65,7 @@ LineString::reverse() const
     auto seq = points->clone();
     CoordinateSequence::reverse(seq.get());
     assert(getFactory());
-    return getFactory()->createLineString(seq.release());
+    return std::unique_ptr<Geometry>(getFactory()->createLineString(seq.release()));
 }
 
 
diff --git a/src/geom/LinearRing.cpp b/src/geom/LinearRing.cpp
index c254a4d..df7d3ca 100644
--- a/src/geom/LinearRing.cpp
+++ b/src/geom/LinearRing.cpp
@@ -120,7 +120,7 @@ LinearRing::getGeometryTypeId() const
     return GEOS_LINEARRING;
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 LinearRing::reverse() const
 {
     if(isEmpty()) {
@@ -131,7 +131,7 @@ LinearRing::reverse() const
     auto seq = points->clone();
     CoordinateSequence::reverse(seq.get());
     assert(getFactory());
-    return getFactory()->createLinearRing(seq.release());
+    return std::unique_ptr<Geometry>(getFactory()->createLinearRing(seq.release()));
 }
 
 } // namespace geos::geom
diff --git a/src/geom/MultiLineString.cpp b/src/geom/MultiLineString.cpp
index 58def9a..ff7e583 100644
--- a/src/geom/MultiLineString.cpp
+++ b/src/geom/MultiLineString.cpp
@@ -113,7 +113,7 @@ MultiLineString::getGeometryTypeId() const
     return GEOS_MULTILINESTRING;
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 MultiLineString::reverse() const
 {
     if(isEmpty()) {
@@ -125,9 +125,9 @@ MultiLineString::reverse() const
     for(size_t i = 0; i < nLines; ++i) {
         LineString* iLS = dynamic_cast<LineString*>((*geometries)[i]);
         assert(iLS);
-        (*revLines)[nLines - 1 - i] = iLS->reverse();
+        (*revLines)[nLines - 1 - i] = iLS->reverse().release();
     }
-    return getFactory()->createMultiLineString(revLines);
+    return std::unique_ptr<Geometry>(getFactory()->createMultiLineString(revLines));
 }
 
 } // namespace geos::geom
diff --git a/src/geom/MultiPolygon.cpp b/src/geom/MultiPolygon.cpp
index 0e52aad..7bd2df8 100644
--- a/src/geom/MultiPolygon.cpp
+++ b/src/geom/MultiPolygon.cpp
@@ -84,7 +84,7 @@ MultiPolygon::getBoundary() const
             for(size_t j = 0, jn = rings->getNumGeometries();
                     j < jn; ++j) {
                 //allRings->push_back(new LineString(*(LineString*)rings->getGeometryN(j)));
-                allRings->push_back(rings->getGeometryN(j)->clone());
+                allRings->push_back(rings->getGeometryN(j)->clone().release());
             }
             delete g;
         }
@@ -110,7 +110,7 @@ MultiPolygon::getGeometryTypeId() const
     return GEOS_MULTIPOLYGON;
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 MultiPolygon::reverse() const
 {
     if(isEmpty()) {
@@ -123,10 +123,10 @@ MultiPolygon::reverse() const
                    geometries->end(),
                    reversed->begin(),
     [](const Geometry * g) {
-        return g->reverse();
+        return g->reverse().release();
     });
 
-    return getFactory()->createMultiPolygon(reversed);
+    return std::unique_ptr<Geometry>(getFactory()->createMultiPolygon(reversed));
 }
 
 } // namespace geos::geom
diff --git a/src/geom/Polygon.cpp b/src/geom/Polygon.cpp
index abf156f..b46fa95 100644
--- a/src/geom/Polygon.cpp
+++ b/src/geom/Polygon.cpp
@@ -494,24 +494,24 @@ Polygon::isRectangle() const
     return true;
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 Polygon::reverse() const
 {
     if(isEmpty()) {
         return clone();
     }
 
-    auto* exteriorRingReversed = dynamic_cast<LinearRing*>(shell->reverse());
+    auto* exteriorRingReversed = dynamic_cast<LinearRing*>(shell->reverse().release());
     auto* interiorRingsReversed = new std::vector<Geometry*> {holes->size()};
 
     std::transform(holes->begin(),
                    holes->end(),
                    interiorRingsReversed->begin(),
     [](const Geometry * g) {
-        return g->reverse();
+        return g->reverse().release();
     });
 
-    return getFactory()->createPolygon(exteriorRingReversed, interiorRingsReversed);
+    return std::unique_ptr<Geometry>(getFactory()->createPolygon(exteriorRingReversed, interiorRingsReversed));
 }
 
 } // namespace geos::geom
diff --git a/src/geom/util/CoordinateOperation.cpp b/src/geom/util/CoordinateOperation.cpp
index d2d85cd..5a50d30 100644
--- a/src/geom/util/CoordinateOperation.cpp
+++ b/src/geom/util/CoordinateOperation.cpp
@@ -49,7 +49,7 @@ CoordinateOperation::edit(const Geometry* geometry,
         return factory->createPoint(newCoords);
     }
 
-    return geometry->clone();
+    return geometry->clone().release();
 }
 
 
diff --git a/src/geomgraph/EdgeRing.cpp b/src/geomgraph/EdgeRing.cpp
index ec6b816..1b63505 100644
--- a/src/geomgraph/EdgeRing.cpp
+++ b/src/geomgraph/EdgeRing.cpp
@@ -166,7 +166,7 @@ EdgeRing::toPolygon(const GeometryFactory* p_geometryFactory)
     size_t nholes = holes.size();
     vector<Geometry*>* holeLR = new vector<Geometry*>(nholes);
     for(size_t i = 0; i < nholes; ++i) {
-        Geometry* hole = holes[i]->getLinearRing()->clone();
+        Geometry* hole = holes[i]->getLinearRing()->clone().release();
         (*holeLR)[i] = hole;
     }
 
diff --git a/src/linearref/ExtractLineByLocation.cpp b/src/linearref/ExtractLineByLocation.cpp
index 3ccff62..634c9a3 100644
--- a/src/linearref/ExtractLineByLocation.cpp
+++ b/src/linearref/ExtractLineByLocation.cpp
@@ -39,7 +39,7 @@ namespace geos {
 namespace linearref { // geos.linearref
 
 
-Geometry*
+std::unique_ptr<Geometry>
 ExtractLineByLocation::extract(const Geometry* line, const LinearLocation& start, const LinearLocation& end)
 {
     ExtractLineByLocation ls(line);
@@ -50,19 +50,18 @@ ExtractLineByLocation::ExtractLineByLocation(const Geometry* p_line) :
     line(p_line) {}
 
 
-Geometry*
+std::unique_ptr<Geometry>
 ExtractLineByLocation::extract(const LinearLocation& start, const LinearLocation& end)
 {
     if(end.compareTo(start) < 0) {
-        Geometry* backwards = computeLinear(end, start);
-        Geometry* forwards = reverse(backwards);
-        delete backwards;
+        auto backwards = computeLinear(end, start);
+        auto forwards = reverse(backwards.get());
         return forwards;
     }
     return computeLinear(start, end);
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 ExtractLineByLocation::reverse(const Geometry* linear)
 {
     const LineString* ls = dynamic_cast<const LineString*>(linear);
@@ -81,7 +80,7 @@ ExtractLineByLocation::reverse(const Geometry* linear)
     }
 }
 
-LineString*
+std::unique_ptr<LineString>
 ExtractLineByLocation::computeLine(const LinearLocation& start, const LinearLocation& end)
 {
     auto coordinates = line->getCoordinates();
@@ -130,10 +129,10 @@ ExtractLineByLocation::computeLine(const LinearLocation& start, const LinearLoca
         newCoordinateArray.add(newCoordinateArray[0]);
     }
 
-    return line->getFactory()->createLineString(newCoordinateArray);
+    return std::unique_ptr<LineString>(line->getFactory()->createLineString(newCoordinateArray));
 }
 
-Geometry*
+std::unique_ptr<Geometry>
 ExtractLineByLocation::computeLinear(const LinearLocation& start, const LinearLocation& end)
 {
     LinearGeometryBuilder builder(line->getFactory());
@@ -156,7 +155,7 @@ ExtractLineByLocation::computeLinear(const LinearLocation& start, const LinearLo
     if(! end.isVertex()) {
         builder.add(end.getCoordinate(line));
     }
-    return builder.getGeometry();
+    return std::unique_ptr<Geometry>(builder.getGeometry());
 }
 }
 }
diff --git a/src/linearref/LengthIndexedLine.cpp b/src/linearref/LengthIndexedLine.cpp
index ec2f91a..4a262e3 100644
--- a/src/linearref/LengthIndexedLine.cpp
+++ b/src/linearref/LengthIndexedLine.cpp
@@ -54,7 +54,7 @@ LengthIndexedLine::extractPoint(double index, double offsetDistance) const
 }
 
 
-Geometry*
+std::unique_ptr<Geometry>
 LengthIndexedLine::extractLine(double startIndex, double endIndex) const
 {
     const LocationIndexedLine lil(linearGeom);
diff --git a/src/operation/buffer/BufferBuilder.cpp b/src/operation/buffer/BufferBuilder.cpp
index b6e6267..1f2c653 100644
--- a/src/operation/buffer/BufferBuilder.cpp
+++ b/src/operation/buffer/BufferBuilder.cpp
@@ -139,7 +139,7 @@ BufferBuilder::bufferLineSingleSided(const Geometry* g, double distance,
 
     // Nothing to do for a distance of zero
     if(distance == 0) {
-        return g->clone();
+        return g->clone().release();
     }
 
     // Get geometry factory and precision model.
diff --git a/src/operation/intersection/RectangleIntersection.cpp b/src/operation/intersection/RectangleIntersection.cpp
index bb16564..a297b9e 100644
--- a/src/operation/intersection/RectangleIntersection.cpp
+++ b/src/operation/intersection/RectangleIntersection.cpp
@@ -125,7 +125,7 @@ RectangleIntersection::clip_point(const geom::Point* g,
     double y = g->getY();
 
     if(rect.position(x, y) == Rectangle::Inside) {
-        parts.add(dynamic_cast<geom::Point*>(g->clone()));
+        parts.add(dynamic_cast<geom::Point*>(g->clone().release()));
     }
 }
 
@@ -388,7 +388,7 @@ RectangleIntersection::clip_polygon_to_linestrings(const geom::Polygon* g,
     // If everything was in, just clone the original
 
     if(clip_linestring_parts(g->getExteriorRing(), parts, rect)) {
-        toParts.add(dynamic_cast<geom::Polygon*>(g->clone()));
+        toParts.add(dynamic_cast<geom::Polygon*>(g->clone().release()));
         return;
     }
 
@@ -421,7 +421,7 @@ RectangleIntersection::clip_polygon_to_linestrings(const geom::Polygon* g,
     for(size_t i = 0, n = g->getNumInteriorRing(); i < n; ++i) {
         if(clip_linestring_parts(g->getInteriorRingN(i), parts, rect)) {
             // clones
-            LinearRing* hole = dynamic_cast<LinearRing*>(g->getInteriorRingN(i)->clone());
+            LinearRing* hole = dynamic_cast<LinearRing*>(g->getInteriorRingN(i)->clone().release());
             // becomes exterior
             Polygon* poly = _gf->createPolygon(hole, nullptr);
             toParts.add(poly);
@@ -454,7 +454,7 @@ RectangleIntersection::clip_polygon_to_polygons(const geom::Polygon* g,
 
     const LineString* shell = g->getExteriorRing();
     if(clip_linestring_parts(shell, parts, rect)) {
-        toParts.add(dynamic_cast<geom::Polygon*>(g->clone()));
+        toParts.add(dynamic_cast<geom::Polygon*>(g->clone().release()));
         return;
     }
 
@@ -493,7 +493,7 @@ RectangleIntersection::clip_polygon_to_polygons(const geom::Polygon* g,
         const LineString* hole = g->getInteriorRingN(i);
         if(clip_linestring_parts(hole, holeparts, rect)) {
             // becomes exterior
-            LinearRing* cloned = dynamic_cast<LinearRing*>(hole->clone());
+            LinearRing* cloned = dynamic_cast<LinearRing*>(hole->clone().release());
             Polygon* poly = _gf->createPolygon(cloned, nullptr);
             parts.add(poly);
         }
@@ -559,7 +559,7 @@ RectangleIntersection::clip_linestring(const geom::LineString* g,
     // If everything was in, just clone the original
 
     if(clip_linestring_parts(g, parts, rect)) {
-        parts.add(dynamic_cast<geom::LineString*>(g->clone()));
+        parts.add(dynamic_cast<geom::LineString*>(g->clone().release()));
     }
 
 }
diff --git a/src/operation/intersection/RectangleIntersectionBuilder.cpp b/src/operation/intersection/RectangleIntersectionBuilder.cpp
index a95488f..0d0c105 100644
--- a/src/operation/intersection/RectangleIntersectionBuilder.cpp
+++ b/src/operation/intersection/RectangleIntersectionBuilder.cpp
@@ -483,7 +483,7 @@ RectangleIntersectionBuilder::reconnectPolygons(const Rectangle& rect)
         const geom::LineString* hole = poly->getExteriorRing();
 
         if(exterior.size() == 1) {
-            exterior.front().second->push_back(hole->clone());
+            exterior.front().second->push_back(hole->clone().release());
         }
         else {
             using geos::algorithm::PointLocation;
@@ -494,7 +494,7 @@ RectangleIntersectionBuilder::reconnectPolygons(const Rectangle& rect)
                 const CoordinateSequence* shell_cs = p.first->getCoordinatesRO();
                 if(PointLocation::isInRing(c, shell_cs)) {
                     // add hole to shell
-                    p.second->push_back(hole->clone());
+                    p.second->push_back(hole->clone().release());
                     break;
                 }
             }
@@ -522,7 +522,7 @@ RectangleIntersectionBuilder::reverseLines()
     std::list<geom::LineString*> new_lines;
     for(std::list<geom::LineString*>::reverse_iterator i = lines.rbegin(), e = lines.rend(); i != e; ++i) {
         LineString* ol = *i;
-        new_lines.push_back(dynamic_cast<LineString*>(ol->reverse()));
+        new_lines.push_back(dynamic_cast<LineString*>(ol->reverse().release()));
         delete ol;
     }
     lines = new_lines;
diff --git a/src/operation/linemerge/LineSequencer.cpp b/src/operation/linemerge/LineSequencer.cpp
index 1c441f2..e5099a7 100644
--- a/src/operation/linemerge/LineSequencer.cpp
+++ b/src/operation/linemerge/LineSequencer.cpp
@@ -218,7 +218,7 @@ LineSequencer::buildSequencedGeometry(const Sequences& sequences)
                 lineToAdd = reverse(line);
             }
             else {
-                Geometry* lineClone = line->clone();
+                Geometry* lineClone = line->clone().release();
                 lineToAdd = dynamic_cast<LineString*>(lineClone);
                 assert(lineToAdd);
             }
diff --git a/src/operation/overlay/snap/SnapOverlayOp.cpp b/src/operation/overlay/snap/SnapOverlayOp.cpp
index 8b36380..0d1bf25 100644
--- a/src/operation/overlay/snap/SnapOverlayOp.cpp
+++ b/src/operation/overlay/snap/SnapOverlayOp.cpp
@@ -91,8 +91,8 @@ SnapOverlayOp::removeCommonBits(const geom::Geometry& p_geom0,
     cbr->add(&p_geom0);
     cbr->add(&p_geom1);
 
-    remGeom.first.reset(cbr->removeCommonBits(p_geom0.clone()));
-    remGeom.second.reset(cbr->removeCommonBits(p_geom1.clone()));
+    remGeom.first.reset(cbr->removeCommonBits(p_geom0.clone().release()));
+    remGeom.second.reset(cbr->removeCommonBits(p_geom1.clone().release()));
 }
 
 /*private*/
diff --git a/src/operation/overlay/validate/FuzzyPointLocator.cpp b/src/operation/overlay/validate/FuzzyPointLocator.cpp
index 6422ff4..649e2ba 100644
--- a/src/operation/overlay/validate/FuzzyPointLocator.cpp
+++ b/src/operation/overlay/validate/FuzzyPointLocator.cpp
@@ -104,7 +104,7 @@ FuzzyPointLocator::getLineWork(const geom::Geometry& geom)
                 lineGeom = gComp->getBoundary();
             }
             else {
-                lineGeom = gComp->clone();
+                lineGeom = gComp->clone().release();
             }
             lineGeoms->push_back(lineGeom);
         }
diff --git a/src/operation/polygonize/BuildArea.cpp b/src/operation/polygonize/BuildArea.cpp
index ec39757..99a2c28 100644
--- a/src/operation/polygonize/BuildArea.cpp
+++ b/src/operation/polygonize/BuildArea.cpp
@@ -122,7 +122,7 @@ static std::unique_ptr<geom::MultiPolygon> collectFacesWithEvenAncestors(
         if( face->countParents() % 2 ) {
             continue; /* we skip odd parents geoms */
         }
-        geoms->push_back(face->poly->clone());
+        geoms->push_back(face->poly->clone().release());
     }
     return std::unique_ptr<geom::MultiPolygon>(
         GeometryFactory::create()->createMultiPolygon(geoms));
diff --git a/src/operation/union/CascadedPolygonUnion.cpp b/src/operation/union/CascadedPolygonUnion.cpp
index a456095..6134684 100644
--- a/src/operation/union/CascadedPolygonUnion.cpp
+++ b/src/operation/union/CascadedPolygonUnion.cpp
@@ -225,10 +225,10 @@ CascadedPolygonUnion::unionSafe(geom::Geometry* g0, geom::Geometry* g1)
     }
 
     if(g0 == nullptr) {
-        return g1->clone();
+        return g1->clone().release();
     }
     if(g1 == nullptr) {
-        return g0->clone();
+        return g0->clone().release();
     }
 
     return unionOptimized(g0, g1);
@@ -411,7 +411,7 @@ CascadedPolygonUnion::restrictToPolygons(std::unique_ptr<geom::Geometry> g)
     Polygon::ConstVect::size_type n = polygons.size();
     GeomVect* newpolys = new GeomVect(n);
     for(Polygon::ConstVect::size_type i = 0; i < n; ++i) {
-        (*newpolys)[i] = polygons[i]->clone();
+        (*newpolys)[i] = polygons[i]->clone().release();
     }
     return unique_ptr<Geometry>(
                g->getFactory()->createMultiPolygon(newpolys)
diff --git a/src/operation/union/CascadedUnion.cpp b/src/operation/union/CascadedUnion.cpp
index e13d0c4..960367c 100644
--- a/src/operation/union/CascadedUnion.cpp
+++ b/src/operation/union/CascadedUnion.cpp
@@ -136,10 +136,10 @@ CascadedUnion::unionSafe(geom::Geometry* g0, geom::Geometry* g1)
     }
 
     if(g0 == nullptr) {
-        return g1->clone();
+        return g1->clone().release();
     }
     if(g1 == nullptr) {
-        return g0->clone();
+        return g0->clone().release();
     }
 
     return unionOptimized(g0, g1);
diff --git a/src/precision/CommonBitsOp.cpp b/src/precision/CommonBitsOp.cpp
index 5aa5650..f616de4 100644
--- a/src/precision/CommonBitsOp.cpp
+++ b/src/precision/CommonBitsOp.cpp
@@ -140,7 +140,7 @@ CommonBitsOp::removeCommonBits(const Geometry* geom0)
     cerr << "CommonBitsRemover bits: " << commonCoord.x << ", " << commonCoord.y << endl;
 #endif
 
-    Geometry* geom = cbr->removeCommonBits(geom0->clone());
+    Geometry* geom = cbr->removeCommonBits(geom0->clone().release());
     return geom;
 }
 
@@ -163,8 +163,8 @@ CommonBitsOp::removeCommonBits(
     cerr << "CommonBitsRemover bits: " << commonCoord.x << ", " << commonCoord.y << endl;
 #endif
 
-    rgeom0.reset(cbr->removeCommonBits(geom0->clone()));
-    rgeom1.reset(cbr->removeCommonBits(geom1->clone()));
+    rgeom0.reset(cbr->removeCommonBits(geom0->clone().release()));
+    rgeom1.reset(cbr->removeCommonBits(geom1->clone().release()));
 
 }
 
diff --git a/src/triangulate/VoronoiDiagramBuilder.cpp b/src/triangulate/VoronoiDiagramBuilder.cpp
index bc14370..e2d8c76 100644
--- a/src/triangulate/VoronoiDiagramBuilder.cpp
+++ b/src/triangulate/VoronoiDiagramBuilder.cpp
@@ -134,7 +134,7 @@ VoronoiDiagramBuilder::clipGeometryCollection(const geom::GeometryCollection& ge
         std::unique_ptr<Geometry> result;
         // don't clip unless necessary
         if(clipEnv.contains(g->getEnvelopeInternal())) {
-            result.reset(g->clone());
+            result = g->clone();
             // TODO: check if userData is correctly cloned here?
         }
         else if(clipEnv.intersects(g->getEnvelopeInternal())) {
diff --git a/tests/unit/geom/Geometry/normalize.cpp b/tests/unit/geom/Geometry/normalize.cpp
index 599baa7..7f5ea18 100644
--- a/tests/unit/geom/Geometry/normalize.cpp
+++ b/tests/unit/geom/Geometry/normalize.cpp
@@ -50,7 +50,7 @@ struct test_geometry_normalize_data {
         ensure(eq);
 
         // Clone and re-normalize, check it doesn't change anymore
-        ge.reset(g2->clone());
+        ge = g2->clone();
         g2->normalize();
         ensure(g2->equalsExact(ge.get()));
     }
diff --git a/tests/unit/geom/LineStringTest.cpp b/tests/unit/geom/LineStringTest.cpp
index ed4bfd8..56abf10 100644
--- a/tests/unit/geom/LineStringTest.cpp
+++ b/tests/unit/geom/LineStringTest.cpp
@@ -188,7 +188,7 @@ void object::test<4>
     LineStringAutoPtr examplar(factory_->createLineString(pseq));
 
     // Create copy
-    LineStringAutoPtr copy(dynamic_cast<geos::geom::LineString*>(examplar->clone()));
+    LineStringAutoPtr copy(dynamic_cast<geos::geom::LineString*>(examplar->clone().release()));
 
     ensure(nullptr != copy.get());
 
diff --git a/tests/unit/geom/MultiPointTest.cpp b/tests/unit/geom/MultiPointTest.cpp
index f6a9751..2fb4fc8 100644
--- a/tests/unit/geom/MultiPointTest.cpp
+++ b/tests/unit/geom/MultiPointTest.cpp
@@ -89,7 +89,7 @@ void object::test<2>
 ()
 {
     const size_t size0 = 0;
-    MultiPointAutoPtr copy(dynamic_cast<geos::geom::MultiPoint*>(empty_mp_->clone()));
+    MultiPointAutoPtr copy(dynamic_cast<geos::geom::MultiPoint*>(empty_mp_->clone().release()));
     ensure(nullptr != copy.get());
 
     ensure(copy->isEmpty());
diff --git a/tests/unit/geom/PolygonTest.cpp b/tests/unit/geom/PolygonTest.cpp
index adfc363..2436ee3 100644
--- a/tests/unit/geom/PolygonTest.cpp
+++ b/tests/unit/geom/PolygonTest.cpp
@@ -107,7 +107,7 @@ void object::test<1>
         ensure(ring.isSimple());
 
         // Exterior (clone is required here because Polygon takes ownership)
-        GeometryPtr geo = ring.clone();
+        geos::geom::Geometry* geo = ring.clone().release();
         LinearRingPtr exterior = dynamic_cast<LinearRingPtr>(geo);
 
         // Create non-empty Polygon
@@ -413,7 +413,7 @@ void object::test<27>
 {
     ensure(poly_ != nullptr);
 
-    GeometryPtr geo = poly_->clone();
+    GeometryPtr geo = poly_->clone().release();
     ensure(geo != nullptr);
     ensure(geo->equals(poly_));
 
diff --git a/tests/unit/linearref/LengthIndexedLineTest.cpp b/tests/unit/linearref/LengthIndexedLineTest.cpp
index 61fce59..875f567 100644
--- a/tests/unit/linearref/LengthIndexedLineTest.cpp
+++ b/tests/unit/linearref/LengthIndexedLineTest.cpp
@@ -138,12 +138,12 @@ struct test_lengthindexedline_data {
     }
 
 
-    Geometry*
+    std::unique_ptr<Geometry>
     indicesOfThenExtract(Geometry* linearGeom, Geometry* subLine)
     {
         LengthIndexedLine indexedLine(linearGeom);
         double* loc = indexedLine.indicesOf(subLine);
-        Geometry* result = indexedLine.extractLine(loc[0], loc[1]);
+        auto result = indexedLine.extractLine(loc[0], loc[1]);
         delete [] loc;
         return result;
     }
diff --git a/tests/unit/operation/union/CascadedPolygonUnionTest.cpp b/tests/unit/operation/union/CascadedPolygonUnionTest.cpp
index e6e887d..6f5c1d7 100644
--- a/tests/unit/operation/union/CascadedPolygonUnionTest.cpp
+++ b/tests/unit/operation/union/CascadedPolygonUnionTest.cpp
@@ -45,16 +45,14 @@ geos::geom::Geometry*
 unionIterated(
     std::vector<geos::geom::Polygon*>* geoms)
 {
-    typedef std::vector<geos::geom::Polygon*>::iterator iterator;
-
     std::unique_ptr<geos::geom::Geometry> unionAll;
-    iterator end = geoms->end();
-    for(iterator i = geoms->begin(); i != end; ++i) {
-        if(!unionAll.get()) {
-            unionAll.reset((*i)->clone());
+
+    for(const auto& p : *geoms) {
+        if(unionAll == nullptr) {
+            unionAll = p->clone();
         }
         else {
-            unionAll.reset(unionAll->Union(*i));
+            unionAll.reset(unionAll->Union(p));
         }
     }
     return unionAll.release();

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

Summary of changes:
 capi/geos_ts_c.cpp                                 | 48 ++++++--------
 doc/example.cpp                                    | 20 +++---
 include/geos/algorithm/ConvexHull.h                |  4 +-
 include/geos/algorithm/MinimumBoundingCircle.h     |  2 +-
 include/geos/geom/BinaryOp.h                       | 13 ++--
 include/geos/geom/Geometry.h                       | 53 +++++++---------
 include/geos/geom/GeometryCollection.h             |  8 +--
 include/geos/geom/LineString.h                     | 10 +--
 include/geos/geom/LinearRing.h                     |  6 +-
 include/geos/geom/MultiLineString.h                |  6 +-
 include/geos/geom/MultiLineString.inl              |  4 +-
 include/geos/geom/MultiPoint.h                     |  8 +--
 include/geos/geom/MultiPolygon.h                   |  6 +-
 include/geos/geom/MultiPolygon.inl                 |  4 +-
 include/geos/geom/Point.h                          |  8 +--
 include/geos/geom/Polygon.h                        | 10 +--
 include/geos/geom/util/Densifier.h                 |  2 +-
 include/geos/linearref/ExtractLineByLocation.h     | 10 +--
 include/geos/linearref/LengthIndexedLine.h         |  2 +-
 include/geos/linearref/LocationIndexedLine.h       |  2 +-
 include/geos/operation/relate/RelateComputer.h     |  4 +-
 include/geos/operation/relate/RelateOp.h           |  8 +--
 include/geos/precision/CommonBitsOp.h              | 16 ++---
 include/geos/precision/CommonBitsRemover.h         |  2 +-
 include/geos/precision/EnhancedPrecisionOp.h       | 18 ++----
 src/algorithm/ConvexHull.cpp                       | 15 ++---
 src/algorithm/MinimumBoundingCircle.cpp            |  6 +-
 src/algorithm/MinimumDiameter.cpp                  |  5 +-
 src/geom/Geometry.cpp                              | 74 ++++++++++------------
 src/geom/GeometryCollection.cpp                    | 10 +--
 src/geom/GeometryFactory.cpp                       | 16 ++---
 src/geom/LineString.cpp                            | 12 ++--
 src/geom/LinearRing.cpp                            |  4 +-
 src/geom/MultiLineString.cpp                       | 15 ++---
 src/geom/MultiPoint.cpp                            |  4 +-
 src/geom/MultiPolygon.cpp                          | 26 ++++----
 src/geom/Point.cpp                                 |  4 +-
 src/geom/Polygon.cpp                               | 18 +++---
 src/geom/util/CoordinateOperation.cpp              |  2 +-
 src/geom/util/Densifier.cpp                        |  2 +-
 src/geomgraph/EdgeRing.cpp                         |  2 +-
 src/linearref/ExtractLineByLocation.cpp            | 19 +++---
 src/linearref/LengthIndexedLine.cpp                |  2 +-
 src/operation/buffer/BufferBuilder.cpp             |  2 +-
 .../intersection/RectangleIntersection.cpp         | 12 ++--
 .../intersection/RectangleIntersectionBuilder.cpp  |  6 +-
 src/operation/linemerge/LineSequencer.cpp          |  2 +-
 src/operation/overlay/snap/GeometrySnapper.cpp     |  2 +-
 src/operation/overlay/snap/SnapOverlayOp.cpp       |  6 +-
 .../overlay/validate/FuzzyPointLocator.cpp         |  6 +-
 src/operation/polygonize/BuildArea.cpp             |  4 +-
 src/operation/relate/RelateComputer.cpp            |  6 +-
 src/operation/relate/RelateOp.cpp                  |  6 +-
 src/operation/union/CascadedPolygonUnion.cpp       |  6 +-
 src/operation/union/CascadedUnion.cpp              |  6 +-
 src/operation/union/UnaryUnionOp.cpp               |  2 +-
 src/operation/valid/MakeValid.cpp                  | 12 ++--
 src/precision/CommonBitsOp.cpp                     | 28 ++++----
 src/precision/CommonBitsRemover.cpp                |  6 +-
 src/precision/EnhancedPrecisionOp.cpp              | 35 +++++-----
 src/triangulate/VoronoiDiagramBuilder.cpp          |  4 +-
 tests/unit/algorithm/ConvexHullTest.cpp            | 20 ++----
 tests/unit/geom/Geometry/normalize.cpp             |  2 +-
 tests/unit/geom/GeometryFactoryTest.cpp            | 40 +++---------
 tests/unit/geom/LineStringTest.cpp                 | 34 +++-------
 tests/unit/geom/LinearRingTest.cpp                 | 24 ++-----
 tests/unit/geom/MultiPointTest.cpp                 | 26 ++------
 tests/unit/geom/PointTest.cpp                      | 18 ++----
 tests/unit/geom/PolygonTest.cpp                    | 36 +++--------
 tests/unit/linearref/LengthIndexedLineTest.cpp     |  4 +-
 .../operation/union/CascadedPolygonUnionTest.cpp   | 16 ++---
 tests/xmltester/XMLTester.cpp                      |  2 +-
 72 files changed, 379 insertions(+), 504 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list