[geos-commits] [SCM] GEOS branch master updated. 75c286d5b65caf47ffb46e37707568bf4f9cd387

git at osgeo.org git at osgeo.org
Wed May 22 17:03:52 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  75c286d5b65caf47ffb46e37707568bf4f9cd387 (commit)
      from  1fb11b298d4890afb6a86cdf3325b1272a5def1c (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 75c286d5b65caf47ffb46e37707568bf4f9cd387
Author: Daniel Baston <dbaston at gmail.com>
Date:   Tue May 21 17:39:40 2019 -0400

    Pull removeRepeatedPoints out of CoordinateSequence
    
    This refactoring supports the goal of a slimmed-down CoordinateSequence
    interface against which it will be easier to develop alternative
    implementations.

diff --git a/include/geos/geom/CoordinateArraySequence.h b/include/geos/geom/CoordinateArraySequence.h
index 3834f93..9d8fa18 100644
--- a/include/geos/geom/CoordinateArraySequence.h
+++ b/include/geos/geom/CoordinateArraySequence.h
@@ -128,8 +128,6 @@ public:
 
     void apply_ro(CoordinateFilter* filter) const override;
 
-    CoordinateSequence& removeRepeatedPoints() override;
-
 private:
     std::vector<Coordinate>* vect;
     mutable std::size_t dimension;
diff --git a/include/geos/geom/CoordinateSequence.h b/include/geos/geom/CoordinateSequence.h
index 54654d8..f6fe861 100644
--- a/include/geos/geom/CoordinateSequence.h
+++ b/include/geos/geom/CoordinateSequence.h
@@ -81,7 +81,6 @@ public:
      * Whether or not the Coordinate returned is the actual underlying
      * Coordinate or merely a copy depends on the implementation.
      */
-    //virtual const Coordinate& getCoordinate(int i) const=0;
     virtual const Coordinate& getAt(std::size_t i) const = 0;
 
     /// Return last Coordinate in the sequence
@@ -113,7 +112,6 @@ public:
      * Returns the number of Coordinates (actual or otherwise, as
      * this implementation may not store its data in Coordinate objects).
      */
-    //virtual int size() const=0;
     virtual std::size_t getSize() const = 0;
 
     size_t
@@ -133,9 +131,9 @@ public:
      *
      * This method is a port of the toCoordinateArray() method of JTS.
      * It is not much used as memory management requires us to
-     * know wheter we should or not delete the returned object
+     * know whether we should or not delete the returned object
      * in a consistent way. Our options are: use shared_ptr<Coordinate>
-     * or always keep ownerhips of an eventual newly created vector.
+     * or always keep ownership of an eventual newly created vector.
      * We opted for the second, so the returned object is a const, to
      * also ensure that returning an internal pointer doesn't make
      * the object mutable.
@@ -159,9 +157,6 @@ public:
      */
     void add(const std::vector<Coordinate>* vc, bool allowRepeated);
 
-    /* This is here for backward compatibility.. */
-    //void add(CoordinateSequence *cl,bool allowRepeated,bool direction);
-
     /** \brief
      *  Add an array of coordinates
      *
@@ -205,12 +200,6 @@ public:
     /// Add a Coordinate to the list
     virtual	void add(const Coordinate& c) = 0;
 
-    // Get number of coordinates
-    //virtual int getSize() const=0;
-
-    /// Get a reference to Coordinate at position pos
-    //virtual	const Coordinate& getAt(std::size_t pos) const=0;
-
     /// Copy Coordinate c to position pos
     virtual	void setAt(const Coordinate& c, std::size_t pos) = 0;
 
@@ -229,24 +218,6 @@ public:
     /// Returns lower-left Coordinate in list
     const Coordinate* minCoordinate() const;
 
-
-    /// \brief
-    /// Returns a new CoordinateSequence being a copy of the input
-    /// with any consecutive equal Coordinate removed.
-    ///
-    /// Equality test is 2D based
-    ///
-    /// Ownership of returned object goes to the caller.
-    ///
-    static CoordinateSequence* removeRepeatedPoints(
-        const CoordinateSequence* cl);
-
-    /// Remove consecutive equal Coordinates from the sequence
-    //
-    /// Equality test is 2D based. Returns a reference to self.
-    ///
-    virtual CoordinateSequence& removeRepeatedPoints() = 0;
-
     /** \brief
      *  Returns true if given CoordinateSequence contains
      *  any two consecutive Coordinate
diff --git a/include/geos/operation/valid/Makefile.am b/include/geos/operation/valid/Makefile.am
index 8d62486..f608323 100644
--- a/include/geos/operation/valid/Makefile.am
+++ b/include/geos/operation/valid/Makefile.am
@@ -13,6 +13,7 @@ geos_HEADERS = \
     IsValidOp.h                 \
     MakeValid.h                 \
     QuadtreeNestedRingTester.h  \
+    RepeatedPointRemover.h      \
     RepeatedPointTester.h       \
     SimpleNestedRingTester.h    \
     SweeplineNestedRingTester.h \
diff --git a/include/geos/operation/valid/RepeatedPointRemover.h b/include/geos/operation/valid/RepeatedPointRemover.h
new file mode 100644
index 0000000..e419d95
--- /dev/null
+++ b/include/geos/operation/valid/RepeatedPointRemover.h
@@ -0,0 +1,41 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2019 Daniel Baston <dbaston at gmail.com>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************/
+
+#ifndef GEOS_OP_VALID_REPEATEDPOINTREMOVER_H
+#define GEOS_OP_VALID_REPEATEDPOINTREMOVER_H
+
+#include <geos/geom/CoordinateSequence.h>
+
+namespace geos {
+namespace operation {
+namespace valid {
+    class RepeatedPointRemover {
+
+    /// \brief
+    /// Returns a new CoordinateSequence being a copy of the input
+    /// with any consecutive equal Coordinate removed.
+    ///
+    /// Equality test is 2D based
+    ///
+    /// Ownership of returned object goes to the caller.
+    /// \param seq
+    /// \return
+    public:
+        static std::unique_ptr<geom::CoordinateSequence> removeRepeatedPoints(const geom::CoordinateSequence* seq);
+    };
+}
+}
+}
+
+#endif
diff --git a/include/geos/triangulate/DelaunayTriangulationBuilder.h b/include/geos/triangulate/DelaunayTriangulationBuilder.h
index 9d9fda3..aaedfc1 100644
--- a/include/geos/triangulate/DelaunayTriangulationBuilder.h
+++ b/include/geos/triangulate/DelaunayTriangulationBuilder.h
@@ -20,11 +20,12 @@
 #define GEOS_TRIANGULATE_DELAUNAYTRIANGULATIONBUILDER_H
 
 #include <geos/triangulate/IncrementalDelaunayTriangulator.h>
+#include <geos/geom/CoordinateSequence.h>
 
+#include <memory>
 
 namespace geos {
 namespace geom {
-class CoordinateSequence;
 class Geometry;
 class MultiLineString;
 class GeometryCollection;
@@ -58,9 +59,7 @@ public:
      * @param geom the geometry to extract from
      * @return a List of the unique Coordinates. Caller takes ownership of the returned object.
      */
-    static geom::CoordinateSequence* extractUniqueCoordinates(const geom::Geometry& geom);
-
-    static void unique(geom::CoordinateSequence& coords);
+    static std::unique_ptr<geom::CoordinateSequence> extractUniqueCoordinates(const geom::Geometry& geom);
 
     /**
      * Converts all {@link Coordinate}s in a collection to {@link Vertex}es.
@@ -69,8 +68,15 @@ public:
      */
     static IncrementalDelaunayTriangulator::VertexList* toVertices(const geom::CoordinateSequence& coords);
 
+    /**
+     * Returns a CoordinateSequence containing only the unique coordinates of its input.
+     * @param seq a coordinateSequence
+     * @return a sorted CoordinateSequence with the unique points of seq.
+     */
+    static std::unique_ptr<geom::CoordinateSequence> unique(const geom::CoordinateSequence* seq);
+
 private:
-    geom::CoordinateSequence* siteCoords;
+    std::unique_ptr<geom::CoordinateSequence> siteCoords;
     double tolerance;
     quadedge::QuadEdgeSubdivision* subdiv;
 
diff --git a/src/geom/CoordinateArraySequence.cpp b/src/geom/CoordinateArraySequence.cpp
index 4b529f8..e954d74 100644
--- a/src/geom/CoordinateArraySequence.cpp
+++ b/src/geom/CoordinateArraySequence.cpp
@@ -281,17 +281,5 @@ CoordinateArraySequence::apply_ro(CoordinateFilter* filter) const
     }
 }
 
-CoordinateSequence&
-CoordinateArraySequence::removeRepeatedPoints()
-{
-    // We use == operator, which is 2D only
-    vector<Coordinate>::iterator new_end = \
-                                           std::unique(vect->begin(), vect->end());
-
-    vect->erase(new_end, vect->end());
-
-    return *this;
-}
-
 } // namespace geos::geom
 } //namespace geos
