@@ -31,35 +31,134 @@ namespace noding { // geos::noding
3131void
3232BoundaryChainNoder::computeNodes (std::vector<SegmentString*>* segStrings)
3333{
34- SegmentSet segSet;
35- std::vector<BoundarySegmentMap> bdySections;
36- bdySections.reserve (segStrings->size ());
37- addSegments (segStrings, segSet, bdySections);
38- markBoundarySegments (segSet);
39- chainList = extractChains (bdySections);
34+ SegmentSet boundarySegSet;
35+ std::vector<BoundaryChainMap> boundaryChains;
36+ boundaryChains.reserve (segStrings->size ());
37+ addSegments (segStrings, boundarySegSet, boundaryChains);
38+ markBoundarySegments (boundarySegSet);
39+ m_chainList = extractChains (boundaryChains);
40+
41+ Coordinate::UnorderedSet nodePts = findNodePts (m_chainList);
42+ if (!nodePts.empty ()) {
43+ std::vector<SegmentString*>* tmplist = nodeChains (m_chainList, nodePts);
44+ // At this point we have copied all the SegmentString*
45+ // we want to keep, so t container needs to go away and be replaced
46+ delete m_chainList;
47+ m_chainList = tmplist;
48+ }
49+ }
50+
51+ /* private */
52+ Coordinate::UnorderedSet
53+ BoundaryChainNoder::findNodePts (const std::vector<SegmentString*>* segStrings) const
54+ {
55+ Coordinate::UnorderedSet interiorVertices;
56+ Coordinate::UnorderedSet nodes;
57+ for (const SegmentString* ss : *segStrings) {
58+ // -- endpoints are nodes
59+ nodes.insert (ss->getCoordinate (0 ));
60+ nodes.insert (ss->getCoordinate (ss->size () - 1 ));
61+
62+ // -- check for duplicate interior points
63+ for (std::size_t i = 1 ; i < ss->size () - 1 ; i++) {
64+ const Coordinate& p = ss->getCoordinate (i);
65+ if (interiorVertices.find (p) != interiorVertices.end ()) {
66+ nodes.insert (p);
67+ }
68+ interiorVertices.insert (p);
69+ }
70+ }
71+ return nodes;
72+ }
73+
74+ /* private */
75+ std::vector<SegmentString*>*
76+ BoundaryChainNoder::nodeChains (
77+ const std::vector<SegmentString*>* chains,
78+ const Coordinate::UnorderedSet& nodePts)
79+ {
80+ std::vector<SegmentString*>* nodedChains = new std::vector<SegmentString*>();
81+ for (SegmentString* chain : *chains) {
82+ nodeChain (chain, nodePts, nodedChains);
83+ }
84+ return nodedChains;
85+ }
86+
87+
88+ /* private */
89+ void
90+ BoundaryChainNoder::nodeChain (
91+ SegmentString* chain,
92+ const Coordinate::UnorderedSet& nodePts,
93+ std::vector<SegmentString*>* nodedChains)
94+ {
95+ std::size_t start = 0 ;
96+ while (start < chain->size () - 1 ) {
97+ std::size_t end = findNodeIndex (chain, start, nodePts);
98+ // -- if no interior nodes found, keep original chain
99+ if (start == 0 && end == chain->size () - 1 ) {
100+ nodedChains->push_back (chain);
101+ return ;
102+ }
103+ nodedChains->push_back (substring (chain, start, end));
104+ start = end;
105+ }
106+ // We replaced this SegmentString with substrings,
107+ // and we are discarding the containing vector later
108+ // so get rid of this chain now
109+ delete chain;
110+ }
111+
112+ /* private static */
113+ BasicSegmentString*
114+ BoundaryChainNoder::substring (const SegmentString* segString, std::size_t start, std::size_t end)
115+ {
116+ // m_substrings.emplace_back(new CoordinateSequence());
117+ // CoordinateSequence* pts = m_substrings.back().get();
118+ CoordinateSequence* pts = new CoordinateSequence ();
119+ for (std::size_t i = start; i < end + 1 ; i++) {
120+ pts->add (segString->getCoordinate (i));
121+ }
122+ return new BasicSegmentString (pts, segString->getData ());
40123}
41124
125+
126+ /* private */
127+ std::size_t
128+ BoundaryChainNoder::findNodeIndex (
129+ const SegmentString* chain,
130+ std::size_t start,
131+ const Coordinate::UnorderedSet& nodePts) const
132+ {
133+ for (std::size_t i = start + 1 ; i < chain->size (); i++) {
134+ if (nodePts.find (chain->getCoordinate (i)) != nodePts.end ())
135+ return i;
136+ }
137+ return chain->size () - 1 ;
138+ }
139+
140+
42141/* public */
43142std::vector<SegmentString*>*
44143BoundaryChainNoder::getNodedSubstrings () const
45144{
46- return chainList ;
145+ return m_chainList ;
47146}
48147
49148/* private */
50149void
51150BoundaryChainNoder::addSegments (
52151 std::vector<SegmentString*>* segStrings,
53152 SegmentSet& segSet,
54- std::vector<BoundarySegmentMap >& includedSegs )
153+ std::vector<BoundaryChainMap >& boundaryChains )
55154{
56155 for (SegmentString* ss : *segStrings) {
57156 m_constructZ |= ss->getCoordinates ()->hasZ ();
58157 m_constructM |= ss->getCoordinates ()->hasM ();
59158
60- includedSegs .emplace_back (ss);
61- BoundarySegmentMap& segInclude = includedSegs .back ();
62- addSegments (ss, segInclude , segSet);
159+ boundaryChains .emplace_back (ss);
160+ BoundaryChainMap& chainMap = boundaryChains .back ();
161+ addSegments (ss, chainMap , segSet);
63162 }
64163}
65164
@@ -80,13 +179,13 @@ BoundaryChainNoder::segSetContains(SegmentSet& segSet, Segment& seg)
80179void
81180BoundaryChainNoder::addSegments (
82181 SegmentString* segString,
83- BoundarySegmentMap& segMap ,
182+ BoundaryChainMap& chainMap ,
84183 SegmentSet& segSet)
85184{
86185 const CoordinateSequence& segCoords = *segString->getCoordinates ();
87186
88187 for (std::size_t i = 0 ; i < segString->size () - 1 ; i++) {
89- Segment seg (segCoords,segMap , i);
188+ Segment seg (segCoords, chainMap , i);
90189 if (segSetContains (segSet, seg)) {
91190 segSet.erase (seg);
92191 }
@@ -102,19 +201,19 @@ void
102201BoundaryChainNoder::markBoundarySegments (SegmentSet& segSet)
103202{
104203 for (const Segment& seg : segSet) {
105- seg.markInBoundary ();
204+ seg.markBoundary ();
106205 }
107206}
108207
109208/* private */
110209std::vector<SegmentString*>*
111- BoundaryChainNoder::extractChains (std::vector<BoundarySegmentMap >& sections ) const
210+ BoundaryChainNoder::extractChains (std::vector<BoundaryChainMap >& boundaryChains ) const
112211{
113- std::vector<SegmentString*>* sectionList = new std::vector<SegmentString*>();
114- for (BoundarySegmentMap& sect : sections ) {
115- sect .createChains (*sectionList , m_constructZ, m_constructM);
212+ std::vector<SegmentString*>* chains = new std::vector<SegmentString*>();
213+ for (BoundaryChainMap& chainMap : boundaryChains ) {
214+ chainMap .createChains (*chains , m_constructZ, m_constructM);
116215 }
117- return sectionList ;
216+ return chains ;
118217}
119218
120219/* ************************************************************************
@@ -123,14 +222,14 @@ BoundaryChainNoder::extractChains(std::vector<BoundarySegmentMap>& sections) con
123222
124223/* public */
125224void
126- BoundaryChainNoder::BoundarySegmentMap ::setBoundarySegment (std::size_t index)
225+ BoundaryChainNoder::BoundaryChainMap ::setBoundarySegment (std::size_t index)
127226{
128227 isBoundary[index] = true ;
129228}
130229
131230/* public */
132231void
133- BoundaryChainNoder::BoundarySegmentMap ::createChains (
232+ BoundaryChainNoder::BoundaryChainMap ::createChains (
134233 std::vector<SegmentString*>& chains,
135234 bool constructZ,
136235 bool constructM)
@@ -149,7 +248,7 @@ BoundaryChainNoder::BoundarySegmentMap::createChains(
149248
150249/* private static */
151250SegmentString*
152- BoundaryChainNoder::BoundarySegmentMap ::createChain (
251+ BoundaryChainNoder::BoundaryChainMap ::createChain (
153252 const SegmentString* segString,
154253 std::size_t startIndex,
155254 std::size_t endIndex,
@@ -166,7 +265,7 @@ BoundaryChainNoder::BoundarySegmentMap::createChain(
166265
167266/* private */
168267std::size_t
169- BoundaryChainNoder::BoundarySegmentMap ::findChainStart (std::size_t index) const
268+ BoundaryChainNoder::BoundaryChainMap ::findChainStart (std::size_t index) const
170269{
171270 while (index < isBoundary.size () && ! isBoundary[index]) {
172271 index++;
@@ -176,7 +275,7 @@ BoundaryChainNoder::BoundarySegmentMap::findChainStart(std::size_t index) const
176275
177276/* private */
178277std::size_t
179- BoundaryChainNoder::BoundarySegmentMap ::findChainEnd (std::size_t index) const
278+ BoundaryChainNoder::BoundaryChainMap ::findChainEnd (std::size_t index) const
180279{
181280 index++;
182281 while (index < isBoundary.size () && isBoundary[index]) {
0 commit comments