/src/geos/src/geom/SimpleCurve.cpp
Line | Count | Source |
1 | | /********************************************************************** |
2 | | * |
3 | | * GEOS - Geometry Engine Open Source |
4 | | * http://geos.osgeo.org |
5 | | * |
6 | | * Copyright (C) 2001-2002 Vivid Solutions Inc. |
7 | | * Copyright (C) 2005 2006 Refractions Research Inc. |
8 | | * Copyright (C) 2011 Sandro Santilli <strk@kbt.io> |
9 | | * Copyright (C) 2024 ISciences, LLC |
10 | | * |
11 | | * This is free software; you can redistribute and/or modify it under |
12 | | * the terms of the GNU Lesser General Public Licence as published |
13 | | * by the Free Software Foundation. |
14 | | * See the COPYING file for more information. |
15 | | * |
16 | | **********************************************************************/ |
17 | | |
18 | | #include <geos/geom/SimpleCurve.h> |
19 | | |
20 | | #include <geos/algorithm/CircularArcs.h> |
21 | | #include <geos/algorithm/Orientation.h> |
22 | | #include <geos/geom/CoordinateFilter.h> |
23 | | #include <geos/geom/GeometryFactory.h> |
24 | | #include <geos/geom/GeometryFilter.h> |
25 | | #include <geos/operation/BoundaryOp.h> |
26 | | #include <geos/geom/CoordinateSequence.h> |
27 | | #include <geos/geom/CoordinateSequenceFilter.h> |
28 | | #include <geos/util.h> |
29 | | |
30 | | |
31 | | namespace geos { |
32 | | namespace geom { |
33 | | |
34 | | SimpleCurve::SimpleCurve(const SimpleCurve& other) |
35 | 4.87M | : Curve(other), |
36 | 4.87M | points(other.points->clone()), |
37 | 4.87M | envelope(other.envelope) |
38 | 4.87M | { |
39 | 4.87M | } |
40 | | |
41 | | SimpleCurve::SimpleCurve(const std::shared_ptr<const CoordinateSequence>& newCoords, |
42 | | bool isLinear, |
43 | | const GeometryFactory& factory) |
44 | 284k | : Curve(factory), |
45 | 284k | points(newCoords), |
46 | 284k | envelope(computeEnvelopeInternal(isLinear)) |
47 | 284k | { |
48 | 284k | } |
49 | | |
50 | | SimpleCurve::SimpleCurve(std::unique_ptr<CoordinateSequence>&& newCoords, |
51 | | bool isLinear, |
52 | | const GeometryFactory& factory) |
53 | 8.20M | : Curve(factory), |
54 | 8.20M | points(newCoords ? std::move(newCoords) : std::make_shared<CoordinateSequence>()), |
55 | 8.20M | envelope(computeEnvelopeInternal(isLinear)) |
56 | 8.20M | { |
57 | 8.20M | } |
58 | | |
59 | | void |
60 | | SimpleCurve::apply_ro(CoordinateFilter* filter) const |
61 | 450k | { |
62 | 450k | assert(points.get()); |
63 | 450k | points->apply_ro(filter); |
64 | 450k | } |
65 | | |
66 | | void |
67 | | SimpleCurve::apply_ro(CoordinateSequenceFilter& filter) const |
68 | 914k | { |
69 | 914k | std::size_t npts = points->size(); |
70 | 914k | if (!npts) { |
71 | 223k | return; |
72 | 223k | } |
73 | 3.02M | for (std::size_t i = 0; i < npts; ++i) { |
74 | 2.71M | filter.filter_ro(*points, i); |
75 | 2.71M | if (filter.isDone()) { |
76 | 379k | break; |
77 | 379k | } |
78 | 2.71M | } |
79 | 691k | } |
80 | | |
81 | | void |
82 | | SimpleCurve::apply_rw(const CoordinateFilter* filter) |
83 | 835k | { |
84 | 835k | assert(points.get()); |
85 | 835k | if (points.use_count() > 1) { |
86 | 0 | points = points->clone(); |
87 | 0 | } |
88 | 835k | const_cast<CoordinateSequence*>(points.get())->apply_rw(filter); |
89 | 835k | } |
90 | | |
91 | | void |
92 | | SimpleCurve::apply_rw(CoordinateSequenceFilter& filter) |
93 | 0 | { |
94 | 0 | if (points.use_count() > 1) { |
95 | 0 | points = points->clone(); |
96 | 0 | } |
97 | 0 | std::size_t npts = points->size(); |
98 | 0 | if (!npts) { |
99 | 0 | return; |
100 | 0 | } |
101 | 0 | for (std::size_t i = 0; i < npts; ++i) { |
102 | 0 | filter.filter_rw(const_cast<CoordinateSequence&>(*points), i); |
103 | 0 | if (filter.isDone()) { |
104 | 0 | break; |
105 | 0 | } |
106 | 0 | } |
107 | 0 | if (filter.isGeometryChanged()) { |
108 | 0 | geometryChanged(); |
109 | 0 | } |
110 | 0 | } |
111 | | |
112 | | int |
113 | | SimpleCurve::compareToSameClass(const Geometry* ls) const |
114 | 0 | { |
115 | 0 | const SimpleCurve* line = detail::down_cast<const SimpleCurve*>(ls); |
116 | | |
117 | | // MD - optimized implementation |
118 | 0 | std::size_t mynpts = points->getSize(); |
119 | 0 | std::size_t othnpts = line->points->getSize(); |
120 | 0 | if (mynpts > othnpts) { |
121 | 0 | return 1; |
122 | 0 | } |
123 | 0 | if (mynpts < othnpts) { |
124 | 0 | return -1; |
125 | 0 | } |
126 | 0 | for (std::size_t i = 0; i < mynpts; i++) { |
127 | 0 | int cmp = points->getAt<CoordinateXY>(i).compareTo(line->points->getAt<CoordinateXY>(i)); |
128 | 0 | if (cmp) { |
129 | 0 | return cmp; |
130 | 0 | } |
131 | 0 | } |
132 | 0 | return 0; |
133 | 0 | } |
134 | | |
135 | | Envelope |
136 | | SimpleCurve::computeEnvelopeInternal(bool isLinear) const |
137 | 8.48M | { |
138 | 8.48M | if (isEmpty()) { |
139 | 1.66M | return Envelope(); |
140 | 1.66M | } |
141 | | |
142 | 6.82M | if (isLinear) { |
143 | 6.51M | return points->getEnvelope(); |
144 | 6.51M | } |
145 | 306k | else { |
146 | 306k | Envelope e; |
147 | 964k | for (std::size_t i = 2; i < points->size(); i += 2) { |
148 | 657k | algorithm::CircularArcs::expandEnvelope(e, |
149 | 657k | points->getAt<CoordinateXY>(i-2), |
150 | 657k | points->getAt<CoordinateXY>(i-1), |
151 | 657k | points->getAt<CoordinateXY>(i)); |
152 | 657k | } |
153 | 306k | return e; |
154 | 306k | } |
155 | 6.82M | } |
156 | | |
157 | | bool |
158 | | SimpleCurve::equalsExact(const Geometry* other, double tolerance) const |
159 | 0 | { |
160 | 0 | if (!isEquivalentClass(other)) { |
161 | 0 | return false; |
162 | 0 | } |
163 | | |
164 | 0 | const SimpleCurve* otherCurve = detail::down_cast<const SimpleCurve*>(other); |
165 | 0 | std::size_t npts = points->getSize(); |
166 | 0 | if (npts != otherCurve->points->getSize()) { |
167 | 0 | return false; |
168 | 0 | } |
169 | 0 | for (std::size_t i = 0; i < npts; ++i) { |
170 | 0 | if (!equal(points->getAt<CoordinateXY>(i), otherCurve->points->getAt<CoordinateXY>(i), tolerance)) { |
171 | 0 | return false; |
172 | 0 | } |
173 | 0 | } |
174 | 0 | return true; |
175 | 0 | } |
176 | | |
177 | | bool |
178 | | SimpleCurve::equalsIdentical(const Geometry* other_g) const |
179 | 0 | { |
180 | 0 | if (!isEquivalentClass(other_g)) { |
181 | 0 | return false; |
182 | 0 | } |
183 | | |
184 | 0 | const auto& other = static_cast<const SimpleCurve&>(*other_g); |
185 | |
|
186 | 0 | if (envelope != other.envelope) { |
187 | 0 | return false; |
188 | 0 | } |
189 | | |
190 | 0 | return getCoordinatesRO()->equalsIdentical(*other.getCoordinatesRO()); |
191 | 0 | } |
192 | | |
193 | | std::unique_ptr<Geometry> |
194 | | SimpleCurve::getBoundary() const |
195 | 10.9k | { |
196 | 10.9k | operation::BoundaryOp bop(*this); |
197 | 10.9k | return bop.getBoundary(); |
198 | 10.9k | } |
199 | | |
200 | | const CoordinateXY* |
201 | | SimpleCurve::getCoordinate() const |
202 | 13.0k | { |
203 | 13.0k | if (isEmpty()) { |
204 | 0 | return nullptr; |
205 | 0 | } |
206 | 13.0k | return &(points->getAt<CoordinateXY>(0)); |
207 | 13.0k | } |
208 | | |
209 | | uint8_t |
210 | | SimpleCurve::getCoordinateDimension() const |
211 | 1.30M | { |
212 | 1.30M | return (uint8_t) points->getDimension(); |
213 | 1.30M | } |
214 | | |
215 | | const Coordinate& |
216 | | SimpleCurve::getCoordinateN(std::size_t n) const |
217 | 38.3k | { |
218 | 38.3k | assert(points.get()); |
219 | 38.3k | return points->getAt(n); |
220 | 38.3k | } |
221 | | |
222 | | std::unique_ptr<CoordinateSequence> |
223 | | SimpleCurve::getCoordinates() const |
224 | 38.5k | { |
225 | 38.5k | assert(points.get()); |
226 | 38.5k | return points->clone(); |
227 | 38.5k | } |
228 | | |
229 | | const CoordinateSequence* |
230 | | SimpleCurve::getCoordinatesRO() const |
231 | 7.88M | { |
232 | 7.88M | assert(nullptr != points.get()); |
233 | 7.88M | return points.get(); |
234 | 7.88M | } |
235 | | |
236 | | const std::shared_ptr<const CoordinateSequence>& |
237 | | SimpleCurve::getSharedCoordinates() const |
238 | 4.35M | { |
239 | 4.35M | assert(nullptr != points.get()); |
240 | 4.35M | return points; |
241 | 4.35M | } |
242 | | |
243 | | const SimpleCurve* |
244 | | SimpleCurve::getCurveN(std::size_t) const |
245 | 162k | { |
246 | 162k | return this; |
247 | 162k | } |
248 | | |
249 | | const CoordinateXY& |
250 | | SimpleCurve::getEndCoordinate() const |
251 | 0 | { |
252 | 0 | if (isEmpty()) { |
253 | 0 | return CoordinateXY::getNull(); |
254 | 0 | } |
255 | 0 | return points->back<CoordinateXY>(); |
256 | 0 | } |
257 | | |
258 | | std::unique_ptr<Point> |
259 | | SimpleCurve::getEndPoint() const |
260 | 10.8k | { |
261 | 10.8k | if (isEmpty()) { |
262 | 0 | return nullptr; |
263 | 0 | } |
264 | 10.8k | return getPointN(getNumPoints() - 1); |
265 | 10.8k | } |
266 | | |
267 | | std::size_t |
268 | | SimpleCurve::getNumCurves() const |
269 | 326k | { |
270 | 326k | return isEmpty() ? 0 : 1; |
271 | 326k | } |
272 | | |
273 | | std::size_t |
274 | | SimpleCurve::getNumPoints() const |
275 | 264k | { |
276 | 264k | assert(points.get()); |
277 | 264k | return points->getSize(); |
278 | 264k | } |
279 | | |
280 | | std::unique_ptr<Point> |
281 | | SimpleCurve::getPointN(std::size_t n) const |
282 | 26.2k | { |
283 | 26.2k | assert(getFactory()); |
284 | 26.2k | assert(points.get()); |
285 | | |
286 | 26.2k | return points->applyAt(n, [this](const auto& c) { |
287 | 26.2k | return getFactory()->createPoint(c); |
288 | 26.2k | }); SimpleCurve.cpp:auto geos::geom::SimpleCurve::getPointN(unsigned long) const::$_0::operator()<geos::geom::Coordinate>(geos::geom::Coordinate const&) const Line | Count | Source | 286 | 22.0k | return points->applyAt(n, [this](const auto& c) { | 287 | 22.0k | return getFactory()->createPoint(c); | 288 | 22.0k | }); |
Unexecuted instantiation: SimpleCurve.cpp:auto geos::geom::SimpleCurve::getPointN(unsigned long) const::$_0::operator()<geos::geom::CoordinateXYM>(geos::geom::CoordinateXYM const&) const SimpleCurve.cpp:auto geos::geom::SimpleCurve::getPointN(unsigned long) const::$_0::operator()<geos::geom::CoordinateXYZM>(geos::geom::CoordinateXYZM const&) const Line | Count | Source | 286 | 4.22k | return points->applyAt(n, [this](const auto& c) { | 287 | 4.22k | return getFactory()->createPoint(c); | 288 | 4.22k | }); |
Unexecuted instantiation: SimpleCurve.cpp:auto geos::geom::SimpleCurve::getPointN(unsigned long) const::$_0::operator()<geos::geom::CoordinateXY>(geos::geom::CoordinateXY const&) const |
289 | 26.2k | } |
290 | | |
291 | | const CoordinateXY& |
292 | | SimpleCurve::getStartCoordinate() const |
293 | 0 | { |
294 | 0 | if (isEmpty()) { |
295 | 0 | return CoordinateXY::getNull(); |
296 | 0 | } |
297 | 0 | return points->front<CoordinateXY>(); |
298 | 0 | } |
299 | | |
300 | | std::unique_ptr<Point> |
301 | | SimpleCurve::getStartPoint() const |
302 | 10.8k | { |
303 | 10.8k | if (isEmpty()) { |
304 | 0 | return nullptr; |
305 | 0 | } |
306 | 10.8k | return getPointN(0); |
307 | 10.8k | } |
308 | | |
309 | | bool |
310 | | SimpleCurve::hasM() const |
311 | 4.30M | { |
312 | 4.30M | return points->hasM(); |
313 | 4.30M | } |
314 | | |
315 | | bool |
316 | | SimpleCurve::hasZ() const |
317 | 4.31M | { |
318 | 4.31M | return points->hasZ(); |
319 | 4.31M | } |
320 | | |
321 | | bool |
322 | | SimpleCurve::isClosed() const |
323 | 2.61M | { |
324 | 2.61M | if (isEmpty()) { |
325 | 248 | return false; |
326 | 248 | } |
327 | | |
328 | 2.61M | return points->front<CoordinateXY>().equals2D(points->back<CoordinateXY>()); |
329 | 2.61M | } |
330 | | |
331 | | bool |
332 | | SimpleCurve::isCoordinate(CoordinateXY& pt) const |
333 | 0 | { |
334 | 0 | assert(points.get()); |
335 | 0 | std::size_t npts = points->getSize(); |
336 | 0 | for (std::size_t i = 0; i < npts; i++) { |
337 | 0 | if (points->getAt<CoordinateXY>(i) == pt) { |
338 | 0 | return true; |
339 | 0 | } |
340 | 0 | } |
341 | 0 | return false; |
342 | 0 | } |
343 | | |
344 | | bool |
345 | | SimpleCurve::isEmpty() const |
346 | 34.9M | { |
347 | 34.9M | assert(points.get()); |
348 | 34.9M | return points->isEmpty(); |
349 | 34.9M | } |
350 | | |
351 | | std::unique_ptr<SimpleCurve> |
352 | | SimpleCurve::clone() const |
353 | 2.49k | { |
354 | 2.49k | return std::unique_ptr<SimpleCurve>(static_cast<SimpleCurve*>(cloneImpl())); |
355 | 2.49k | } |
356 | | |
357 | | std::unique_ptr<SimpleCurve> |
358 | | SimpleCurve::reverse() const |
359 | 146 | { |
360 | 146 | return std::unique_ptr<SimpleCurve>(static_cast<SimpleCurve*>(reverseImpl())); |
361 | 146 | } |
362 | | |
363 | | } // namespace geos::geom |
364 | | } // namespace geos |