[geos-commits] [SCM] GEOS branch master updated. 142466d2244614884386b1c49a23f8849857585c

git at osgeo.org git at osgeo.org
Sat Dec 19 10:36:32 PST 2020


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  142466d2244614884386b1c49a23f8849857585c (commit)
       via  928ffac311678d131d47d9076fb0e837854239d0 (commit)
       via  4c1cf5ae2ad3a0702debca5c6130434e97ccf407 (commit)
       via  9a9ba9eb13b5891f2d5d34bb8a6ae3d85140959d (commit)
       via  67cc8f7aac2531b6a4f5e970d9d85cb9bd2659e2 (commit)
       via  2cffa09cf3819a03c809eee23b69291ba05e4c39 (commit)
      from  4466ee0e4e85f21ef362098f0d61db4222b831b7 (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 142466d2244614884386b1c49a23f8849857585c
Merge: 4466ee0 928ffac
Author: Daniel Baston <dbaston at gmail.com>
Date:   Sat Dec 19 13:36:11 2020 -0500

    Merge branch 'segment-node-list2'


commit 928ffac311678d131d47d9076fb0e837854239d0
Author: Daniel Baston <dbaston at gmail.com>
Date:   Sat Dec 19 12:18:38 2020 -0500

    Inline SegmentNode::compareTo

diff --git a/include/geos/noding/Makefile.am b/include/geos/noding/Makefile.am
index 56e8949..c4cc74b 100644
--- a/include/geos/noding/Makefile.am
+++ b/include/geos/noding/Makefile.am
@@ -1,5 +1,5 @@
 #
-# This file is part of project GEOS (http://trac.osgeo.org/geos/) 
+# This file is part of project GEOS (http://trac.osgeo.org/geos/)
 #
 SUBDIRS = \
 	snapround \
@@ -31,6 +31,7 @@ geos_HEADERS = \
 	SegmentIntersectionDetector.h \
 	SegmentIntersector.h \
 	SegmentNode.h \
+	SegmentNode.inl \
 	SegmentNodeList.h \
 	SegmentPointComparator.h \
 	SegmentSetMutualIntersector.h \
diff --git a/include/geos/noding/SegmentNode.h b/include/geos/noding/SegmentNode.h
index fd24425..3869475 100644
--- a/include/geos/noding/SegmentNode.h
+++ b/include/geos/noding/SegmentNode.h
@@ -124,4 +124,8 @@ struct GEOS_DLL  SegmentNodeLT {
 } // namespace geos.noding
 } // namespace geos
 
+#ifdef GEOS_INLINE
+# include "geos/noding/SegmentNode.inl"
+#endif
+
 #endif // GEOS_NODING_SEGMENTNODE_H
diff --git a/src/noding/SegmentNode.cpp b/include/geos/noding/SegmentNode.inl
similarity index 66%
copy from src/noding/SegmentNode.cpp
copy to include/geos/noding/SegmentNode.inl
index 8f9c306..a70f18b 100644
--- a/src/noding/SegmentNode.cpp
+++ b/include/geos/noding/SegmentNode.inl
@@ -4,10 +4,9 @@
  * http://geos.osgeo.org
  *
  * Copyright (C) 2006      Refractions Research Inc.
- * Copyright (C) 2001-2002 Vivid Solutions Inc.
  *
  * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU Lesser General Licence as published
+ * the terms of the GNU Lesser General Public Licence as published
  * by the Free Software Foundation.
  * See the COPYING file for more information.
  *
@@ -17,45 +16,17 @@
  *
  **********************************************************************/
 
-#ifndef GEOS_DEBUG
-#define GEOS_DEBUG 0
-#endif
-
-#include <iostream>
-#include <sstream>
-#include <iomanip>
+#ifndef GEOS_NODING_SEGMENTNODE_INL
+#define GEOS_NODING_SEGMENTNODE_INL
 
 #include <geos/noding/SegmentNode.h>
-#include <geos/noding/SegmentPointComparator.h>
-#include <geos/noding/NodedSegmentString.h>
 #include <geos/geom/Coordinate.h>