diff --git a/src/geom/CoordinateSequence.cpp b/src/geom/CoordinateSequence.cpp
index 5c61610..38bb77c 100644
--- a/src/geom/CoordinateSequence.cpp
+++ b/src/geom/CoordinateSequence.cpp
@@ -248,25 +248,25 @@ CoordinateSequence::add(const CoordinateSequence* cl,
 
 
 /*public static*/
-CoordinateSequence*
-CoordinateSequence::removeRepeatedPoints(const CoordinateSequence* cl)
-{
-#if PROFILE
-    static Profile* prof = profiler->get("CoordinateSequence::removeRepeatedPoints()");
-    prof->start();
-#endif
-    const vector<Coordinate>* v = cl->toVector();
-
-    vector<Coordinate>* nv = new vector<Coordinate>;
-    nv->reserve(v->size());
-    unique_copy(v->begin(), v->end(), back_inserter(*nv));
-    CoordinateSequence* ret = CoordinateArraySequenceFactory::instance()->create(nv);
-
-#if PROFILE
-    prof->stop();
-#endif
-    return ret;
-}
+//CoordinateSequence*
+//CoordinateSequence::removeRepeatedPoints(const CoordinateSequence* cl)
+//{
+//#if PROFILE
+//    static Profile* prof = profiler->get("CoordinateSequence::removeRepeatedPoints()");
+//    prof->start();
+//#endif
+//    const vector<Coordinate>* v = cl->toVector();
+//
+//    vector<Coordinate>* nv = new vector<Coordinate>;
+//    nv->reserve(v->size());
+//    unique_copy(v->begin(), v->end(), back_inserter(*nv));
+//    CoordinateSequence* ret = CoordinateArraySequenceFactory::instance()->create(nv);
+//
+//#if PROFILE
+//    prof->stop();
+//#endif
+//    return ret;
+//}
 
 void
 CoordinateSequence::expandEnvelope(Envelope& env) const
diff --git a/src/geomgraph/GeometryGraph.cpp b/src/geomgraph/GeometryGraph.cpp
index c816520..d18f47d 100644
--- a/src/geomgraph/GeometryGraph.cpp
+++ b/src/geomgraph/GeometryGraph.cpp
@@ -47,6 +47,8 @@
 #include <geos/geom/GeometryCollection.h>
 #include <geos/util/Interrupt.h>
 
+#include <geos/operation/valid/RepeatedPointRemover.h>
+
 #include <geos/inline.h>
 
 #include <vector>
@@ -244,11 +246,10 @@ GeometryGraph::addPolygonRing(const LinearRing* lr, int cwLeft, int cwRight)
 
     const CoordinateSequence* lrcl = lr->getCoordinatesRO();
 
-    CoordinateSequence* coord = CoordinateSequence::removeRepeatedPoints(lrcl);
+    auto coord = geos::operation::valid::RepeatedPointRemover::removeRepeatedPoints(lrcl);
     if(coord->getSize() < 4) {
         hasTooFewPointsVar = true;
         invalidPoint = coord->getAt(0); // its now a Coordinate
-        delete coord;
         return;
     }
     int left = cwLeft;
@@ -259,21 +260,16 @@ GeometryGraph::addPolygonRing(const LinearRing* lr, int cwLeft, int cwRight)
      * IllegalArgumentException if degenerate ring does
      * not contain 3 distinct points.
      */
-    try {
-        if(Orientation::isCCW(coord)) {
-            left = cwRight;
-            right = cwLeft;
-        }
-    }
-    catch(...) {
-        delete coord;
-        throw;
+    if(Orientation::isCCW(coord.get())) {
+        left = cwRight;
+        right = cwLeft;
     }
 
-    Edge* e = new Edge(coord, Label(argIndex, Location::BOUNDARY, left, right));
+    auto coordRaw = coord.release();
+    Edge* e = new Edge(coordRaw, Label(argIndex, Location::BOUNDARY, left, right));
     lineEdgeMap[lr] = e;
     insertEdge(e);
-    insertPoint(argIndex, coord->getAt(0), Location::BOUNDARY);
+    insertPoint(argIndex, coordRaw->getAt(0), Location::BOUNDARY);
 }
 
 void
@@ -300,15 +296,15 @@ GeometryGraph::addPolygon(const Polygon* p)
 void
 GeometryGraph::addLineString(const LineString* line)
 {
-    CoordinateSequence* coord = CoordinateSequence::removeRepeatedPoints(line->getCoordinatesRO());
+    auto coord = operation::valid::RepeatedPointRemover::removeRepeatedPoints(line->getCoordinatesRO());
     if(coord->getSize() < 2) {
         hasTooFewPointsVar = true;
         invalidPoint = coord->getAt(0);
-        delete coord;
         return;
     }
 
-    Edge* e = new Edge(coord, Label(argIndex, Location::INTERIOR));
+    auto coordRaw = coord.release();
+    Edge* e = new Edge(coordRaw, Label(argIndex, Location::INTERIOR));
     lineEdgeMap[line] = e;
     insertEdge(e);
 
@@ -319,9 +315,9 @@ GeometryGraph::addLineString(const LineString* line)
      * This allows for the case that the node already exists and is
      * a boundary point.
      */
-    assert(coord->size() >= 2); // found LineString with single point
-    insertBoundaryPoint(argIndex, coord->getAt(0));
-    insertBoundaryPoint(argIndex, coord->getAt(coord->getSize() - 1));
+    assert(coordRaw->size() >= 2); // found LineString with single point
+    insertBoundaryPoint(argIndex, coordRaw->getAt(0));
+    insertBoundaryPoint(argIndex, coordRaw->getAt(coordRaw->getSize() - 1));
 }
 
 /*
diff --git a/src/noding/ScaledNoder.cpp b/src/noding/ScaledNoder.cpp
index dcbb005..71747f4 100644
--- a/src/noding/ScaledNoder.cpp
+++ b/src/noding/ScaledNoder.cpp
@@ -21,6 +21,8 @@
 #include <geos/geom/CoordinateFilter.h> // for inheritance
 #include <geos/noding/ScaledNoder.h>
 #include <geos/noding/SegmentString.h>
+#include <geos/operation/valid/RepeatedPointRemover.h>
+#include <geos/operation/valid/RepeatedPointTester.h>
 #include <geos/util/math.h>
 #include <geos/util.h>
 
@@ -169,8 +171,13 @@ ScaledNoder::scale(SegmentString::NonConstVect& segStrings) const
         // SegmentStrings here, but who's going
         // to delete them then ? And is it worth
         // the memory cost ?
-        cs->removeRepeatedPoints();
-
+        operation::valid::RepeatedPointTester rpt;
+        if (rpt.hasRepeatedPoint(cs)) {
+            auto cs2 = operation::valid::RepeatedPointRemover::removeRepeatedPoints(cs);
+            delete cs;
+            cs = cs2.release();
+            // FIXME
+        }
     }
 }
 
diff --git a/src/operation/buffer/BufferBuilder.cpp b/src/operation/buffer/BufferBuilder.cpp
index 5e1afe5..5211d68 100644
--- a/src/operation/buffer/BufferBuilder.cpp
+++ b/src/operation/buffer/BufferBuilder.cpp
@@ -35,6 +35,7 @@
 #include <geos/operation/overlay/snap/SnapOverlayOp.h>
 #include <geos/operation/overlay/PolygonBuilder.h>
 #include <geos/operation/overlay/OverlayNodeFactory.h>
+#include <geos/operation/valid/RepeatedPointRemover.h>
 #include <geos/operation/linemerge/LineMerger.h>
 #include <geos/algorithm/LineIntersector.h>
 #include <geos/noding/IntersectionAdder.h>
@@ -556,17 +557,16 @@ BufferBuilder::computeNodedEdges(SegmentString::NonConstVect& bufferSegStrList,
         SegmentString* segStr = *i;
         const Label* oldLabel = static_cast<const Label*>(segStr->getData());
 
-        CoordinateSequence* cs = CoordinateSequence::removeRepeatedPoints(segStr->getCoordinates());
+        auto cs = operation::valid::RepeatedPointRemover::removeRepeatedPoints(segStr->getCoordinates());
         delete segStr;
         if(cs->size() < 2) {
             // don't insert collapsed edges
             // we need to take care of the memory here as cs is a new sequence
-            delete cs;
             continue;
         }
 
         // Edge takes ownership of the CoordinateSequence
-        Edge* edge = new Edge(cs, *oldLabel);
+        Edge* edge = new Edge(cs.release(), *oldLabel);
 
         // will take care of the Edge ownership
         insertUniqueEdge(edge);
diff --git a/src/operation/buffer/OffsetCurveSetBuilder.cpp b/src/operation/buffer/OffsetCurveSetBuilder.cpp
index a32770a..802cd51 100644
--- a/src/operation/buffer/OffsetCurveSetBuilder.cpp
+++ b/src/operation/buffer/OffsetCurveSetBuilder.cpp
@@ -25,6 +25,7 @@
 #include <geos/util/UnsupportedOperationException.h>
 #include <geos/operation/buffer/OffsetCurveSetBuilder.h>
 #include <geos/operation/buffer/OffsetCurveBuilder.h>
+#include <geos/operation/valid/RepeatedPointRemover.h>
 #include <geos/geom/CoordinateSequence.h>
 #include <geos/geom/Geometry.h>
 #include <geos/geom/GeometryFactory.h>
@@ -204,7 +205,7 @@ OffsetCurveSetBuilder::addLineString(const LineString* line)
 #if GEOS_DEBUG
     std::cerr << __FUNCTION__ << ": " << line->toString() << std::endl;
 #endif
-    std::unique_ptr<CoordinateSequence> coord(CoordinateSequence::removeRepeatedPoints(line->getCoordinatesRO()));
+    auto coord = operation::valid::RepeatedPointRemover::removeRepeatedPoints(line->getCoordinatesRO());
 #if GEOS_DEBUG
     std::cerr << " After coordinate removal: " << coord->toString() << std::endl;
 #endif
@@ -237,24 +238,22 @@ OffsetCurveSetBuilder::addPolygon(const Polygon* p)
         return;
     }
 
+    auto shellCoord =
+            operation::valid::RepeatedPointRemover::removeRepeatedPoints(shell->getCoordinatesRO());
+
     // don't attempt to buffer a polygon
     // with too few distinct vertices
-    CoordinateSequence* shellCoord =
-        CoordinateSequence::removeRepeatedPoints(shell->getCoordinatesRO());
     if(distance <= 0.0 && shellCoord->size() < 3) {
-        delete shellCoord;
         return;
     }
 
     addPolygonRing(
-        shellCoord,
+        shellCoord.get(),
         offsetDistance,
         offsetSide,
         Location::EXTERIOR,
         Location::INTERIOR);
 
-    delete shellCoord;
-
     for(size_t i = 0, n = p->getNumInteriorRing(); i < n; ++i) {
         const LineString* hls = p->getInteriorRingN(i);
         assert(dynamic_cast<const LinearRing*>(hls));
@@ -266,20 +265,17 @@ OffsetCurveSetBuilder::addPolygon(const Polygon* p)
             continue;
         }
 
-        CoordinateSequence* holeCoord =
-            CoordinateSequence::removeRepeatedPoints(hole->getCoordinatesRO());
+        auto holeCoord = valid::RepeatedPointRemover::removeRepeatedPoints(hole->getCoordinatesRO());
 
         // Holes are topologically labelled opposite to the shell,
         // since the interior of the polygon lies on their opposite
         // side (on the left, if the hole is oriented CCW)
         addPolygonRing(
-            holeCoord,
+            holeCoord.get(),
             offsetDistance,
             Position::opposite(offsetSide),
             Location::INTERIOR,
             Location::EXTERIOR);
-
-        delete holeCoord;
     }
 }
 
diff --git a/src/operation/intersection/RectangleIntersectionBuilder.cpp b/src/operation/intersection/RectangleIntersectionBuilder.cpp
index f0f4984..c0bd960 100644
--- a/src/operation/intersection/RectangleIntersectionBuilder.cpp
+++ b/src/operation/intersection/RectangleIntersectionBuilder.cpp
@@ -14,6 +14,7 @@
 
 #include <geos/operation/intersection/Rectangle.h>
 #include <geos/operation/intersection/RectangleIntersectionBuilder.h>
+#include <geos/operation/valid/RepeatedPointRemover.h>
 #include <geos/geom/CoordinateSequenceFactory.h>
 #include <geos/geom/GeometryFactory.h>
 #include <geos/geom/GeometryCollection.h>
@@ -72,14 +73,13 @@ RectangleIntersectionBuilder::reconnect()
     }
 
     // Merge the two linestrings
-
-    CoordinateSequence* ncs = CoordinateSequence::removeRepeatedPoints(&cs2);
+    auto ncs = valid::RepeatedPointRemover::removeRepeatedPoints(&cs2);
     ncs->add(&cs1, false, true);
 
     delete line1;
     delete line2;
 
-    LineString* nline = _gf.createLineString(ncs);
+    LineString* nline = _gf.createLineString(ncs.release());
     lines.pop_front();
     lines.pop_back();
 
diff --git a/src/operation/linemerge/LineMergeGraph.cpp b/src/operation/linemerge/LineMergeGraph.cpp
index 7585087..d3c2197 100644
--- a/src/operation/linemerge/LineMergeGraph.cpp
+++ b/src/operation/linemerge/LineMergeGraph.cpp
@@ -21,6 +21,7 @@
 #include <geos/operation/linemerge/LineMergeGraph.h>
 #include <geos/operation/linemerge/LineMergeEdge.h>
 #include <geos/operation/linemerge/LineMergeDirectedEdge.h>
+#include <geos/operation/valid/RepeatedPointRemover.h>
 #include <geos/planargraph/DirectedEdge.h>
 #include <geos/planargraph/Node.h>
 #include <geos/geom/CoordinateSequence.h>
@@ -56,9 +57,7 @@ LineMergeGraph::addEdge(const LineString* lineString)
     cerr << "Adding LineString " << lineString->toString() << endl;
 #endif
 
-    std::unique_ptr<CoordinateSequence> coordinates(
-        CoordinateSequence::removeRepeatedPoints(lineString->getCoordinatesRO())
-    );
+    auto coordinates = valid::RepeatedPointRemover::removeRepeatedPoints(lineString->getCoordinatesRO());
 
     std::size_t nCoords = coordinates->size(); // virtual call..
 
diff --git a/src/operation/polygonize/PolygonizeGraph.cpp b/src/operation/polygonize/PolygonizeGraph.cpp
index afb3f4f..3bafb0f 100644
--- a/src/operation/polygonize/PolygonizeGraph.cpp
+++ b/src/operation/polygonize/PolygonizeGraph.cpp
@@ -21,6 +21,7 @@
 #include <geos/operation/polygonize/PolygonizeDirectedEdge.h>
 #include <geos/operation/polygonize/PolygonizeEdge.h>
 #include <geos/operation/polygonize/EdgeRing.h>
+#include <geos/operation/valid/RepeatedPointRemover.h>
 #include <geos/planargraph/Node.h>
 #include <geos/planargraph/DirectedEdgeStar.h>
 #include <geos/planargraph/DirectedEdge.h>
@@ -127,14 +128,13 @@ PolygonizeGraph::addEdge(const LineString* line)
         return;
     }
 
-    CoordinateSequence* linePts = CoordinateSequence::removeRepeatedPoints(line->getCoordinatesRO());
+    auto linePts = valid::RepeatedPointRemover::removeRepeatedPoints(line->getCoordinatesRO());
 
     /*
      * This would catch invalid linestrings
      * (containing duplicated points only)
      */
     if(linePts->getSize() < 2) {
-        delete linePts;
         return;
     }
 
@@ -152,7 +152,7 @@ PolygonizeGraph::addEdge(const LineString* line)
     edge->setDirectedEdges(de0, de1);
     add(edge);
 
-    newCoords.push_back(linePts);
+    newCoords.push_back(linePts.release());
 }
 
 Node*
