[geos-commits] [SCM] GEOS branch master updated. 7a143371ed80b0f4a613894ab5717ca4cd878a21

git at osgeo.org git at osgeo.org
Thu Sep 5 11:56:56 PDT 2019


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GEOS".

The branch, master has been updated
       via  7a143371ed80b0f4a613894ab5717ca4cd878a21 (commit)
       via  c0792512e490468ff5343c53fc3dd1a8ebc195ab (commit)
       via  dcd417a9de17db283bc144db964e0548305f8d64 (commit)
       via  ef19c262d671c095559cb5aeeebddcecbfddbff8 (commit)
       via  116a57af2e4a052e4c604bc9d58de106481ca386 (commit)
       via  a52c9bb3113e752987658a0382f209e257b6643b (commit)
       via  bb77dfa4f82d3cbba425ddb5c38bb72c8125a733 (commit)
      from  38efd9bd7c5a778983f4ce3d8c557e9d85a76b77 (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 7a143371ed80b0f4a613894ab5717ca4cd878a21
Merge: c079251 dcd417a
Author: Daniel Baston <dbaston at gmail.com>
Date:   Thu Sep 5 14:43:32 2019 -0400

    Merge branch 'reduce-new'


commit c0792512e490468ff5343c53fc3dd1a8ebc195ab
Merge: 38efd9b ef19c26
Author: Daniel Baston <dbaston at gmail.com>
Date:   Thu Sep 5 14:43:11 2019 -0400

    Merge remote-tracking branch 'origin/fixed-size-coordinate-sequence'


commit dcd417a9de17db283bc144db964e0548305f8d64
Author: Daniel Baston <dbaston at gmail.com>
Date:   Thu Sep 5 14:23:30 2019 -0400

    Remove some heap-allocated vectors

diff --git a/include/geos/geom/CoordinateArraySequenceFactory.h b/include/geos/geom/CoordinateArraySequenceFactory.h
index 870a8ff..38614ea 100644
--- a/include/geos/geom/CoordinateArraySequenceFactory.h
+++ b/include/geos/geom/CoordinateArraySequenceFactory.h
@@ -47,6 +47,8 @@ public:
 
     std::unique_ptr<CoordinateSequence> create(std::vector<Coordinate>* coords, std::size_t dims = 0) const override;
 
+    std::unique_ptr<CoordinateSequence> create(std::vector<Coordinate> && coords, std::size_t dims = 0) const override;
+
     /** @see CoordinateSequenceFactory::create(std::size_t, int) */
     std::unique_ptr<CoordinateSequence> create(std::size_t size, std::size_t dimension = 0) const override;
 
diff --git a/include/geos/geom/CoordinateArraySequenceFactory.inl b/include/geos/geom/CoordinateArraySequenceFactory.inl
index dfee25f..761fdc6 100644
--- a/include/geos/geom/CoordinateArraySequenceFactory.inl
+++ b/include/geos/geom/CoordinateArraySequenceFactory.inl
@@ -39,6 +39,12 @@ CoordinateArraySequenceFactory::create(std::vector<Coordinate>* coords,
 }
 
 INLINE std::unique_ptr<CoordinateSequence>
+CoordinateArraySequenceFactory::create(std::vector<Coordinate> && coords,
+        size_t dimension) const {
+    return std::unique_ptr<CoordinateSequence>(new CoordinateArraySequence(std::move(coords), dimension));
+}
+
+INLINE std::unique_ptr<CoordinateSequence>
 CoordinateArraySequenceFactory::create(std::size_t size, std::size_t dimension)
 const
 {
diff --git a/include/geos/geom/CoordinateSequenceFactory.h b/include/geos/geom/CoordinateSequenceFactory.h
index 0cb5151..daf2c30 100644
--- a/include/geos/geom/CoordinateSequenceFactory.h
+++ b/include/geos/geom/CoordinateSequenceFactory.h
@@ -74,6 +74,16 @@ public:
         std::size_t dimension = 0) const = 0;
 
     /** \brief
+     * Returns a CoordinateSequence based on the given array.
+     *
+     * @param coordinates the coordinates
+     * @param dimension 0, 2 or 3 with 0 indicating unknown at this time.
+     */
+    virtual std::unique_ptr<CoordinateSequence> create(
+            std::vector<Coordinate> && coordinates,
+            std::size_t dimension = 0) const = 0;
+
+    /** \brief
      * Creates a CoordinateSequence of the specified size and dimension.
      *
      * For this to be useful, the CoordinateSequence implementation must
diff --git a/src/algorithm/ConvexHull.cpp b/src/algorithm/ConvexHull.cpp
index addadb4..3e8b7be 100644
--- a/src/algorithm/ConvexHull.cpp
+++ b/src/algorithm/ConvexHull.cpp
@@ -105,19 +105,13 @@ ConvexHull::toCoordinateSequence(Coordinate::ConstVect& cv)
     const CoordinateSequenceFactory* csf =
         geomFactory->getCoordinateSequenceFactory();
 
-    // Create a new Coordinate::Vect for feeding it to
-    // the CoordinateSequenceFactory
-    Coordinate::Vect* vect = new Coordinate::Vect();
+    std::vector<Coordinate> vect(cv.size());
 
-    size_t n = cv.size();
-    vect->reserve(n); // avoid multiple reallocs
-
-    for(size_t i = 0; i < n; ++i) {
-        vect->push_back(*(cv[i])); // Coordinate copy
+    for(size_t i = 0; i < cv.size(); ++i) {
+        vect[i] = *(cv[i]); // Coordinate copy
     }
 
-    return csf->create(vect); // takes ownership of the vector
-
+    return csf->create(std::move(vect)); // takes ownership of the vector
 }
 
 /* private */
diff --git a/src/geom/GeometryCollection.cpp b/src/geom/GeometryCollection.cpp
index 46a2812..3e18fc5 100644
--- a/src/geom/GeometryCollection.cpp
+++ b/src/geom/GeometryCollection.cpp
@@ -99,18 +99,18 @@ GeometryCollection::setSRID(int newSRID)
 std::unique_ptr<CoordinateSequence>
 GeometryCollection::getCoordinates() const
 {
-    auto coordinates = detail::make_unique<std::vector<Coordinate>>(getNumPoints());
+    std::vector<Coordinate> coordinates(getNumPoints());
 
     size_t k = 0;
     for(const auto& g : geometries) {
-        auto childCoordinates = g->getCoordinates(); // TODO avoid this copy
+        auto childCoordinates = g->getCoordinates(); // TODO avoid this copy where getCoordinateRO() exists
         size_t npts = childCoordinates->getSize();
         for(size_t j = 0; j < npts; ++j) {
-            (*coordinates)[k] = childCoordinates->getAt(j);
+            coordinates[k] = childCoordinates->getAt(j);
             k++;
         }
     }
-    return CoordinateArraySequenceFactory::instance()->create(coordinates.release());
+    return CoordinateArraySequenceFactory::instance()->create(std::move(coordinates));
 }
 
 bool
diff --git a/src/geom/Polygon.cpp b/src/geom/Polygon.cpp
index b10f360..37624ac 100644
--- a/src/geom/Polygon.cpp
+++ b/src/geom/Polygon.cpp
@@ -125,22 +125,20 @@ Polygon::getCoordinates() const
         return getFactory()->getCoordinateSequenceFactory()->create();
     }
 