-
-
-using namespace geos::geom;
+#include <geos/noding/SegmentPointComparator.h>
 
 namespace geos {
-namespace noding { // geos.noding
-
-
-/*public*/
-SegmentNode::SegmentNode(const NodedSegmentString& ss, const Coordinate& nCoord,
-                         std::size_t nSegmentIndex, int nSegmentOctant)
-    :
-    segString(&ss),
-    segmentOctant(nSegmentOctant),
-    coord(nCoord),
-    segmentIndex(nSegmentIndex)
-{
-    // Number of points in NodedSegmentString is one-more number of segments
-    assert(segmentIndex < segString->size());
+namespace noding {
 
-    isInteriorVar = \
-                    !coord.equals2D(segString->getCoordinate(segmentIndex));
-
-}
-
-
-bool
+INLINE bool
 SegmentNode::isEndPoint(unsigned int maxSegmentIndex) const
 {
     if(segmentIndex == 0 && ! isInteriorVar) {
@@ -72,7 +43,7 @@ SegmentNode::isEndPoint(unsigned int maxSegmentIndex) const
  * @return 0 this EdgeIntersection is at the argument location
  * @return 1 this EdgeIntersection is located after the argument location
  */
-int
+INLINE int
 SegmentNode::compareTo(const SegmentNode& other) const
 {
     if(segmentIndex < other.segmentIndex) {
@@ -110,12 +81,10 @@ SegmentNode::compareTo(const SegmentNode& other) const
                                            other.coord);
 }
 
-std::ostream&
-operator<< (std::ostream& os, const SegmentNode& n)
-{
-    return os << n.coord << " seg#=" << n.segmentIndex << " octant#=" << n.segmentOctant << std::endl;
+
+
+}
 }
 
-} // namespace geos.noding
-} // namespace geos
+#endif
 
diff --git a/src/noding/SegmentNode.cpp b/src/noding/SegmentNode.cpp
index 8f9c306..2a4a7f7 100644
--- a/src/noding/SegmentNode.cpp
+++ b/src/noding/SegmentNode.cpp
@@ -26,7 +26,6 @@
 #include <iomanip>
 
 #include <geos/noding/SegmentNode.h>
-#include <geos/noding/SegmentPointComparator.h>
 #include <geos/noding/NodedSegmentString.h>
 #include <geos/geom/Coordinate.h>
 
@@ -36,81 +35,25 @@ using namespace geos::geom;
 namespace geos {
 namespace noding { // geos.noding
 
-
 /*public*/
-SegmentNode::SegmentNode(const NodedSegmentString& ss, const Coordinate& nCoord,
+SegmentNode::SegmentNode(const NodedSegmentString& ss, const geom::Coordinate& nCoord,
                          std::size_t nSegmentIndex, int nSegmentOctant)
-    :
-    segString(&ss),
-    segmentOctant(nSegmentOctant),
-    coord(nCoord),
-    segmentIndex(nSegmentIndex)
+        :
+        segString(&ss),
+        segmentOctant(nSegmentOctant),
+        coord(nCoord),
+        segmentIndex(nSegmentIndex)
 {
     // Number of points in NodedSegmentString is one-more number of segments
     assert(segmentIndex < segString->size());
 
     isInteriorVar = \
-                    !coord.equals2D(segString->getCoordinate(segmentIndex));
-
-}
+            !coord.equals2D(segString->getCoordinate(segmentIndex));
 
-
-bool
-SegmentNode::isEndPoint(unsigned int maxSegmentIndex) const
-{
-    if(segmentIndex == 0 && ! isInteriorVar) {
-        return true;
-    }
-    if(segmentIndex == maxSegmentIndex) {
-        return true;
-    }
-    return false;
 }
 
-/**
- * @return -1 this EdgeIntersection is located before the argument location
- * @return 0 this EdgeIntersection is at the argument location
- * @return 1 this EdgeIntersection is located after the argument location
- */
-int
-SegmentNode::compareTo(const SegmentNode& other) const
-{
-    if(segmentIndex < other.segmentIndex) {
-        return -1;
-    }
-    if(segmentIndex > other.segmentIndex) {
-        return 1;
-    }
-
-#if GEOS_DEBUG
-    std::cerr << setprecision(17) << "compareTo: " << *this << ", " << other << std::endl;
-#endif
 
-    if(coord.equals2D(other.coord)) {
-
-#if GEOS_DEBUG
-        std::cerr << " Coordinates equal!" << std::endl;
-#endif
-
-        return 0;
-    }
-
-#if GEOS_DEBUG
-    std::cerr << " Coordinates do not equal!" << std::endl;
-#endif
-
-    // an exterior node is the segment start point,
-    // so always sorts first
-    // this guards against a robustness problem
-    // where the octants are not reliable
-    if (! isInteriorVar) return -1;
-    if (! other.isInteriorVar) return 1;
-
-    return SegmentPointComparator::compare(segmentOctant, coord,
-                                           other.coord);
-}
-
-std::ostream&
+    std::ostream&
 operator<< (std::ostream& os, const SegmentNode& n)
 {
     return os << n.coord << " seg#=" << n.segmentIndex << " octant#=" << n.segmentOctant << std::endl;
@@ -119,3 +62,7 @@ operator<< (std::ostream& os, const SegmentNode& n)
 } // namespace geos.noding
 } // namespace geos
 
+#ifndef GEOS_INLINE
+# include "geos/noding/SegmentNode.inl"
+#endif
+

commit 4c1cf5ae2ad3a0702debca5c6130434e97ccf407
Author: Daniel Baston <dbaston at gmail.com>
Date:   Sat Dec 19 10:38:50 2020 -0500

    Avoid Coordinate copy in SnapRoundingNoder

diff --git a/include/geos/noding/snapround/SnapRoundingNoder.h b/include/geos/noding/snapround/SnapRoundingNoder.h
index 6e5d221..0b614e9 100644
--- a/include/geos/noding/snapround/SnapRoundingNoder.h
+++ b/include/geos/noding/snapround/SnapRoundingNoder.h
@@ -96,8 +96,6 @@ private:
     */
     void addIntersectionPixels(std::vector<SegmentString*>& segStrings);
 
-    void round(const geom::Coordinate& pt, geom::Coordinate& ptOut);
-
     /**
     * Gets a list of the rounded coordinates.
     * Duplicate (collapsed) coordinates are removed.
@@ -105,7 +103,7 @@ private:
     * @param pts the coordinates to round
     * @return array of rounded coordinates
     */
-    std::unique_ptr<std::vector<geom::Coordinate>> round(const std::vector<geom::Coordinate>& pts);
+    std::vector<geom::Coordinate> round(const std::vector<geom::Coordinate>& pts) const;
 
     /**
     * Computes new segment strings which are rounded and contain
diff --git a/src/noding/snapround/SnapRoundingNoder.cpp b/src/noding/snapround/SnapRoundingNoder.cpp
index 7e6daae..9e70c64 100644
--- a/src/noding/snapround/SnapRoundingNoder.cpp
+++ b/src/noding/snapround/SnapRoundingNoder.cpp
@@ -96,26 +96,14 @@ SnapRoundingNoder::addVertexPixels(std::vector<SegmentString*>& segStrings)
 }
 
 /*private*/
-void
-SnapRoundingNoder::round(const Coordinate& pt, Coordinate& ptOut)
-{
-    ptOut = pt;
-    pm->makePrecise(ptOut);
-    return;
-}
-
-/*private*/
-std::unique_ptr<std::vector<Coordinate>>
-SnapRoundingNoder::round(const std::vector<Coordinate>& pts)
+std::vector<Coordinate>
+SnapRoundingNoder::round(const std::vector<Coordinate>& pts) const
 {
-    std::unique_ptr<std::vector<Coordinate>> roundPts(new std::vector<Coordinate>);
-    roundPts->reserve(pts.size());
-    for (auto pt: pts) {
-        Coordinate ptOut;
-        round(pt, ptOut);
-        roundPts->push_back(ptOut);
+    std::vector<Coordinate> roundPts = pts;
+    for (auto& pt: roundPts) {
+        pm->makePrecise(pt);
     }
-    roundPts->erase(std::unique(roundPts->begin(), roundPts->end()), roundPts->end());
+    roundPts.erase(std::unique(roundPts.begin(), roundPts.end()), roundPts.end());
     return roundPts;
 }
 
@@ -158,8 +146,8 @@ SnapRoundingNoder::computeSegmentSnaps(NodedSegmentString* ss)
     * in preparation for snapping to the Hot Pixels
     */
     std::vector<Coordinate> pts = ss->getNodedCoordinates();
-    std::unique_ptr<std::vector<Coordinate>> ptsRoundVec = round(pts);
-    std::unique_ptr<geom::CoordinateArraySequence> ptsRound(new CoordinateArraySequence(ptsRoundVec.release()));
+    std::vector<Coordinate> ptsRoundVec = round(pts);
+    std::unique_ptr<geom::CoordinateArraySequence> ptsRound(new CoordinateArraySequence(std::move(ptsRoundVec)));
 
     // if complete collapse this edge can be eliminated
     if (ptsRound->size() <= 1)
@@ -177,8 +165,8 @@ SnapRoundingNoder::computeSegmentSnaps(NodedSegmentString* ss)
         * If the segment has collapsed completely, skip it
         */
         Coordinate p1 = pts[i+1];
-        Coordinate p1Round;
-        round(p1, p1Round);
+        Coordinate p1Round = p1;
+        pm->makePrecise(p1Round);
         if (p1Round.equals2D(currSnap))
             continue;
 

commit 9a9ba9eb13b5891f2d5d34bb8a6ae3d85140959d
Author: Daniel Baston <dbaston at gmail.com>
Date:   Sat Dec 19 10:29:05 2020 -0500

    Tidy SegmentNodeList

diff --git a/include/geos/noding/NodedSegmentString.h b/include/geos/noding/NodedSegmentString.h
index 27d75fb..bc28cbf 100644
--- a/include/geos/noding/NodedSegmentString.h
+++ b/include/geos/noding/NodedSegmentString.h
@@ -85,7 +85,7 @@ public:
     static SegmentString::NonConstVect* getNodedSubstrings(
         const SegmentString::NonConstVect& segStrings);
 
-    std::unique_ptr<std::vector<geom::Coordinate>> getNodedCoordinates();
+    std::vector<geom::Coordinate> getNodedCoordinates();
 
 
     /** \brief
diff --git a/include/geos/noding/SegmentNodeList.h b/include/geos/noding/SegmentNodeList.h
index 5762cf7..a8c1407 100644
--- a/include/geos/noding/SegmentNodeList.h
+++ b/include/geos/noding/SegmentNodeList.h
@@ -124,29 +124,28 @@ private:
     void findCollapsesFromInsertedNodes(
         std::vector<std::size_t>& collapsedVertexIndexes) const;
 
-    bool findCollapseIndex(const SegmentNode& ei0, const SegmentNode& ei1,
-                           size_t& collapsedVertexIndex) const;
+    static bool findCollapseIndex(const SegmentNode& ei0, const SegmentNode& ei1,
+                           size_t& collapsedVertexIndex);
 
     void addEdgeCoordinates(const SegmentNode* ei0, const SegmentNode* ei1, std::vector<geom::Coordinate>& coordList) const;
 
+public:
+
     // Declare type as noncopyable
     SegmentNodeList(const SegmentNodeList& other) = delete;
     SegmentNodeList& operator=(const SegmentNodeList& rhs) = delete;
 
-public:
-
     friend std::ostream& operator<< (std::ostream& os, const SegmentNodeList& l);
 
     using container = decltype(nodeMap);
+    using iterator = container::iterator;
+    using const_iterator = container::const_iterator;
 
-    typedef container::iterator iterator;
-    typedef container::const_iterator const_iterator;
+    explicit SegmentNodeList(const NodedSegmentString* newEdge): edge(*newEdge) {}
 
-    SegmentNodeList(const NodedSegmentString* newEdge): edge(*newEdge) {}
+    explicit SegmentNodeList(const NodedSegmentString& newEdge): edge(newEdge) {}
 
-    SegmentNodeList(const NodedSegmentString& newEdge): edge(newEdge) {}
-
-    ~SegmentNodeList();
+    ~SegmentNodeList() = default;
 
     const NodedSegmentString&
     getEdge() const
@@ -180,13 +179,25 @@ public:
         return nodeMap.size();
     }
 
-    iterator begin();
+    iterator begin() {
+        prepare();
+        return nodeMap.begin();
+    }
 
-    const_iterator begin() const;
+    const_iterator begin() const {
+        prepare();
+        return nodeMap.begin();
+    }
 
-    iterator end();
+    iterator end() {
+        prepare();
+        return nodeMap.end();
+    }
 
-    const_iterator end() const;
+    const_iterator end() const {
+        prepare();
+        return nodeMap.end();
+    }
 
     /**
      * Adds entries for the first and last points of the edge to the list
@@ -217,7 +228,7 @@ public:
     * @return an array of Coordinates
     *
     */
-    std::unique_ptr<std::vector<geom::Coordinate>> getSplitCoordinates();
+    std::vector<geom::Coordinate> getSplitCoordinates();
 
 
 };
diff --git a/src/noding/NodedSegmentString.cpp b/src/noding/NodedSegmentString.cpp
index 3855594..771ea65 100644
--- a/src/noding/NodedSegmentString.cpp
+++ b/src/noding/NodedSegmentString.cpp
@@ -133,7 +133,7 @@ NodedSegmentString::getNodedSubstrings(
 }
 
 /* public */
-std::unique_ptr<std::vector<Coordinate>>
+std::vector<Coordinate>
 NodedSegmentString::getNodedCoordinates() {
     return nodeList.getSplitCoordinates();
 }
diff --git a/src/noding/SegmentNodeList.cpp b/src/noding/SegmentNodeList.cpp
index 4c4d7af..739ecde 100644
--- a/src/noding/SegmentNodeList.cpp
+++ b/src/noding/SegmentNodeList.cpp
@@ -58,10 +58,6 @@ SegmentNodeList::add(const Coordinate& intPt, std::size_t segmentIndex)
     ready = false;
 }
 
-SegmentNodeList::~SegmentNodeList()
-{
-}
-
 void SegmentNodeList::prepare() const {
     if (!ready) {
         std::sort(nodeMap.begin(), nodeMap.end(), [](const SegmentNode& s1, const SegmentNode& s2) {
@@ -76,34 +72,6 @@ void SegmentNodeList::prepare() const {
     }
 }
 
-SegmentNodeList::iterator
-SegmentNodeList::begin()
-{
-    prepare();
-    return nodeMap.begin();
-}
-
-SegmentNodeList::const_iterator
-SegmentNodeList::begin() const
-{
-    prepare();
-    return nodeMap.begin();
-}
-
-SegmentNodeList::iterator
-SegmentNodeList::end()
-{
-    prepare();
-    return nodeMap.end();
-}
-
-SegmentNodeList::const_iterator
-SegmentNodeList::end() const
-{
-    prepare();
-    return nodeMap.end();
-}
-
 void
 SegmentNodeList::addEndpoints()
 {
@@ -174,7 +142,7 @@ SegmentNodeList::findCollapsesFromInsertedNodes(
 /* private */
 bool
 SegmentNodeList::findCollapseIndex(const SegmentNode& ei0, const SegmentNode& ei1,
-                                   size_t& collapsedVertexIndex) const
+                                   size_t& collapsedVertexIndex)
 {
     assert(ei1.segmentIndex >= ei0.segmentIndex);
     // only looking for equal nodes
@@ -215,11 +183,11 @@ SegmentNodeList::addSplitEdges(std::vector<SegmentString*>& edgeList)
 
     // there should always be at least two entries in the list
     // since the endpoints are nodes
-    iterator it = begin();
+    auto it = begin();
     const SegmentNode* eiPrev = &(*it);
     assert(eiPrev);
     ++it;
-    for(iterator itEnd = end(); it != itEnd; ++it) {
+    for(auto itEnd = end(); it != itEnd; ++it) {
         const SegmentNode* ei = &(*it);
         assert(ei);
 
@@ -313,23 +281,22 @@ SegmentNodeList::createSplitEdgePts(const SegmentNode* ei0, const SegmentNode* e
     if (useIntPt1) {
         pts.emplace_back(ei1->coord);
     }
-    return;
 }
 
 
 /*public*/
-std::unique_ptr<std::vector<Coordinate>>
+std::vector<Coordinate>
 SegmentNodeList::getSplitCoordinates()
 {
     // ensure that the list has entries for the first and last point of the edge
     addEndpoints();
-    std::unique_ptr<std::vector<Coordinate>> coordList(new std::vector<Coordinate>);
+    std::vector<Coordinate> coordList;
     // there should always be at least two entries in the list, since the endpoints are nodes
-    iterator it = begin();
+    auto it = begin();
     const SegmentNode* eiPrev = &(*it);
-    for(iterator itEnd = end(); it != itEnd; ++it) {
+    for(auto itEnd = end(); it != itEnd; ++it) {
         const SegmentNode* ei = &(*it);
-        addEdgeCoordinates(eiPrev, ei, *coordList);
+        addEdgeCoordinates(eiPrev, ei, coordList);
         eiPrev = ei;
     }
     return coordList;
diff --git a/src/noding/snapround/SnapRoundingNoder.cpp b/src/noding/snapround/SnapRoundingNoder.cpp
index 78363ea..7e6daae 100644
--- a/src/noding/snapround/SnapRoundingNoder.cpp
+++ b/src/noding/snapround/SnapRoundingNoder.cpp
@@ -157,8 +157,8 @@ SnapRoundingNoder::computeSegmentSnaps(NodedSegmentString* ss)
     * The coordinates are now rounded to the grid,
     * in preparation for snapping to the Hot Pixels
     */
-    std::unique_ptr<std::vector<Coordinate>> pts = ss->getNodedCoordinates();
-    std::unique_ptr<std::vector<Coordinate>> ptsRoundVec = round(*pts);
+    std::vector<Coordinate> pts = ss->getNodedCoordinates();
+    std::unique_ptr<std::vector<Coordinate>> ptsRoundVec = round(pts);
     std::unique_ptr<geom::CoordinateArraySequence> ptsRound(new CoordinateArraySequence(ptsRoundVec.release()));
 
     // if complete collapse this edge can be eliminated
@@ -169,20 +169,20 @@ SnapRoundingNoder::computeSegmentSnaps(NodedSegmentString* ss)
     NodedSegmentString* snapSS = new NodedSegmentString(ptsRound.release(), ss->getData());
 
     std::size_t snapSSindex = 0;
-    for (std::size_t i = 0, sz = pts->size()-1; i < sz; i++ ) {
+    for (std::size_t i = 0, sz = pts.size()-1; i < sz; i++ ) {
 
         const geom::Coordinate& currSnap = snapSS->getCoordinate(snapSSindex);
 
         /**
         * If the segment has collapsed completely, skip it
         */
-        Coordinate p1 = (*pts)[i+1];
+        Coordinate p1 = pts[i+1];
         Coordinate p1Round;
         round(p1, p1Round);
         if (p1Round.equals2D(currSnap))
             continue;
 
-        Coordinate p0 = (*pts)[i];
+        Coordinate p0 = pts[i];
 
         /**
         * Add any Hot Pixel intersections with *original* segment to rounded segment.

commit 67cc8f7aac2531b6a4f5e970d9d85cb9bd2659e2
Author: Daniel Baston <dbaston at gmail.com>
Date:   Fri Dec 18 20:42:08 2020 -0500

    Store SegmentNode in std::vector instead of std::map
    
    Provides a roughly 5-percent performance gain.

diff --git a/include/geos/noding/SegmentNode.h b/include/geos/noding/SegmentNode.h
index 88bb674..fd24425 100644
--- a/include/geos/noding/SegmentNode.h
+++ b/include/geos/noding/SegmentNode.h
@@ -46,16 +46,12 @@ namespace noding { // geos.noding
  */
 class GEOS_DLL SegmentNode {
 private:
-    const NodedSegmentString& segString;
+    const NodedSegmentString* segString;
 
     int segmentOctant;
 
     bool isInteriorVar;
 
-    // Declare type as noncopyable
-    SegmentNode(const SegmentNode& other) = delete;
-    SegmentNode& operator=(const SegmentNode& rhs) = delete;
-
 public:
     friend std::ostream& operator<< (std::ostream& os, const SegmentNode& n);
 
diff --git a/include/geos/noding/SegmentNodeList.h b/include/geos/noding/SegmentNodeList.h
index 4ce01c2..5762cf7 100644
--- a/include/geos/noding/SegmentNodeList.h
+++ b/include/geos/noding/SegmentNodeList.h
@@ -55,7 +55,14 @@ namespace noding { // geos::noding
  */
 class GEOS_DLL SegmentNodeList {
 private:
-    std::set<SegmentNode, SegmentNodeLT> nodeMap;
+    // Since we are adding frequently to the SegmentNodeList and iterating infrequently,
+    // it is faster to store all the SegmentNodes in a vector and sort/remove duplicates
+    // before iteration, rather than storing them in a set and continuously maintaining
+    // a sorted order.
+    mutable std::vector<SegmentNode> nodeMap;
+    mutable bool ready = false;
+
+    void prepare() const;
 
     // the parent edge
     const NodedSegmentString& edge;
@@ -169,29 +176,17 @@ public:
     size_t
     size() const
     {
+        prepare();
         return nodeMap.size();
     }
 
-    container::iterator
-    begin()
-    {
-        return nodeMap.begin();
-    }
-    container::const_iterator
-    begin() const
-    {
-        return nodeMap.begin();
-    }
-    container::iterator
-    end()
-    {
-        return nodeMap.end();
-    }
-    container::const_iterator
-    end() const
-    {
-        return nodeMap.end();
-    }
+    iterator begin();
+
+    const_iterator begin() const;
+
+    iterator end();
+
+    const_iterator end() const;
 
     /**
      * Adds entries for the first and last points of the edge to the list
diff --git a/src/noding/SegmentNode.cpp b/src/noding/SegmentNode.cpp
index 83f663e..8f9c306 100644
--- a/src/noding/SegmentNode.cpp
+++ b/src/noding/SegmentNode.cpp
@@ -41,16 +41,16 @@ namespace noding { // geos.noding
 SegmentNode::SegmentNode(const NodedSegmentString& ss, const Coordinate& nCoord,
                          std::size_t nSegmentIndex, int nSegmentOctant)
     :
-    segString(ss),
+    segString(&ss),
     segmentOctant(nSegmentOctant),
     coord(nCoord),
     segmentIndex(nSegmentIndex)
 {
     // Number of points in NodedSegmentString is one-more number of segments
-    assert(segmentIndex < segString.size());
+    assert(segmentIndex < segString->size());
 
     isInteriorVar = \
-                    !coord.equals2D(segString.getCoordinate(segmentIndex));
+                    !coord.equals2D(segString->getCoordinate(segmentIndex));
 
 }
 
diff --git a/src/noding/SegmentNodeList.cpp b/src/noding/SegmentNodeList.cpp
index 516b0e0..4c4d7af 100644
--- a/src/noding/SegmentNodeList.cpp
+++ b/src/noding/SegmentNodeList.cpp
@@ -53,13 +53,57 @@ static Profiler* profiler = Profiler::instance();
 void
 SegmentNodeList::add(const Coordinate& intPt, std::size_t segmentIndex)
 {
-    nodeMap.emplace(edge, intPt, segmentIndex, edge.getSegmentOctant(segmentIndex));
+    SegmentNode sn(edge, intPt, segmentIndex, edge.getSegmentOctant(segmentIndex));
+    nodeMap.push_back(sn);
+    ready = false;
 }
 
 SegmentNodeList::~SegmentNodeList()
 {
 }
 
+void SegmentNodeList::prepare() const {
+    if (!ready) {
+        std::sort(nodeMap.begin(), nodeMap.end(), [](const SegmentNode& s1, const SegmentNode& s2) {
+            return s1.compareTo(s2) < 0;
+        });
+
+        nodeMap.erase(std::unique(nodeMap.begin(), nodeMap.end(), [](const SegmentNode& s1, const SegmentNode& s2) {
+            return s1.compareTo(s2) == 0;
+        }), nodeMap.end());
+
+        ready = true;
+    }
+}
+
+SegmentNodeList::iterator
+SegmentNodeList::begin()
+{
+    prepare();
+    return nodeMap.begin();
+}
+
+SegmentNodeList::const_iterator
+SegmentNodeList::begin() const
+{
+    prepare();
+    return nodeMap.begin();
+}
+
+SegmentNodeList::iterator
+SegmentNodeList::end()
+{
+    prepare();
+    return nodeMap.end();
+}
+
+SegmentNodeList::const_iterator
+SegmentNodeList::end() const
+{
+    prepare();
+    return nodeMap.end();
+}
+
 void
 SegmentNodeList::addEndpoints()
 {
@@ -112,10 +156,10 @@ SegmentNodeList::findCollapsesFromInsertedNodes(
 
     // there should always be at least two entries in the list,
     // since the endpoints are nodes
-    iterator it = begin();
+    auto it = begin();
     const SegmentNode* eiPrev = &(*it);
     ++it;
-    for(iterator itEnd = end(); it != itEnd; ++it) {
+    for(auto itEnd = end(); it != itEnd; ++it) {
         const SegmentNode* ei = &(*it);
         bool isCollapsed = findCollapseIndex(*eiPrev, *ei,
                                              collapsedVertexIndex);

commit 2cffa09cf3819a03c809eee23b69291ba05e4c39
Author: Daniel Baston <dbaston at gmail.com>
Date:   Tue Dec 8 20:40:51 2020 -0500

    Store SegmentNode values directly in SegmentNodeList
    
    SegmentNodeList went to great pains to create SegmentNodes with stable
    addresses so that pointers to the created SegmentNodes could be passed
    to callers. However, the returned pointers were never used. This commit
    simplifies SegmentNodeList by storing SegmentNodes directly in nodeMap.

diff --git a/include/geos/noding/NodedSegmentString.h b/include/geos/noding/NodedSegmentString.h
index d93bba9..27d75fb 100644
--- a/include/geos/noding/NodedSegmentString.h
+++ b/include/geos/noding/NodedSegmentString.h
@@ -111,39 +111,6 @@ public:
 
     ~NodedSegmentString() override = default;
 
-    /** \brief
-     * Adds an intersection node for a given point and segment to this segment string.
-     *
-     * If an intersection already exists for this exact location, the existing
-     * node will be returned.
-     *
-     * @param intPt the location of the intersection
-     * @param segmentIndex the index of the segment containing the intersection
-     * @return the intersection node for the point
-     */
-    SegmentNode*
-    addIntersectionNode(geom::Coordinate* intPt, std::size_t segmentIndex)
-    {
-        std::size_t normalizedSegmentIndex = segmentIndex;
-
-        // normalize the intersection point location
-        std::size_t nextSegIndex = normalizedSegmentIndex + 1;
-        if(nextSegIndex < size()) {
-            geom::Coordinate const& nextPt =
-                getCoordinate(nextSegIndex);
-
-            // Normalize segment index if intPt falls on vertex
-            // The check for point equality is 2D only - Z values are ignored
-            if(intPt->equals2D(nextPt)) {
-                normalizedSegmentIndex = nextSegIndex;
-            }
-        }
-
-        // Add the intersection point to edge intersection list.
-        SegmentNode* ei = getNodeList().add(*intPt, normalizedSegmentIndex);
-        return ei;
-    }
-
     SegmentNodeList& getNodeList();
 
     const SegmentNodeList& getNodeList() const;
diff --git a/include/geos/noding/SegmentNode.h b/include/geos/noding/SegmentNode.h
index dba6232..88bb674 100644
--- a/include/geos/noding/SegmentNode.h
+++ b/include/geos/noding/SegmentNode.h
@@ -103,7 +103,7 @@ public:
      * @return 1 this EdgeIntersection is located after the
      *           argument location
      */
-    int compareTo(const SegmentNode& other);
+    int compareTo(const SegmentNode& other) const;
 
     //string print() const;
 };
@@ -116,6 +116,12 @@ struct GEOS_DLL  SegmentNodeLT {
     {
         return s1->compareTo(*s2) < 0;
     }
+
+    bool
+    operator()(const SegmentNode& s1, const SegmentNode& s2) const
+    {
+        return s1.compareTo(s2) < 0;
+    }
 };
 
 
diff --git a/include/geos/noding/SegmentNodeList.h b/include/geos/noding/SegmentNodeList.h
index 80c46c6..4ce01c2 100644
--- a/include/geos/noding/SegmentNodeList.h
+++ b/include/geos/noding/SegmentNodeList.h
@@ -55,8 +55,7 @@ namespace noding { // geos::noding
  */
 class GEOS_DLL SegmentNodeList {
 private:
-    std::set<SegmentNode*, SegmentNodeLT> nodeMap;
-    std::deque<SegmentNode> nodeQue;
+    std::set<SegmentNode, SegmentNodeLT> nodeMap;
 
     // the parent edge
     const NodedSegmentString& edge;
@@ -131,7 +130,8 @@ public:
 
     friend std::ostream& operator<< (std::ostream& os, const SegmentNodeList& l);
 
-    typedef std::set<SegmentNode*, SegmentNodeLT> container;
+    using container = decltype(nodeMap);
+
     typedef container::iterator iterator;
     typedef container::const_iterator const_iterator;
 
@@ -157,23 +157,12 @@ public:
      * @param intPt the intersection Coordinate, will be copied
      * @param segmentIndex
      */
-    SegmentNode* add(const geom::Coordinate& intPt, std::size_t segmentIndex);
+    void add(const geom::Coordinate& intPt, std::size_t segmentIndex);
 
-    SegmentNode*
+    void
     add(const geom::Coordinate* intPt, std::size_t segmentIndex)
     {
-        return add(*intPt, segmentIndex);
-    }
-
-    /*
-     * returns the set of SegmentNodes
-     */
-    //replaces iterator()
-    // TODO: obsolete this function
-    std::set<SegmentNode*, SegmentNodeLT>*
-    getNodes()
-    {
-        return &nodeMap;
+        add(*intPt, segmentIndex);
     }
 
     /// Return the number of nodes in this list
diff --git a/src/noding/SegmentNode.cpp b/src/noding/SegmentNode.cpp
index 64732df..83f663e 100644
--- a/src/noding/SegmentNode.cpp
+++ b/src/noding/SegmentNode.cpp
@@ -73,7 +73,7 @@ SegmentNode::isEndPoint(unsigned int maxSegmentIndex) const
  * @return 1 this EdgeIntersection is located after the argument location
  */
 int
-SegmentNode::compareTo(const SegmentNode& other)
+SegmentNode::compareTo(const SegmentNode& other) const
 {
     if(segmentIndex < other.segmentIndex) {
         return -1;
diff --git a/src/noding/SegmentNodeList.cpp b/src/noding/SegmentNodeList.cpp
index bb52d39..516b0e0 100644
--- a/src/noding/SegmentNodeList.cpp
+++ b/src/noding/SegmentNodeList.cpp
@@ -50,25 +50,12 @@ static Profiler* profiler = Profiler::instance();
 #endif
 
 
-SegmentNode*
+void
 SegmentNodeList::add(const Coordinate& intPt, std::size_t segmentIndex)
 {
-    nodeQue.emplace_back(edge, intPt, segmentIndex, edge.getSegmentOctant(segmentIndex));
-    SegmentNode* eiNew = &(nodeQue.back());
-
-    std::pair<SegmentNodeList::iterator, bool> p = nodeMap.insert(eiNew);
-    if(p.second) {    // new SegmentNode inserted
-        return eiNew;
-    }
-    else {
-        // sanity check
-        assert(eiNew->coord.equals2D(intPt));
-        nodeQue.pop_back();
-        return *(p.first);
-    }
+    nodeMap.emplace(edge, intPt, segmentIndex, edge.getSegmentOctant(segmentIndex));
 }
 
-
 SegmentNodeList::~SegmentNodeList()
 {
 }
@@ -126,10 +113,10 @@ SegmentNodeList::findCollapsesFromInsertedNodes(
     // there should always be at least two entries in the list,
     // since the endpoints are nodes
     iterator it = begin();
-    SegmentNode* eiPrev = *it;
+    const SegmentNode* eiPrev = &(*it);
     ++it;
     for(iterator itEnd = end(); it != itEnd; ++it) {
-        SegmentNode* ei = *it;
+        const SegmentNode* ei = &(*it);
         bool isCollapsed = findCollapseIndex(*eiPrev, *ei,
                                              collapsedVertexIndex);
         if(isCollapsed) {
@@ -185,11 +172,11 @@ SegmentNodeList::addSplitEdges(std::vector<SegmentString*>& edgeList)
     // there should always be at least two entries in the list
     // since the endpoints are nodes
     iterator it = begin();
-    SegmentNode* eiPrev = *it;
+    const SegmentNode* eiPrev = &(*it);
     assert(eiPrev);
     ++it;
     for(iterator itEnd = end(); it != itEnd; ++it) {
-        SegmentNode* ei = *it;
+        const SegmentNode* ei = &(*it);
         assert(ei);
 
         if(! ei->compareTo(*eiPrev)) {
@@ -295,9 +282,9 @@ SegmentNodeList::getSplitCoordinates()
     std::unique_ptr<std::vector<Coordinate>> coordList(new std::vector<Coordinate>);
     // there should always be at least two entries in the list, since the endpoints are nodes
     iterator it = begin();
-    SegmentNode* eiPrev = *it;
+    const SegmentNode* eiPrev = &(*it);
     for(iterator itEnd = end(); it != itEnd; ++it) {
-        SegmentNode* ei = *it;
+        const SegmentNode* ei = &(*it);
         addEdgeCoordinates(eiPrev, ei, *coordList);
         eiPrev = ei;
     }
@@ -323,8 +310,8 @@ operator<< (std::ostream& os, const SegmentNodeList& nlist)
 {
     os << "Intersections: (" << nlist.nodeMap.size() << "):" << std::endl;
 
-    for(const SegmentNode* ei: nlist.nodeMap) {
-        os << " " << *ei;
+    for(const SegmentNode& ei: nlist.nodeMap) {
+        os << " " << ei;
     }
     return os;
 }

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

Summary of changes:
 include/geos/noding/Makefile.am                    |  3 +-
 include/geos/noding/NodedSegmentString.h           | 35 +---------
 include/geos/noding/SegmentNode.h                  | 18 +++--
 .../geos/noding/SegmentNode.inl                    | 55 ++++-----------
 include/geos/noding/SegmentNodeList.h              | 73 ++++++++++----------
 include/geos/noding/snapround/SnapRoundingNoder.h  |  4 +-
 src/noding/NodedSegmentString.cpp                  |  2 +-
 src/noding/SegmentNode.cpp                         | 79 ++++------------------
 src/noding/SegmentNodeList.cpp                     | 68 +++++++++----------
 src/noding/snapround/SnapRoundingNoder.cpp         | 40 ++++-------
 10 files changed, 123 insertions(+), 254 deletions(-)
 copy src/noding/SegmentNode.cpp => include/geos/noding/SegmentNode.inl (64%)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list