diff --git a/src/operation/valid/Makefile.am b/src/operation/valid/Makefile.am
index 4c082a7..7d66258 100644
--- a/src/operation/valid/Makefile.am
+++ b/src/operation/valid/Makefile.am
@@ -16,6 +16,7 @@ libopvalid_la_SOURCES = \
     ConsistentAreaTester.cpp \
     IsValidOp.cpp \
     QuadtreeNestedRingTester.cpp \
+    RepeatedPointRemover.cpp \
     RepeatedPointTester.cpp \
     SimpleNestedRingTester.cpp \
     SweeplineNestedRingTester.cpp \
diff --git a/src/operation/valid/RepeatedPointRemover.cpp b/src/operation/valid/RepeatedPointRemover.cpp
new file mode 100644
index 0000000..ec5bf30
--- /dev/null
+++ b/src/operation/valid/RepeatedPointRemover.cpp
@@ -0,0 +1,54 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2019 Daniel Baston <dbaston at gmail.com
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************/
+
+#include <geos/operation/valid/RepeatedPointRemover.h>
+
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/CoordinateArraySequenceFactory.h>
+
+namespace geos {
+namespace operation {
+namespace valid {
+
+std::unique_ptr<geom::CoordinateSequence>
+RepeatedPointRemover::removeRepeatedPoints(const geom::CoordinateSequence* seq) {
+    using geom::Coordinate;
+
+    auto seqFactory = geom::CoordinateArraySequenceFactory::instance();
+
+    if (seq->isEmpty()) {
+        return std::unique_ptr<geom::CoordinateSequence>(seqFactory->create());
+    }
+
+    std::unique_ptr<std::vector<Coordinate>> pts(new std::vector<Coordinate>);
+    auto sz = seq->getSize();
+    pts->reserve(sz); // assume not many points are repeated
+
+    const Coordinate* prevPt = &(seq->getAt(0));
+    pts->push_back(*prevPt) ;
+
+    for (size_t i = 1; i < sz; i++) {
+        const Coordinate* nextPt = &(seq->getAt(i));
+        if (*nextPt != *prevPt) {
+            pts->push_back(*nextPt);
+        }
+        prevPt = nextPt;
+    }
+
+    return std::unique_ptr<geom::CoordinateSequence>(seqFactory->create(pts.release(), seq->getDimension()));
+}
+
+}
+}
+}
diff --git a/src/precision/PrecisionReducerCoordinateOperation.cpp b/src/precision/PrecisionReducerCoordinateOperation.cpp
index 20de484..d2b5099 100644
--- a/src/precision/PrecisionReducerCoordinateOperation.cpp
+++ b/src/precision/PrecisionReducerCoordinateOperation.cpp
@@ -24,6 +24,7 @@
 #include <geos/geom/Geometry.h>
 #include <geos/geom/LineString.h>
 #include <geos/geom/LinearRing.h>