-    std::vector<Coordinate>* cl = new std::vector<Coordinate>;
-
-    // reserve space in the vector for all the polygon points
-    cl->reserve(getNumPoints());
+    std::vector<Coordinate> cl;
+    cl.reserve(getNumPoints());
 
     // Add shell points
     const CoordinateSequence* shellCoords = shell->getCoordinatesRO();
-    shellCoords->toVector(*cl);
+    shellCoords->toVector(cl);
 
     // Add holes points
     for(const auto& hole : holes) {
         const CoordinateSequence* childCoords = hole->getCoordinatesRO();
-        childCoords->toVector(*cl);
+        childCoords->toVector(cl);
     }
 
-    return getFactory()->getCoordinateSequenceFactory()->create(cl);
+    return getFactory()->getCoordinateSequenceFactory()->create(std::move(cl));
 }
 
 size_t
diff --git a/src/triangulate/DelaunayTriangulationBuilder.cpp b/src/triangulate/DelaunayTriangulationBuilder.cpp
index d726cb9..8f417d2 100644
--- a/src/triangulate/DelaunayTriangulationBuilder.cpp
+++ b/src/triangulate/DelaunayTriangulationBuilder.cpp
@@ -49,11 +49,11 @@ DelaunayTriangulationBuilder::unique(const CoordinateSequence* seq) {
     auto seqFactory = CoordinateArraySequenceFactory::instance();
     auto dim = seq->getDimension();
 
-    auto coords = detail::make_unique<std::vector<Coordinate>>();
-    seq->toVector(*(coords.get()));
-    std::sort(coords->begin(), coords->end(), geos::geom::CoordinateLessThen());
+    std::vector<Coordinate> coords;
+    seq->toVector(coords);
+    std::sort(coords.begin(), coords.end(), geos::geom::CoordinateLessThen());
 
-    std::unique_ptr<CoordinateSequence> sortedSeq(seqFactory->create(coords.release(), dim));
+    std::unique_ptr<CoordinateSequence> sortedSeq(seqFactory->create(std::move(coords), dim));
 
     operation::valid::RepeatedPointTester rpt;
     if (rpt.hasRepeatedPoint(sortedSeq.get())) {

commit ef19c262d671c095559cb5aeeebddcecbfddbff8
Author: Daniel Baston <dbaston at gmail.com>
Date:   Wed Sep 4 20:46:15 2019 -0400

    Mark FixedSizeCoordinateSequence methods as final

diff --git a/include/geos/geom/FixedSizeCoordinateSequence.h b/include/geos/geom/FixedSizeCoordinateSequence.h
index b42b2cb..add43da 100644
--- a/include/geos/geom/FixedSizeCoordinateSequence.h
+++ b/include/geos/geom/FixedSizeCoordinateSequence.h
@@ -34,29 +34,29 @@ namespace geom {
     public:
         explicit FixedSizeCoordinateSequence(size_t dimension_in = 0) : dimension(dimension_in) {}
 
-        std::unique_ptr<CoordinateSequence> clone() const override {
+        std::unique_ptr<CoordinateSequence> clone() const final {
             auto seq = detail::make_unique<FixedSizeCoordinateSequence<N>>();
             seq->m_data = m_data;
             return std::unique_ptr<CoordinateSequence>(seq.release());
         }
 
-        const Coordinate& getAt(size_t i) const override {
+        const Coordinate& getAt(size_t i) const final {
             return m_data[i];
         }
 
-        void getAt(size_t i, Coordinate& c) const override {
+        void getAt(size_t i, Coordinate& c) const final {
             c = m_data[i];
         }
 
-        size_t getSize() const override {
+        size_t getSize() const final {
             return N;
         }
 
-        bool isEmpty() const override {
+        bool isEmpty() const final {
             return N == 0;
         }
 
-        void setAt(const Coordinate & c, size_t pos) override {
+        void setAt(const Coordinate & c, size_t pos) final {
             m_data[pos] = c;
         }
 
@@ -81,7 +81,7 @@ namespace geom {
             }
         }
 
-        size_t getDimension() const override {
+        size_t getDimension() const final {
             if(dimension != 0) {
                 return dimension;
             }
@@ -104,16 +104,16 @@ namespace geom {
             out.insert(out.end(), m_data.begin(), m_data.end());
         }
 
-        void setPoints(const std::vector<Coordinate> & v) override {
+        void setPoints(const std::vector<Coordinate> & v) final {
             std::copy(v.begin(), v.end(), m_data.begin());
         }
 
-        void apply_ro(CoordinateFilter* filter) const override {
+        void apply_ro(CoordinateFilter* filter) const final {
             std::for_each(m_data.begin(), m_data.end(),
                     [&filter](const Coordinate & c) { filter->filter_ro(&c); });
         }
 
-        void apply_rw(const CoordinateFilter* filter) override {
+        void apply_rw(const CoordinateFilter* filter) final {
             std::for_each(m_data.begin(), m_data.end(),
                     [&filter](Coordinate &c) { filter->filter_rw(&c); });
             dimension = 0; // re-check (see http://trac.osgeo.org/geos/ticket/435)

commit 116a57af2e4a052e4c604bc9d58de106481ca386
Author: Daniel Baston <dbaston at gmail.com>
Date:   Wed Sep 4 20:44:11 2019 -0400

    Make FixedSizeCoordinateSequence match CoordinateArraySequence dim
    behavior

diff --git a/include/geos/geom/FixedSizeCoordinateSequence.h b/include/geos/geom/FixedSizeCoordinateSequence.h
index 2c9d01d..b42b2cb 100644
--- a/include/geos/geom/FixedSizeCoordinateSequence.h
+++ b/include/geos/geom/FixedSizeCoordinateSequence.h
@@ -116,6 +116,7 @@ namespace geom {
         void apply_rw(const CoordinateFilter* filter) override {
             std::for_each(m_data.begin(), m_data.end(),
                     [&filter](Coordinate &c) { filter->filter_rw(&c); });
+            dimension = 0; // re-check (see http://trac.osgeo.org/geos/ticket/435)
         }
 
     private:
diff --git a/tests/unit/geom/FixedSizeCoordinateSequenceTest.cpp b/tests/unit/geom/FixedSizeCoordinateSequenceTest.cpp
index 8b95279..394db77 100644
--- a/tests/unit/geom/FixedSizeCoordinateSequenceTest.cpp
+++ b/tests/unit/geom/FixedSizeCoordinateSequenceTest.cpp
@@ -16,38 +16,112 @@ struct test_fixedsizecoordinatesequence_data {
 typedef test_group<test_fixedsizecoordinatesequence_data> group;
 typedef group::object object;
 
+using geos::geom::FixedSizeCoordinateSequence;
+
 group test_fixedsizecoordinatesequence_group("geos::geom::FixedSizeCoordinateSequence");
 
 //
 // Test Cases
 //
 
+// Empty sequence is empty
 template<>
 template<>
 void object::test<1>() {
-    geos::geom::FixedSizeCoordinateSequence<0> seq;
+    FixedSizeCoordinateSequence<0> seq;
 
     ensure(seq.isEmpty());
+
 }
 
+// test getSize
 template<>
 template<>
 void object::test<2>() {
-    geos::geom::FixedSizeCoordinateSequence<3> seq;
+    FixedSizeCoordinateSequence<3> seq;
 
     ensure_equals(seq.getSize(), 3ul);
 }
 
+//  test setAt, getAt
 template<>
 template<>
 void object::test<3>() {
-    geos::geom::FixedSizeCoordinateSequence<3> seq;
+    FixedSizeCoordinateSequence<3> seq;
 
     seq.setAt({1, 2}, 0);
     seq.setAt({3, 4}, 1);
     seq.setAt({5, 6}, 2);
 
     ensure(seq.getAt(0) == geos::geom::Coordinate{1, 2});
+
+    geos::geom::Coordinate c;
+    seq.getAt(2, c);
+    ensure(c == geos::geom::Coordinate{5, 6});
+}
+
+// test setOrdinate
+template<>
+template<>
+void object::test<4>() {
+    FixedSizeCoordinateSequence<2> seq;
+
+    seq.setOrdinate(0, geos::geom::CoordinateSequence::X, 2.2);
+    seq.setOrdinate(0, geos::geom::CoordinateSequence::Y, 3.3);
+    seq.setOrdinate(0, geos::geom::CoordinateSequence::Z, 4.4);
+
+    try {
+        seq.setOrdinate(0, 17, 5.5);
+        fail();
+    } catch (geos::util::IllegalArgumentException & e) {}
+
+    ensure(seq[0].equals3D(geos::geom::Coordinate{2.2, 3.3, 4.4}));
+}
+
+// test getDimension
+template<>
+template<>
+void object::test<5>() {
+    // empty sequence is always XYZ
+    FixedSizeCoordinateSequence<0> seq0;
+    ensure_equals(seq0.getDimension(), 3ul);
+
+    // sequence dimension is set by first coordinate
+    FixedSizeCoordinateSequence<1> seq1_2d;
+    seq1_2d.setAt({1, 2}, 0);
+    ensure_equals(seq1_2d.getDimension(), 2ul);
+
+    FixedSizeCoordinateSequence<1> seq1_3d;
+    seq1_3d.setAt({1, 2, 3}, 0);
+    ensure_equals(seq1_3d.getDimension(), 3ul);
+
+    // sequence dimension doesn't change even if coordinate dimension does
+    seq1_2d.setAt({1, 2, 3}, 0);
+    ensure_equals(seq1_2d.getDimension(), 2ul);
+
+    // sequence dimension doesn't change even if coordinate dimension does
+    seq1_3d.setAt({1, 2}, 0);
+    ensure_equals(seq1_3d.getDimension(), 3ul);
+
+    // unless it's changed by apply_rw. weird!
+
+    struct ZSetter : public geos::geom::CoordinateFilter {
+        ZSetter(double val) : m_val(val) {}
+
+        void filter_rw(geos::geom::Coordinate* c) const override {
+            c->z = m_val;
+        }
+
+        double m_val;
+    };
+
+    ZSetter setNaN(geos::DoubleNotANumber);
+    seq1_3d.apply_rw(&setNaN);
+    ensure_equals(seq1_3d.getDimension(), 2ul);
+
+    ZSetter setZero(0);
+    seq1_3d.apply_rw(&setZero);
+    ensure_equals(seq1_3d.getDimension(), 3ul);
 }
 
 }

commit a52c9bb3113e752987658a0382f209e257b6643b
Author: Daniel Baston <dbaston at gmail.com>
Date:   Wed Sep 4 20:13:21 2019 -0400

    Add FixedSizeCoordinateSequence to autotools build

diff --git a/include/geos/geom/Makefile.am b/include/geos/geom/Makefile.am
index de11186..d5e4665 100644
--- a/include/geos/geom/Makefile.am
+++ b/include/geos/geom/Makefile.am
@@ -24,6 +24,7 @@ geos_HEADERS = \
     Dimension.h \
     Envelope.h \
     Envelope.inl \
+    FixedSizeCoordinateSequence.h \
     GeometryCollection.h \
     GeometryCollection.inl \
     GeometryComponentFilter.h \
diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am
index 4111495..71e1210 100644
--- a/tests/unit/Makefile.am
+++ b/tests/unit/Makefile.am
@@ -63,6 +63,7 @@ geos_unit_SOURCES = \
 	geom/CoordinateTest.cpp \
 	geom/DimensionTest.cpp \
 	geom/EnvelopeTest.cpp \
+	geom/FixedSizeCoordinateSequenceTest.cpp \
 	geom/GeometryCollectionTest.cpp \
 	geom/Geometry/clone.cpp \
 	geom/Geometry/coversTest.cpp \

commit bb77dfa4f82d3cbba425ddb5c38bb72c8125a733
Author: Daniel Baston <dbaston at gmail.com>
Date:   Sat Jun 8 22:54:08 2019 -0400

    Add FixedSizeCoordinateSequence

diff --git a/benchmarks/ClassSizes.cpp b/benchmarks/ClassSizes.cpp
index 1e45a7f..dba2d8d 100644
--- a/benchmarks/ClassSizes.cpp
+++ b/benchmarks/ClassSizes.cpp
@@ -19,6 +19,8 @@
 
 #include <geos/geom/GeometryFactory.h>
 #include <geos/io/WKTReader.h>
+#include <geos/geom/CoordinateArraySequence.h>
+#include <geos/geom/FixedSizeCoordinateSequence.h>
 #include <geos/geom/Geometry.h>
 #include <geos/geom/Point.h>
 #include <geos/geom/LinearRing.h>
@@ -58,6 +60,9 @@ main()
     check(geom::MultiPoint);
     check(geom::MultiLineString);
     check(geom::MultiPolygon);
+    check(geom::CoordinateArraySequence);
+    check(geom::FixedSizeCoordinateSequence<1>);
+    check(geom::FixedSizeCoordinateSequence<2>);
     check(int64);
 }
 
diff --git a/benchmarks/capi/GEOSPreparedContainsPerfTest.cpp b/benchmarks/capi/GEOSPreparedContainsPerfTest.cpp
index c0c9ccd..f010948 100644
--- a/benchmarks/capi/GEOSPreparedContainsPerfTest.cpp
+++ b/benchmarks/capi/GEOSPreparedContainsPerfTest.cpp
@@ -57,10 +57,7 @@ public:
         size_t hits = 0;
         auto prep = GEOSPrepare(g);
         for (const auto& c : coords) {
-            auto seq = GEOSCoordSeq_create(1, 2);
-            GEOSCoordSeq_setX(seq, 0, c.x);
-            GEOSCoordSeq_setY(seq, 0, c.y);
-            auto pt = GEOSGeom_createPoint(seq);
+            auto pt = GEOSGeom_createPointFromXY(c.x, c.y);
 
             if (GEOSPreparedContains(prep, pt)) {
                 hits++;
diff --git a/capi/geos_c.cpp b/capi/geos_c.cpp
index d606940..1a56555 100644
--- a/capi/geos_c.cpp
+++ b/capi/geos_c.cpp
@@ -912,6 +912,12 @@ extern "C" {
     }
 
     Geometry*
+    GEOSGeom_createPointFromXY(double x, double y)
+    {
+        return GEOSGeom_createPointFromXY_r(handle, x, y);
+    }
+
+    Geometry*
     GEOSGeom_createLinearRing(CoordinateSequence* cs)
     {
         return GEOSGeom_createLinearRing_r(handle, cs);
diff --git a/capi/geos_c.h.in b/capi/geos_c.h.in
index e085d96..5f7329e 100644
--- a/capi/geos_c.h.in
+++ b/capi/geos_c.h.in
@@ -480,6 +480,10 @@ extern GEOSGeometry GEOS_DLL *GEOSOffsetCurve_r(GEOSContextHandle_t handle,
 extern GEOSGeometry GEOS_DLL *GEOSGeom_createPoint_r(
                                        GEOSContextHandle_t handle,
                                        GEOSCoordSequence* s);
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createPointFromXY_r(
+                                       GEOSContextHandle_t handle,
+                                       double x,
+                                       double y);
 extern GEOSGeometry GEOS_DLL *GEOSGeom_createEmptyPoint_r(
                                        GEOSContextHandle_t handle);
 extern GEOSGeometry GEOS_DLL *GEOSGeom_createLinearRing_r(
@@ -1525,6 +1529,7 @@ extern GEOSGeometry GEOS_DLL *GEOSOffsetCurve(const GEOSGeometry* g,
  ***********************************************************************/
 
 extern GEOSGeometry GEOS_DLL *GEOSGeom_createPoint(GEOSCoordSequence* s);
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createPointFromXY(double x, double y);
 extern GEOSGeometry GEOS_DLL *GEOSGeom_createEmptyPoint();
 extern GEOSGeometry GEOS_DLL *GEOSGeom_createLinearRing(GEOSCoordSequence* s);
 extern GEOSGeometry GEOS_DLL *GEOSGeom_createLineString(GEOSCoordSequence* s);
diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp
index 826cb71..ad97e95 100644
--- a/capi/geos_ts_c.cpp
+++ b/capi/geos_ts_c.cpp
@@ -32,6 +32,7 @@
 #include <geos/geom/PrecisionModel.h>
 #include <geos/geom/GeometryFactory.h>
 #include <geos/geom/CoordinateSequenceFactory.h>
+#include <geos/geom/FixedSizeCoordinateSequence.h>
 #include <geos/geom/Coordinate.h>
 #include <geos/geom/IntersectionMatrix.h>
 #include <geos/geom/Envelope.h>
@@ -3692,8 +3693,16 @@ extern "C" {
         }
 
         try {
-            const GeometryFactory* gf = handle->geomFactory;
-            return gf->getCoordinateSequenceFactory()->create(size, dims).release();
+            switch (size) {
+                case 1:
+                    return new geos::geom::FixedSizeCoordinateSequence<1>(dims);
+                case 2:
+                    return new geos::geom::FixedSizeCoordinateSequence<2>(dims);
+                default: {
+                    const GeometryFactory *gf = handle->geomFactory;
+                    return gf->getCoordinateSequenceFactory()->create(size, dims).release();
+                }
+            }
         }
         catch(const std::exception& e) {
             handle->ERROR_MESSAGE("%s", e.what());
@@ -4053,6 +4062,34 @@ extern "C" {
     }
 
     Geometry*
+    GEOSGeom_createPointFromXY_r(GEOSContextHandle_t extHandle, double x, double y)
+    {
+        if(0 == extHandle) {
+            return 0;
+        }
+
+        GEOSContextHandleInternal_t* handle = 0;
+        handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
+        if(0 == handle->initialized) {
+            return 0;
+        }
+
+        try {
+            const GeometryFactory* gf = handle->geomFactory;
+            geos::geom::Coordinate c(x, y);
+            return gf->createPoint(c);
+        }
+        catch(const std::exception& e) {
+            handle->ERROR_MESSAGE("%s", e.what());
+        }
+        catch(...) {
+            handle->ERROR_MESSAGE("Unknown exception thrown");
+        }
+
+        return 0;
+    }
+
+    Geometry*
     GEOSGeom_createLinearRing_r(GEOSContextHandle_t extHandle, CoordinateSequence* cs)
     {
         if(0 == extHandle) {
diff --git a/include/geos/geom/CoordinateArraySequence.h b/include/geos/geom/CoordinateArraySequence.h
index 0476ce2..caad30e 100644
--- a/include/geos/geom/CoordinateArraySequence.h
+++ b/include/geos/geom/CoordinateArraySequence.h
@@ -114,9 +114,6 @@ public:
 
     void setPoints(const std::vector<Coordinate>& v) override;
 
-    double getOrdinate(std::size_t index,
-                       size_t ordinateIndex) const override;
-
     void setOrdinate(std::size_t index, std::size_t ordinateIndex,
                      double value) override;
 
diff --git a/include/geos/geom/CoordinateSequence.h b/include/geos/geom/CoordinateSequence.h
index 18bf663..9e135fd 100644
--- a/include/geos/geom/CoordinateSequence.h
+++ b/include/geos/geom/CoordinateSequence.h
@@ -219,7 +219,7 @@ public:
      * @param ordinateIndex the ordinate index in the coordinate
      *                      (in range [0, dimension-1])
      */
-    virtual double getOrdinate(std::size_t index, std::size_t ordinateIndex) const = 0;
+    virtual double getOrdinate(std::size_t index, std::size_t ordinateIndex) const;
 
     /**
      * Returns ordinate X (0) of the specified coordinate.
diff --git a/include/geos/geom/FixedSizeCoordinateSequence.h b/include/geos/geom/FixedSizeCoordinateSequence.h
new file mode 100644
index 0000000..2c9d01d
--- /dev/null
+++ b/include/geos/geom/FixedSizeCoordinateSequence.h
@@ -0,0 +1,129 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2019 Daniel Baston
+ *
+ * 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_GEOM_FIXEDSIZECOORDINATESEQUENCE_H
+#define GEOS_GEOM_FIXEDSIZECOORDINATESEQUENCE_H
+
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/CoordinateFilter.h>
+#include <geos/geom/CoordinateSequence.h>
+#include <geos/util.h>
+
+#include <algorithm>
+#include <array>
+#include <memory>
+#include <sstream>
+#include <vector>
+
+namespace geos {
+namespace geom {
+
+    template<size_t N>
+    class FixedSizeCoordinateSequence : public CoordinateSequence {
+    public:
+        explicit FixedSizeCoordinateSequence(size_t dimension_in = 0) : dimension(dimension_in) {}
+
+        std::unique_ptr<CoordinateSequence> clone() const override {
+            auto seq = detail::make_unique<FixedSizeCoordinateSequence<N>>();
+            seq->m_data = m_data;
+            return std::unique_ptr<CoordinateSequence>(seq.release());
+        }
+
+        const Coordinate& getAt(size_t i) const override {
+            return m_data[i];
+        }
+
+        void getAt(size_t i, Coordinate& c) const override {
+            c = m_data[i];
+        }
+
+        size_t getSize() const override {
+            return N;
+        }
+
+        bool isEmpty() const override {
+            return N == 0;
+        }
+
+        void setAt(const Coordinate & c, size_t pos) override {
+            m_data[pos] = c;
+        }
+
+        void setOrdinate(size_t index, size_t ordinateIndex, double value)
+        {
+            switch(ordinateIndex) {
+                case CoordinateSequence::X:
+                    m_data[index].x = value;
+                    break;
+                case CoordinateSequence::Y:
+                    m_data[index].y = value;
+                    break;
+                case CoordinateSequence::Z:
+                    m_data[index].z = value;
+                    break;
+                default: {
+                    std::stringstream ss;
+                    ss << "Unknown ordinate index " << index;
+                    throw geos::util::IllegalArgumentException(ss.str());
+                    break;
+                }
+            }
+        }
+
+        size_t getDimension() const override {
+            if(dimension != 0) {
+                return dimension;
+            }
+
+            if(isEmpty()) {
+                return 3;
+            }
+
+            if(std::isnan(m_data[0].z)) {
+                dimension = 2;
+            }
+            else {
+                dimension = 3;
+            }
+
+            return dimension;
+        }
+
+        void toVector(std::vector<Coordinate> & out) const {
+            out.insert(out.end(), m_data.begin(), m_data.end());
+        }
+
+        void setPoints(const std::vector<Coordinate> & v) override {
+            std::copy(v.begin(), v.end(), m_data.begin());
+        }
+
+        void apply_ro(CoordinateFilter* filter) const override {
+            std::for_each(m_data.begin(), m_data.end(),
+                    [&filter](const Coordinate & c) { filter->filter_ro(&c); });
+        }
+
+        void apply_rw(const CoordinateFilter* filter) override {
+            std::for_each(m_data.begin(), m_data.end(),
+                    [&filter](Coordinate &c) { filter->filter_rw(&c); });
+        }
+
+    private:
+        std::array<Coordinate, N> m_data;
+        mutable std::size_t dimension;
+    };
+
+}
+}
+
+#endif
diff --git a/include/geos/geom/Point.h b/include/geos/geom/Point.h
index 3a1d838..e9fb358 100644
--- a/include/geos/geom/Point.h
+++ b/include/geos/geom/Point.h
@@ -24,6 +24,7 @@
 #include <geos/export.h>
 #include <geos/geom/Geometry.h> // for inheritance
 #include <geos/geom/CoordinateSequence.h> // for proper use of unique_ptr<>
+#include <geos/geom/FixedSizeCoordinateSequence.h>
 #include <geos/geom/Envelope.h> // for proper use of unique_ptr<>
 #include <geos/geom/Dimension.h> // for Dimension::DimensionType
 
@@ -157,6 +158,8 @@ protected:
      */
     Point(CoordinateSequence* newCoords, const GeometryFactory* newFactory);
 
+    Point(const Coordinate& c, const GeometryFactory* newFactory);
+
     Point(const Point& p);
 
     Envelope::Ptr computeEnvelopeInternal() const override;
@@ -174,7 +177,8 @@ private:
     /**
      *  The <code>Coordinate</code> wrapped by this <code>Point</code>.
      */
-    std::unique_ptr<CoordinateSequence> coordinates;
+    FixedSizeCoordinateSequence<1> coordinates;
+    bool empty;
 };
 
 } // namespace geos::geom
diff --git a/src/geom/CoordinateArraySequence.cpp b/src/geom/CoordinateArraySequence.cpp
index d451a35..9d951ca 100644
--- a/src/geom/CoordinateArraySequence.cpp
+++ b/src/geom/CoordinateArraySequence.cpp
@@ -208,21 +208,6 @@ CoordinateArraySequence::expandEnvelope(Envelope& env) const
     }
 }
 
-double
-CoordinateArraySequence::getOrdinate(size_t index, size_t ordinateIndex) const
-{
-    switch(ordinateIndex) {
-    case CoordinateSequence::X:
-        return vect[index].x;
-    case CoordinateSequence::Y:
-        return vect[index].y;
-    case CoordinateSequence::Z:
-        return vect[index].z;
-    default:
-        return DoubleNotANumber;
-    }
-}
-
 void
 CoordinateArraySequence::setOrdinate(size_t index, size_t ordinateIndex,
                                      double value)
diff --git a/src/geom/CoordinateSequence.cpp b/src/geom/CoordinateSequence.cpp
index f9d0f4d..4af566a 100644
--- a/src/geom/CoordinateSequence.cpp
+++ b/src/geom/CoordinateSequence.cpp
@@ -19,6 +19,7 @@
 #include <geos/geom/CoordinateArraySequenceFactory.h>
 #include <geos/geom/Coordinate.h>
 #include <geos/geom/Envelope.h>
+#include <geos/util/IllegalArgumentException.h>
 
 #include <cstdio>
 #include <algorithm>
@@ -36,6 +37,21 @@ namespace geom { // geos::geom
 static Profiler* profiler = Profiler::instance();
 #endif
 
+double
+CoordinateSequence::getOrdinate(size_t index, size_t ordinateIndex) const
+{
+    switch(ordinateIndex) {
+        case CoordinateSequence::X:
+            return getAt(index).x;
+        case CoordinateSequence::Y:
+            return getAt(index).y;
+        case CoordinateSequence::Z:
+            return getAt(index).z;
+        default:
+            return DoubleNotANumber;
+    }
+}
+
 bool
 CoordinateSequence::hasRepeatedPoints() const
 {
diff --git a/src/geom/GeometryFactory.cpp b/src/geom/GeometryFactory.cpp
index 161b36f..2ef93d8 100644
--- a/src/geom/GeometryFactory.cpp
+++ b/src/geom/GeometryFactory.cpp
@@ -325,11 +325,7 @@ GeometryFactory::createPoint(const Coordinate& coordinate) const
         return createPoint();
     }
     else {
-        std::size_t dim = std::isnan(coordinate.z) ? 2 : 3;
-        auto cl = coordinateListFactory->create(new vector<Coordinate>(1, coordinate), dim);
-
-        Point* ret = createPoint(cl.release());
-        return ret;
+        return new Point(coordinate, this);
     }
 }
 
diff --git a/src/geom/Point.cpp b/src/geom/Point.cpp
index ca665eb..325ec2a 100644
--- a/src/geom/Point.cpp
+++ b/src/geom/Point.cpp
@@ -46,41 +46,56 @@ namespace geom { // geos::geom
 Point::Point(CoordinateSequence* newCoords, const GeometryFactory* factory)
     :
     Geometry(factory),
-    coordinates(newCoords)
+    empty(false)
 {
-    if(coordinates.get() == nullptr) {
-        coordinates = factory->getCoordinateSequenceFactory()->create();
+    std::unique_ptr<CoordinateSequence> coords(newCoords);
+
+    if(coords == nullptr) {
+        empty = true;
         return;
     }
-    if(coordinates->getSize() != 1) {
+
+    if (coords->getSize() == 1) {
+        coordinates.setAt(coords->getAt(0), 0);
+    } else if (coords->getSize() > 1) {
         throw util::IllegalArgumentException("Point coordinate list must contain a single element");
+    } else {
+        empty = true;
     }
 }
 
+Point::Point(const Coordinate & c, const GeometryFactory* factory) :
+    Geometry(factory),
+    empty(false)
+{
+    coordinates.setAt(c, 0);
+}
+
 /*protected*/
 Point::Point(const Point& p)
     :
     Geometry(p),
-    coordinates(p.coordinates->clone())
+    coordinates(p.coordinates),
+    empty(p.empty)
 {
 }
 
 std::unique_ptr<CoordinateSequence>
 Point::getCoordinates() const
 {
-    return coordinates->clone();
+    return coordinates.clone();
 }
 
 size_t
 Point::getNumPoints() const
 {
-    return isEmpty() ? 0 : 1;
+    return empty ? 0 : 1;
 }
 
 bool
 Point::isEmpty() const
 {
-    return coordinates->isEmpty();
+    return empty;
 }
 
 bool
@@ -98,7 +113,7 @@ Point::getDimension() const
 int
 Point::getCoordinateDimension() const
 {
-    return (int) coordinates->getDimension();
+    return (int) coordinates.getDimension();
 }
 
 int
@@ -137,7 +152,7 @@ Point::getZ() const
 const Coordinate*
 Point::getCoordinate() const
 {
-    return coordinates->getSize() != 0 ? &(coordinates->getAt(0)) : nullptr;
+    return empty ? nullptr : &coordinates[0];
 }
 
 string
@@ -176,12 +191,7 @@ Point::apply_ro(CoordinateFilter* filter) const
 void
 Point::apply_rw(const CoordinateFilter* filter)
 {
-    if(isEmpty()) {
-        return;
-    }
-    Coordinate newcoord = coordinates->getAt(0);
-    filter->filter_rw(&newcoord);
-    coordinates->setAt(newcoord, 0);
+    coordinates.apply_rw(filter);
 }
 
 void
@@ -214,7 +224,7 @@ Point::apply_rw(CoordinateSequenceFilter& filter)
     if(isEmpty()) {
         return;
     }
-    filter.filter_rw(*coordinates, 0);
+    filter.filter_rw(coordinates, 0);
     if(filter.isGeometryChanged()) {
         geometryChanged();
     }
@@ -226,7 +236,7 @@ Point::apply_ro(CoordinateSequenceFilter& filter) const
     if(isEmpty()) {
         return;
     }
-    filter.filter_ro(*coordinates, 0);
+    filter.filter_ro(coordinates, 0);
     //if (filter.isGeometryChanged()) geometryChanged();
 }
 
@@ -279,7 +289,7 @@ Point::getGeometryTypeId() const
 const CoordinateSequence*
 Point::getCoordinatesRO() const
 {
-    return coordinates.get();
+    return &coordinates;
 }
 
 } // namespace geos::geom
diff --git a/tests/unit/geom/FixedSizeCoordinateSequenceTest.cpp b/tests/unit/geom/FixedSizeCoordinateSequenceTest.cpp
new file mode 100644
index 0000000..8b95279
--- /dev/null
+++ b/tests/unit/geom/FixedSizeCoordinateSequenceTest.cpp
@@ -0,0 +1,53 @@
+#include <tut/tut.hpp>
+// geos
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/FixedSizeCoordinateSequence.h>
+// std
+
+namespace tut {
+//
+// Test Group
+//
+
+// Common data used by tests
+struct test_fixedsizecoordinatesequence_data {
+};
+
+typedef test_group<test_fixedsizecoordinatesequence_data> group;
+typedef group::object object;
+
+group test_fixedsizecoordinatesequence_group("geos::geom::FixedSizeCoordinateSequence");
+
+//
+// Test Cases
+//
+
+template<>
+template<>
+void object::test<1>() {
+    geos::geom::FixedSizeCoordinateSequence<0> seq;
+
+    ensure(seq.isEmpty());
+}
+
+template<>
+template<>
+void object::test<2>() {
+    geos::geom::FixedSizeCoordinateSequence<3> seq;
+
+    ensure_equals(seq.getSize(), 3ul);
+}
+
+template<>
+template<>
+void object::test<3>() {
+    geos::geom::FixedSizeCoordinateSequence<3> seq;
+
+    seq.setAt({1, 2}, 0);
+    seq.setAt({3, 4}, 1);
+    seq.setAt({5, 6}, 2);
+
+    ensure(seq.getAt(0) == geos::geom::Coordinate{1, 2});
+}
+
+}

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

Summary of changes:
 benchmarks/ClassSizes.cpp                          |   5 +
 benchmarks/capi/GEOSPreparedContainsPerfTest.cpp   |   5 +-
 capi/geos_c.cpp                                    |   6 +
 capi/geos_c.h.in                                   |   5 +
 capi/geos_ts_c.cpp                                 |  41 ++++++-
 include/geos/geom/CoordinateArraySequence.h        |   3 -
 include/geos/geom/CoordinateArraySequenceFactory.h |   2 +
 .../geos/geom/CoordinateArraySequenceFactory.inl   |   6 +
 include/geos/geom/CoordinateSequence.h             |   2 +-
 include/geos/geom/CoordinateSequenceFactory.h      |  10 ++
 include/geos/geom/FixedSizeCoordinateSequence.h    | 130 +++++++++++++++++++++
 include/geos/geom/Makefile.am                      |   1 +
 include/geos/geom/Point.h                          |   6 +-
 src/algorithm/ConvexHull.cpp                       |  14 +--
 src/geom/CoordinateArraySequence.cpp               |  15 ---
 src/geom/CoordinateSequence.cpp                    |  16 +++
 src/geom/GeometryCollection.cpp                    |   8 +-
 src/geom/GeometryFactory.cpp                       |   6 +-
 src/geom/Point.cpp                                 |  48 +++++---
 src/geom/Polygon.cpp                               |  12 +-
 src/triangulate/DelaunayTriangulationBuilder.cpp   |   8 +-
 tests/unit/Makefile.am                             |   1 +
 .../unit/geom/FixedSizeCoordinateSequenceTest.cpp  | 127 ++++++++++++++++++++
 23 files changed, 402 insertions(+), 75 deletions(-)
 create mode 100644 include/geos/geom/FixedSizeCoordinateSequence.h
 create mode 100644 tests/unit/geom/FixedSizeCoordinateSequenceTest.cpp


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list