/src/geos/src/geom/Point.cpp
Line | Count | Source |
1 | | /********************************************************************** |
2 | | * |
3 | | * GEOS - Geometry Engine Open Source |
4 | | * http://geos.osgeo.org |
5 | | * |
6 | | * Copyright (C) 2011 Sandro Santilli <strk@kbt.io> |
7 | | * Copyright (C) 2001-2002 Vivid Solutions Inc. |
8 | | * Copyright (C) 2005 2006 Refractions Research Inc. |
9 | | * |
10 | | * This is free software; you can redistribute and/or modify it under |
11 | | * the terms of the GNU Lesser General Public Licence as published |
12 | | * by the Free Software Foundation. |
13 | | * See the COPYING file for more information. |
14 | | * |
15 | | ********************************************************************** |
16 | | * |
17 | | * Last port: geom/Point.java r320 (JTS-1.12) |
18 | | * |
19 | | **********************************************************************/ |
20 | | |
21 | | #include <geos/util/UnsupportedOperationException.h> |
22 | | #include <geos/util/IllegalArgumentException.h> |
23 | | #include <geos/geom/Coordinate.h> |
24 | | #include <geos/geom/Point.h> |
25 | | #include <geos/geom/CoordinateSequence.h> |
26 | | #include <geos/geom/CoordinateSequenceFilter.h> |
27 | | #include <geos/geom/CoordinateFilter.h> |
28 | | #include <geos/geom/GeometryFilter.h> |
29 | | #include <geos/geom/GeometryComponentFilter.h> |
30 | | #include <geos/geom/Dimension.h> |
31 | | #include <geos/geom/Envelope.h> |
32 | | #include <geos/geom/GeometryCollection.h> |
33 | | #include <geos/geom/GeometryFactory.h> |
34 | | #include <geos/util.h> |
35 | | |
36 | | #include <string> |
37 | | #include <memory> |
38 | | |
39 | | namespace geos { |
40 | | namespace geom { // geos::geom |
41 | | |
42 | | |
43 | | |
44 | | /*protected*/ |
45 | | Point::Point(CoordinateSequence&& newCoords, const GeometryFactory* factory) |
46 | 11.6k | : Geometry(factory) |
47 | 11.6k | , coordinates(newCoords) |
48 | 11.6k | , envelope(computeEnvelopeInternal()) |
49 | 11.6k | { |
50 | 11.6k | if (coordinates.getSize() > 1) { |
51 | 2 | throw util::IllegalArgumentException("Point coordinate list must contain a single element"); |
52 | 2 | } |
53 | 11.6k | } |
54 | | |
55 | | Point::Point(const Coordinate & c, const GeometryFactory* factory) |
56 | 5.92M | : Geometry(factory) |
57 | 5.92M | , coordinates{c} |
58 | 5.92M | , envelope(c) |
59 | 5.92M | { |
60 | 5.92M | } |
61 | | |
62 | | Point::Point(const CoordinateXY & c, const GeometryFactory* factory) |
63 | 1 | : Geometry(factory) |
64 | 1 | , coordinates{c} |
65 | 1 | , envelope(c) |
66 | 1 | { |
67 | 1 | } |
68 | | |
69 | | Point::Point(const CoordinateXYM & c, const GeometryFactory* factory) |
70 | 0 | : Geometry(factory) |
71 | 0 | , coordinates{c} |
72 | 0 | , envelope(c) |
73 | 0 | { |
74 | 0 | } |
75 | | |
76 | | Point::Point(const CoordinateXYZM & c, const GeometryFactory* factory) |
77 | 3.89M | : Geometry(factory) |
78 | | // check Z and M values because we may be constructing this from |
79 | | // an XYM coordinate that was stored as XYZM |
80 | 3.89M | , coordinates{1u, !std::isnan(c.z), !std::isnan(c.m), false} |
81 | 3.89M | , envelope(c) |
82 | 3.89M | { |
83 | 3.89M | coordinates.setAt(c, 0); |
84 | 3.89M | } |
85 | | |
86 | | /*protected*/ |
87 | | Point::Point(const Point& p) |
88 | 14.9M | : Geometry(p) |
89 | 14.9M | , coordinates(p.coordinates) |
90 | 14.9M | , envelope(p.envelope) |
91 | 14.9M | {} |
92 | | |
93 | | std::unique_ptr<CoordinateSequence> |
94 | | Point::getCoordinates() const |
95 | 0 | { |
96 | 0 | return getCoordinatesRO()->clone(); |
97 | 0 | } |
98 | | |
99 | | std::size_t |
100 | | Point::getNumPoints() const |
101 | 13.0M | { |
102 | 13.0M | return coordinates.size(); |
103 | 13.0M | } |
104 | | |
105 | | bool |
106 | | Point::isEmpty() const |
107 | 11.0M | { |
108 | 11.0M | return coordinates.isEmpty(); |
109 | 11.0M | } |
110 | | |
111 | | bool |
112 | | Point::isSimple() const |
113 | 0 | { |
114 | 0 | return true; |
115 | 0 | } |
116 | | |
117 | | Dimension::DimensionType |
118 | | Point::getDimension() const |
119 | 50.5M | { |
120 | 50.5M | return Dimension::P; // point |
121 | 50.5M | } |
122 | | |
123 | | uint8_t |
124 | | Point::getCoordinateDimension() const |
125 | 1.51M | { |
126 | 1.51M | return (uint8_t) getCoordinatesRO()->getDimension(); |
127 | 1.51M | } |
128 | | |
129 | | bool |
130 | | Point::hasM() const |
131 | 16.8M | { |
132 | 16.8M | return getCoordinatesRO()->hasM(); |
133 | 16.8M | } |
134 | | |
135 | | bool |
136 | | Point::hasZ() const |
137 | 16.8M | { |
138 | 16.8M | return getCoordinatesRO()->hasZ(); |
139 | 16.8M | } |
140 | | |
141 | | int |
142 | | Point::getBoundaryDimension() const |
143 | 0 | { |
144 | 0 | return Dimension::False; |
145 | 0 | } |
146 | | |
147 | | double |
148 | | Point::getX() const |
149 | 0 | { |
150 | 0 | if(isEmpty()) { |
151 | 0 | throw util::UnsupportedOperationException("getX called on empty Point\n"); |
152 | 0 | } |
153 | 0 | return getCoordinate()->x; |
154 | 0 | } |
155 | | |
156 | | double |
157 | | Point::getY() const |
158 | 0 | { |
159 | 0 | if(isEmpty()) { |
160 | 0 | throw util::UnsupportedOperationException("getY called on empty Point\n"); |
161 | 0 | } |
162 | 0 | return getCoordinate()->y; |
163 | 0 | } |
164 | | |
165 | | double |
166 | | Point::getZ() const |
167 | 0 | { |
168 | 0 | if(isEmpty()) { |
169 | 0 | throw util::UnsupportedOperationException("getZ called on empty Point\n"); |
170 | 0 | } |
171 | 0 | return coordinates.getOrdinate(0, CoordinateSequence::Z); |
172 | 0 | } |
173 | | |
174 | | double |
175 | | Point::getM() const |
176 | 0 | { |
177 | 0 | if(isEmpty()) { |
178 | 0 | throw util::UnsupportedOperationException("getM called on empty Point\n"); |
179 | 0 | } |
180 | 0 | return coordinates.getOrdinate(0, CoordinateSequence::M); |
181 | 0 | } |
182 | | |
183 | | std::string |
184 | | Point::getGeometryType() const |
185 | 5 | { |
186 | 5 | return "Point"; |
187 | 5 | } |
188 | | |
189 | | std::unique_ptr<Geometry> |
190 | | Point::getBoundary() const |
191 | 0 | { |
192 | 0 | return getFactory()->createGeometryCollection(); |
193 | 0 | } |
194 | | |
195 | | Envelope |
196 | | Point::computeEnvelopeInternal() const |
197 | 11.6k | { |
198 | 11.6k | if(isEmpty()) { |
199 | 4.74k | return Envelope(); |
200 | 4.74k | } |
201 | | |
202 | 6.91k | return Envelope(*getCoordinate()); |
203 | 11.6k | } |
204 | | |
205 | | void |
206 | | Point::apply_ro(CoordinateFilter* filter) const |
207 | 13.0M | { |
208 | 13.0M | coordinates.apply_ro(filter); |
209 | 13.0M | } |
210 | | |
211 | | void |
212 | | Point::apply_rw(const CoordinateFilter* filter) |
213 | 506k | { |
214 | 506k | coordinates.apply_rw(filter); |
215 | 506k | } |
216 | | |
217 | | void |
218 | | Point::apply_rw(GeometryFilter* filter) |
219 | 0 | { |
220 | 0 | filter->filter_rw(this); |
221 | 0 | } |
222 | | |
223 | | void |
224 | | Point::apply_ro(GeometryFilter* filter) const |
225 | 20.9M | { |
226 | 20.9M | filter->filter_ro(this); |
227 | 20.9M | } |
228 | | |
229 | | void |
230 | | Point::apply_rw(GeometryComponentFilter* filter) |
231 | 0 | { |
232 | 0 | filter->filter_rw(this); |
233 | 0 | } |
234 | | |
235 | | void |
236 | | Point::apply_ro(GeometryComponentFilter* filter) const |
237 | 197k | { |
238 | 197k | filter->filter_ro(this); |
239 | 197k | } |
240 | | |
241 | | void |
242 | | Point::apply_rw(CoordinateSequenceFilter& filter) |
243 | 0 | { |
244 | 0 | if(isEmpty()) { |
245 | 0 | return; |
246 | 0 | } |
247 | 0 | filter.filter_rw(coordinates, 0); |
248 | 0 | if(filter.isGeometryChanged()) { |
249 | 0 | geometryChanged(); |
250 | 0 | } |
251 | 0 | } |
252 | | |
253 | | void |
254 | | Point::apply_ro(CoordinateSequenceFilter& filter) const |
255 | 430k | { |
256 | 430k | if(isEmpty()) { |
257 | 77 | return; |
258 | 77 | } |
259 | 430k | filter.filter_ro(coordinates, 0); |
260 | 430k | } |
261 | | |
262 | | bool |
263 | | Point::equalsExact(const Geometry* other, double tolerance) const |
264 | 0 | { |
265 | 0 | if(!isEquivalentClass(other)) { |
266 | 0 | return false; |
267 | 0 | } |
268 | | |
269 | | // assume the isEquivalentClass would return false |
270 | | // if other is not a point |
271 | 0 | assert(dynamic_cast<const Point*>(other)); |
272 | |
|
273 | 0 | if(isEmpty()) { |
274 | 0 | return other->isEmpty(); |
275 | 0 | } |
276 | 0 | else if(other->isEmpty()) { |
277 | 0 | return false; |
278 | 0 | } |
279 | | |
280 | 0 | const CoordinateXY* this_coord = getCoordinate(); |
281 | 0 | const CoordinateXY* other_coord = other->getCoordinate(); |
282 | | |
283 | | // assume the isEmpty checks above worked :) |
284 | 0 | assert(this_coord && other_coord); |
285 | |
|
286 | 0 | return equal(*this_coord, *other_coord, tolerance); |
287 | 0 | } |
288 | | |
289 | | bool |
290 | | Point::equalsIdentical(const Geometry* other) const |
291 | 0 | { |
292 | 0 | if(!isEquivalentClass(other)) { |
293 | 0 | return false; |
294 | 0 | } |
295 | | |
296 | 0 | return getCoordinatesRO()->equalsIdentical( |
297 | 0 | *static_cast<const Point*>(other)->getCoordinatesRO()); |
298 | 0 | } |
299 | | |
300 | | int |
301 | | Point::compareToSameClass(const Geometry* g) const |
302 | 0 | { |
303 | 0 | const Point* p = detail::down_cast<const Point*>(g); |
304 | 0 | return getCoordinate()->compareTo(*(p->getCoordinate())); |
305 | 0 | } |
306 | | |
307 | | GeometryTypeId |
308 | | Point::getGeometryTypeId() const |
309 | 29.1M | { |
310 | 29.1M | return GEOS_POINT; |
311 | 29.1M | } |
312 | | |
313 | | /*public*/ |
314 | | const CoordinateSequence* |
315 | | Point::getCoordinatesRO() const |
316 | 40.0M | { |
317 | 40.0M | return &coordinates; |
318 | 40.0M | } |
319 | | |
320 | | } // namespace geos::geom |
321 | | } // namespace geos |