/src/geos/src/simplify/LinkedLine.cpp
Line | Count | Source |
1 | | /********************************************************************** |
2 | | * |
3 | | * GEOS - Geometry Engine Open Source |
4 | | * http://geos.osgeo.org |
5 | | * |
6 | | * Copyright (C) 2022 Paul Ramsey <pramsey@cleverelephant.ca> |
7 | | * Copyright (c) 2022 Martin Davis. |
8 | | * |
9 | | * This is free software; you can redistribute and/or modify it under |
10 | | * the terms of the GNU Lesser General Public Licence as published |
11 | | * by the Free Software Foundation. |
12 | | * See the COPYING file for more information. |
13 | | * |
14 | | **********************************************************************/ |
15 | | |
16 | | #include <geos/simplify/LinkedLine.h> |
17 | | |
18 | | #include <geos/geom/Coordinate.h> |
19 | | #include <geos/geom/CoordinateSequence.h> |
20 | | #include <geos/io/WKTWriter.h> |
21 | | #include <geos/constants.h> |
22 | | |
23 | | using geos::geom::Coordinate; |
24 | | using geos::geom::CoordinateSequence; |
25 | | using geos::io::WKTWriter; |
26 | | |
27 | | |
28 | | namespace geos { |
29 | | namespace simplify { // geos.simplify |
30 | | |
31 | | |
32 | | LinkedLine::LinkedLine(const CoordinateSequence& pts) |
33 | 0 | : m_coord(pts) |
34 | 0 | , m_isRing(pts.isRing()) |
35 | 0 | , m_size(pts.isRing() ? pts.size() - 1 : pts.size()) |
36 | 0 | { |
37 | 0 | createNextLinks(m_size); |
38 | 0 | createPrevLinks(m_size); |
39 | 0 | } |
40 | | |
41 | | |
42 | | /* public */ |
43 | | bool |
44 | | LinkedLine::isRing() const |
45 | 0 | { |
46 | 0 | return m_isRing; |
47 | 0 | } |
48 | | |
49 | | /* public */ |
50 | | bool |
51 | | LinkedLine::isCorner(std::size_t i) const |
52 | 0 | { |
53 | 0 | if (! isRing() |
54 | 0 | && (i == 0 || i == m_coord.size() - 1)) |
55 | 0 | { |
56 | 0 | return false; |
57 | 0 | } |
58 | 0 | return true; |
59 | 0 | } |
60 | | |
61 | | /* private */ |
62 | | void |
63 | | LinkedLine::createNextLinks(std::size_t size) |
64 | 0 | { |
65 | 0 | m_next.resize(size); |
66 | 0 | for (std::size_t i = 0; i < size; i++) { |
67 | 0 | m_next[i] = i + 1; |
68 | 0 | } |
69 | 0 | m_next[size - 1] = m_isRing ? 0 : NO_COORD_INDEX; |
70 | 0 | return; |
71 | 0 | } |
72 | | |
73 | | /* private */ |
74 | | void |
75 | | LinkedLine::createPrevLinks(std::size_t size) |
76 | 0 | { |
77 | 0 | m_prev.resize(size); |
78 | 0 | for (std::size_t i = 1; i < size; i++) { |
79 | 0 | m_prev[i] = i - 1; |
80 | 0 | } |
81 | 0 | m_prev[0] = m_isRing ? size - 1 : NO_COORD_INDEX; |
82 | 0 | return; |
83 | 0 | } |
84 | | |
85 | | /* public */ |
86 | | std::size_t |
87 | | LinkedLine::size() const |
88 | 0 | { |
89 | 0 | return m_size; |
90 | 0 | } |
91 | | |
92 | | /* public */ |
93 | | std::size_t |
94 | | LinkedLine::next(std::size_t i) const |
95 | 0 | { |
96 | 0 | return m_next[i]; |
97 | 0 | } |
98 | | |
99 | | /* public */ |
100 | | std::size_t |
101 | | LinkedLine::prev(std::size_t i) const |
102 | 0 | { |
103 | 0 | return m_prev[i]; |
104 | 0 | } |
105 | | |
106 | | /* public */ |
107 | | const Coordinate& |
108 | | LinkedLine::getCoordinate(std::size_t index) const |
109 | 0 | { |
110 | 0 | return m_coord.getAt(index); |
111 | 0 | } |
112 | | |
113 | | /* public */ |
114 | | const Coordinate& |
115 | | LinkedLine::prevCoordinate(std::size_t index) const |
116 | 0 | { |
117 | 0 | return m_coord.getAt(prev(index)); |
118 | 0 | } |
119 | | |
120 | | /* public */ |
121 | | const Coordinate& |
122 | | LinkedLine::nextCoordinate(std::size_t index) const |
123 | 0 | { |
124 | 0 | return m_coord.getAt(next(index)); |
125 | 0 | } |
126 | | |
127 | | /* public */ |
128 | | bool |
129 | | LinkedLine::hasCoordinate(std::size_t index) const |
130 | 0 | { |
131 | | //-- if not a ring, endpoints are always present |
132 | 0 | if (! m_isRing && (index == 0 || index == m_coord.size() - 1)) |
133 | 0 | return true; |
134 | | |
135 | 0 | return index != NO_COORD_INDEX |
136 | 0 | && index < m_prev.size() |
137 | 0 | && m_prev[index] != NO_COORD_INDEX; |
138 | 0 | } |
139 | | |
140 | | /* public */ |
141 | | void |
142 | | LinkedLine::remove(std::size_t index) |
143 | 0 | { |
144 | 0 | std::size_t iprev = m_prev[index]; |
145 | 0 | std::size_t inext = m_next[index]; |
146 | 0 | if (iprev != NO_COORD_INDEX) |
147 | 0 | m_next[iprev] = inext; |
148 | 0 | if (inext != NO_COORD_INDEX) |
149 | 0 | m_prev[inext] = iprev; |
150 | 0 | m_prev[index] = NO_COORD_INDEX; |
151 | 0 | m_next[index] = NO_COORD_INDEX; |
152 | 0 | m_size = m_size > 0 ? m_size - 1 : m_size; |
153 | 0 | } |
154 | | |
155 | | /* public */ |
156 | | std::unique_ptr<CoordinateSequence> |
157 | | LinkedLine::getCoordinates() const |
158 | 0 | { |
159 | 0 | std::unique_ptr<CoordinateSequence> coords(new CoordinateSequence()); |
160 | 0 | std::size_t len = m_isRing ? m_coord.size() - 1 : m_coord.size(); |
161 | 0 | for (std::size_t i = 0; i < len; i++) { |
162 | 0 | if (hasCoordinate(i)) { |
163 | 0 | coords->add(m_coord.getAt(i), false); |
164 | 0 | } |
165 | 0 | } |
166 | 0 | if (m_isRing) { |
167 | 0 | coords->closeRing(); |
168 | 0 | } |
169 | 0 | return coords; |
170 | 0 | } |
171 | | |
172 | | std::ostream& |
173 | | operator<< (std::ostream& os, const LinkedLine& ll) |
174 | 0 | { |
175 | 0 | auto cs = ll.getCoordinates(); |
176 | 0 | os << WKTWriter::toLineString(*cs); |
177 | 0 | return os; |
178 | 0 | } |
179 | | |
180 | | |
181 | | |
182 | | } // namespace geos.simplify |
183 | | } // namespace geos |