+#include <geos/operation/valid/RepeatedPointRemover.h>
 
 #include <vector>
 
@@ -58,8 +59,7 @@ PrecisionReducerCoordinateOperation::edit(const CoordinateSequence* cs,
 
     // remove repeated points, to simplify returned geometry as
     // much as possible.
-    //
-    CoordinateSequence* noRepeatedCoords = CoordinateSequence::removeRepeatedPoints(reducedCoords);
+    auto noRepeatedCoords = operation::valid::RepeatedPointRemover::removeRepeatedPoints(reducedCoords);
 
     /**
      * Check to see if the removal of repeated points
@@ -89,13 +89,12 @@ PrecisionReducerCoordinateOperation::edit(const CoordinateSequence* cs,
 
     // return null or orginal length coordinate array
     if(noRepeatedCoords->getSize() < minLength) {
-        delete noRepeatedCoords;
         return collapsedCoords;
     }
 
     // ok to return shorter coordinate array
     delete reducedCoords;
-    return noRepeatedCoords;
+    return noRepeatedCoords.release();
 }
 
 
diff --git a/src/precision/SimpleGeometryPrecisionReducer.cpp b/src/precision/SimpleGeometryPrecisionReducer.cpp
index 33a2cf2..04a91d3 100644
--- a/src/precision/SimpleGeometryPrecisionReducer.cpp
+++ b/src/precision/SimpleGeometryPrecisionReducer.cpp
@@ -27,6 +27,7 @@
 #include <geos/geom/GeometryFactory.h>
 #include <geos/geom/LineString.h>
 #include <geos/geom/LinearRing.h>
+#include <geos/operation/valid/RepeatedPointRemover.h>
 
 #include <vector>
 #include <typeinfo>
@@ -89,8 +90,7 @@ PrecisionReducerCoordinateOperation::edit(const CoordinateSequence* cs,
 
     // remove repeated points, to simplify returned geometry as
     // much as possible.
-    //
-    CoordinateSequence* noRepeatedCoords = CoordinateSequence::removeRepeatedPoints(reducedCoords);
+    auto noRepeatedCoords = operation::valid::RepeatedPointRemover::removeRepeatedPoints(reducedCoords);
 
     /**
      * Check to see if the removal of repeated points
@@ -118,12 +118,11 @@ PrecisionReducerCoordinateOperation::edit(const CoordinateSequence* cs,
     }
     // return null or orginal length coordinate array
     if(noRepeatedCoords->getSize() < minLength) {
-        delete noRepeatedCoords;
         return collapsedCoords;
     }
     // ok to return shorter coordinate array
     delete reducedCoords;
-    return noRepeatedCoords;
+    return noRepeatedCoords.release();
 }
 
 } // anonymous namespace
diff --git a/src/triangulate/DelaunayTriangulationBuilder.cpp b/src/triangulate/DelaunayTriangulationBuilder.cpp
index f219bea..389aa9e 100644
--- a/src/triangulate/DelaunayTriangulationBuilder.cpp
+++ b/src/triangulate/DelaunayTriangulationBuilder.cpp
@@ -22,32 +22,44 @@
 
 #include <geos/geom/GeometryFactory.h>
 #include <geos/geom/Coordinate.h>
+#include <geos/geom/CoordinateArraySequenceFactory.h>
 #include <geos/geom/CoordinateSequence.h>
+#include <geos/operation/valid/RepeatedPointRemover.h>
 #include <geos/triangulate/IncrementalDelaunayTriangulator.h>
 #include <geos/triangulate/quadedge/QuadEdgeSubdivision.h>
+#include <geos/operation/valid/RepeatedPointRemover.h>
+#include <geos/operation/valid/RepeatedPointTester.h>
 
 namespace geos {
 namespace triangulate { //geos.triangulate
 
 using namespace geos::geom;
 
-CoordinateSequence*
+std::unique_ptr<CoordinateSequence>
 DelaunayTriangulationBuilder::extractUniqueCoordinates(
     const Geometry& geom)
 {
-    geom::CoordinateSequence* coords = geom.getCoordinates();
-    unique(*coords);
-    return coords;
+    std::unique_ptr<CoordinateSequence> seq(geom.getCoordinates());
+    return unique(seq.get());
 }
 
-void
-DelaunayTriangulationBuilder::unique(CoordinateSequence& coords)
-{
-    std::vector<Coordinate> coordVector;
-    coords.toVector(coordVector);
-    std::sort(coordVector.begin(), coordVector.end(), geos::geom::CoordinateLessThen());
-    coords.setPoints(coordVector);
-    coords.removeRepeatedPoints();
+std::unique_ptr<CoordinateSequence>
+DelaunayTriangulationBuilder::unique(const CoordinateSequence* seq) {
+    auto seqFactory = CoordinateArraySequenceFactory::instance();
+    auto dim = seq->getDimension();
+
+    std::unique_ptr<std::vector<Coordinate>> coords(new std::vector<Coordinate>());
+    seq->toVector(*(coords.get()));
+    std::sort(coords->begin(), coords->end(), geos::geom::CoordinateLessThen());
+
+    std::unique_ptr<CoordinateSequence> sortedSeq(seqFactory->create(coords.release(), dim));
+
+    operation::valid::RepeatedPointTester rpt;
+    if (rpt.hasRepeatedPoint(sortedSeq.get())) {
+        return operation::valid::RepeatedPointRemover::removeRepeatedPoints(sortedSeq.get());
+    } else {
+        return sortedSeq;
+    }
 }
 
 IncrementalDelaunayTriangulator::VertexList*
@@ -70,9 +82,6 @@ DelaunayTriangulationBuilder::DelaunayTriangulationBuilder() :
 
 DelaunayTriangulationBuilder::~DelaunayTriangulationBuilder()
 {
-    if(siteCoords) {
-        delete siteCoords;
-    }
     if(subdiv) {
         delete subdiv;
     }
@@ -81,9 +90,6 @@ DelaunayTriangulationBuilder::~DelaunayTriangulationBuilder()
 void
 DelaunayTriangulationBuilder::setSites(const Geometry& geom)
 {
-    if(siteCoords) {
-        delete siteCoords;
-    }
     // remove any duplicate points (they will cause the triangulation to fail)
     siteCoords = extractUniqueCoordinates(geom);
 }
@@ -91,12 +97,8 @@ DelaunayTriangulationBuilder::setSites(const Geometry& geom)
 void
 DelaunayTriangulationBuilder::setSites(const CoordinateSequence& coords)
 {
-    if(siteCoords) {
-        delete siteCoords;
-    }
-    siteCoords = coords.clone();
     // remove any duplicate points (they will cause the triangulation to fail)
-    unique(*siteCoords);
+    siteCoords = operation::valid::RepeatedPointRemover::removeRepeatedPoints(&coords);
 }
 
 void
diff --git a/src/triangulate/VoronoiDiagramBuilder.cpp b/src/triangulate/VoronoiDiagramBuilder.cpp
index 0b36554..bc14370 100644
--- a/src/triangulate/VoronoiDiagramBuilder.cpp
+++ b/src/triangulate/VoronoiDiagramBuilder.cpp
@@ -30,6 +30,7 @@
 #include <geos/triangulate/IncrementalDelaunayTriangulator.h>
 #include <geos/triangulate/DelaunayTriangulationBuilder.h>
 #include <geos/triangulate/quadedge/QuadEdgeSubdivision.h>
+#include <geos/operation/valid/RepeatedPointRemover.h>
 
 namespace geos {
 namespace triangulate { //geos.triangulate
@@ -49,14 +50,13 @@ VoronoiDiagramBuilder::~VoronoiDiagramBuilder()
 void
 VoronoiDiagramBuilder::setSites(const geom::Geometry& geom)
 {
-    siteCoords.reset(DelaunayTriangulationBuilder::extractUniqueCoordinates(geom));
+    siteCoords = DelaunayTriangulationBuilder::extractUniqueCoordinates(geom);
 }
 
 void
 VoronoiDiagramBuilder::setSites(const geom::CoordinateSequence& coords)
 {
-    siteCoords.reset(coords.clone());
-    DelaunayTriangulationBuilder::unique(*siteCoords);
+    siteCoords = operation::valid::RepeatedPointRemover::removeRepeatedPoints(&coords);
 }
 
 void
diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am
index 0531e38..ac7af8a 100644
--- a/tests/unit/Makefile.am
+++ b/tests/unit/Makefile.am
@@ -120,6 +120,7 @@ geos_unit_SOURCES = \
 	operation/union/CascadedPolygonUnionTest.cpp \
 	operation/union/UnaryUnionOpTest.cpp \
 	operation/valid/IsValidTest.cpp \
+	operation/valid/RepeatedPointRemoverTest.cpp \
 	operation/valid/ValidClosedRingTest.cpp \
 	operation/valid/ValidSelfTouchingRingFormingHoleTest.cpp \
 	precision/SimpleGeometryPrecisionReducerTest.cpp \
diff --git a/tests/unit/geom/CoordinateArraySequenceTest.cpp b/tests/unit/geom/CoordinateArraySequenceTest.cpp
index 19bcefe..fdb42b7 100644
--- a/tests/unit/geom/CoordinateArraySequenceTest.cpp
+++ b/tests/unit/geom/CoordinateArraySequenceTest.cpp
@@ -408,34 +408,6 @@ void object::test<10>
     ensure_equals(sequence.getAt(2).z, 27);
 }
 
-// Test of removeRepeatedPoints
-template<>
-template<>
-void object::test<11>
-()
-{
-    using geos::geom::Coordinate;
-
-    geos::geom::CoordinateArraySequence sequence;
-
-    // Add new 3 equal coordinates
-    Coordinate c(1, 2, 3);
-    sequence.add(c);
-    sequence.add(c);
-    sequence.add(c);
-
-    Coordinate c2(5, 10, 15);
-    sequence.add(c2);
-    sequence.add(c2);
-
-    sequence.add(c);
-
-    ensure_equals(sequence.size(), 6u);
-    sequence.removeRepeatedPoints();
-
-    ensure_equals(sequence.size(), 3u);
-}
-
 // Test of equality and inequality operators
 template<>
 template<>
diff --git a/tests/unit/operation/valid/RepeatedPointRemoverTest.cpp b/tests/unit/operation/valid/RepeatedPointRemoverTest.cpp
new file mode 100644
index 0000000..7276e74
--- /dev/null
+++ b/tests/unit/operation/valid/RepeatedPointRemoverTest.cpp
@@ -0,0 +1,62 @@
+//
+// Test Suite for geos::operation::valid::RepeatedPointRemover class.
+//
+
+// tut
+#include <tut/tut.hpp>
+// geos
+#include <geos/operation/valid/RepeatedPointRemover.h>
+#include <geos/geom/Geometry.h>
+#include <geos/geom/LineString.h>
+#include <geos/geom/CoordinateSequence.h>
+#include <geos/io/WKTReader.h>
+// std
+#include <memory>
+#include <string>
+
+using geos::geom::Geometry;
+using geos::geom::LineString;
+using geos::geom::CoordinateSequence;
+using geos::operation::valid::RepeatedPointRemover;
+
+
+namespace tut {
+//
+// Test Group
+//
+
+// Common data used by tests
+    struct test_repeated_point_remover_test_data {
+        geos::io::WKTReader wktreader;
+
+        test_repeated_point_remover_test_data()
+                : wktreader()
+        {}
+
+        std::unique_ptr<Geometry> readWKT(const std::string & wkt) {
+            return std::unique_ptr<Geometry>(wktreader.read(wkt));
+        }
+    };
+
+    typedef test_group<test_repeated_point_remover_test_data> group;
+    typedef group::object object;
+
+    group test_repeated_point_remover_group("geos::operation::valid::RepeatedPointRemover");
+
+    template<>
+    template<>
+    void object::test<1>()
+    {
+        auto input = readWKT("LINESTRING (3 7, 8 8, 8 8, 8 8, 10 9)");
+        auto expected = readWKT("LINESTRING (3 7, 8 8, 10 9)");
+
+        std::unique_ptr<CoordinateSequence> coords(input->getCoordinates());
+        auto resultCoords = RepeatedPointRemover::removeRepeatedPoints(coords.get());
+
+        std::unique_ptr<LineString> result(input->getFactory()->createLineString(resultCoords.release()));
+
+        ensure(expected->equalsExact(result.get()));
+    }
+} // namespace tut
+
+
diff --git a/tests/unit/triangulate/DelaunayTest.cpp b/tests/unit/triangulate/DelaunayTest.cpp
index 5cdb7d3..2fef678 100644
--- a/tests/unit/triangulate/DelaunayTest.cpp
+++ b/tests/unit/triangulate/DelaunayTest.cpp
@@ -38,7 +38,7 @@ typedef group::object object;
 
 group test_incdelaunaytri_group("geos::triangulate::Delaunay");
 
-//helper function for funning triangulation
+//helper function for running triangulation
 void
 runDelaunay(const char* sitesWkt, bool computeTriangles, const char* expectedWkt, double tolerance = 0.0)
 {
diff --git a/tests/unit/triangulate/quadedge/QuadEdgeSubdivisionTest.cpp b/tests/unit/triangulate/quadedge/QuadEdgeSubdivisionTest.cpp
index 23cf51a..2506747 100644
--- a/tests/unit/triangulate/quadedge/QuadEdgeSubdivisionTest.cpp
+++ b/tests/unit/triangulate/quadedge/QuadEdgeSubdivisionTest.cpp
@@ -19,6 +19,7 @@
 #include <geos/io/WKTReader.h>
 #include <geos/geom/Envelope.h>
 #include <geos/geom/Coordinate.h>
+#include <geos/operation/valid/RepeatedPointRemover.h>
 // std
 #include <stdio.h>
 #include <iostream>
@@ -87,7 +88,7 @@ void object::test<2>
     Geometry* sites;
     QuadEdgeSubdivision* subdiv;
     sites = reader.read("MULTIPOINT ((150 200), (180 270), (275 163))");
-    CoordinateSequence* siteCoords = DelaunayTriangulationBuilder::extractUniqueCoordinates(*sites);
+    auto siteCoords = DelaunayTriangulationBuilder::extractUniqueCoordinates(*sites);
     Envelope Env = DelaunayTriangulationBuilder::envelope(*siteCoords);
 
     double expandBy = std::max(Env.getWidth(), Env.getHeight());
@@ -109,7 +110,6 @@ void object::test<2>
     polys->normalize();
     expected->normalize();
     ensure(polys->equalsExact(expected, 1e-7));
-    delete siteCoords;
     delete sites;
     delete subdiv;
     delete vertices;
@@ -158,7 +158,7 @@ template<> template<> void object::test<3>
             p->getExteriorRing()->getCoordinates()
         );
         size_t from = cs->size();
-        cs->removeRepeatedPoints();
+        cs = geos::operation::valid::RepeatedPointRemover::removeRepeatedPoints(cs.get());
         ensure_equals(from, cs->size());
     }
 }

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

Summary of changes:
 include/geos/geom/CoordinateArraySequence.h        |  2 -
 include/geos/geom/CoordinateSequence.h             | 33 +-----------
 include/geos/operation/valid/Makefile.am           |  1 +
 .../geos/operation/valid/RepeatedPointRemover.h    | 41 ++++++++++++++
 .../triangulate/DelaunayTriangulationBuilder.h     | 16 ++++--
 src/geom/CoordinateArraySequence.cpp               | 12 -----
 src/geom/CoordinateSequence.cpp                    | 38 ++++++-------
 src/geomgraph/GeometryGraph.cpp                    | 34 ++++++------
 src/noding/ScaledNoder.cpp                         | 11 +++-
 src/operation/buffer/BufferBuilder.cpp             |  6 +--
 src/operation/buffer/OffsetCurveSetBuilder.cpp     | 20 +++----
 .../intersection/RectangleIntersectionBuilder.cpp  |  6 +--
 src/operation/linemerge/LineMergeGraph.cpp         |  5 +-
 src/operation/polygonize/PolygonizeGraph.cpp       |  6 +--
 src/operation/valid/Makefile.am                    |  1 +
 src/operation/valid/RepeatedPointRemover.cpp       | 54 +++++++++++++++++++
 .../PrecisionReducerCoordinateOperation.cpp        |  7 ++-
 src/precision/SimpleGeometryPrecisionReducer.cpp   |  7 ++-
 src/triangulate/DelaunayTriangulationBuilder.cpp   | 48 +++++++++--------
 src/triangulate/VoronoiDiagramBuilder.cpp          |  6 +--
 tests/unit/Makefile.am                             |  1 +
 tests/unit/geom/CoordinateArraySequenceTest.cpp    | 28 ----------
 .../operation/valid/RepeatedPointRemoverTest.cpp   | 62 ++++++++++++++++++++++
 tests/unit/triangulate/DelaunayTest.cpp            |  2 +-
 .../quadedge/QuadEdgeSubdivisionTest.cpp           |  6 +--
 25 files changed, 273 insertions(+), 180 deletions(-)
 create mode 100644 include/geos/operation/valid/RepeatedPointRemover.h
 create mode 100644 src/operation/valid/RepeatedPointRemover.cpp
 create mode 100644 tests/unit/operation/valid/RepeatedPointRemoverTest.cpp


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list