/src/gdal/ogr/ogrpoint.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: OpenGIS Simple Features Reference Implementation |
4 | | * Purpose: The Point geometry class. |
5 | | * Author: Frank Warmerdam, warmerdam@pobox.com |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 1999, Frank Warmerdam |
9 | | * Copyright (c) 2008-2011, Even Rouault <even dot rouault at spatialys.com> |
10 | | * |
11 | | * SPDX-License-Identifier: MIT |
12 | | ****************************************************************************/ |
13 | | |
14 | | #include "cpl_port.h" |
15 | | #include "ogr_geometry.h" |
16 | | |
17 | | #include <cmath> |
18 | | #include <cstdio> |
19 | | #include <cstring> |
20 | | #include <algorithm> |
21 | | #include <limits> |
22 | | #include <new> |
23 | | |
24 | | #include "cpl_conv.h" |
25 | | #include "ogr_core.h" |
26 | | #include "ogr_p.h" |
27 | | #include "ogr_spatialref.h" |
28 | | |
29 | | /************************************************************************/ |
30 | | /* GetEmptyNonEmptyFlag() */ |
31 | | /************************************************************************/ |
32 | | |
33 | | static int GetEmptyNonEmptyFlag(double x, double y) |
34 | 124k | { |
35 | 124k | if (std::isnan(x) || std::isnan(y)) |
36 | 513 | return 0; |
37 | 124k | return OGRGeometry::OGR_G_NOT_EMPTY_POINT; |
38 | 124k | } |
39 | | |
40 | | /************************************************************************/ |
41 | | /* OGRPoint() */ |
42 | | /************************************************************************/ |
43 | | |
44 | | /** |
45 | | * \brief Create an empty point. |
46 | | */ |
47 | | |
48 | 34.1k | OGRPoint::OGRPoint() : x(0.0), y(0.0), z(0.0), m(0.0) |
49 | | |
50 | 34.1k | { |
51 | 34.1k | flags = 0; |
52 | 34.1k | } |
53 | | |
54 | | /************************************************************************/ |
55 | | /* OGRPoint() */ |
56 | | /************************************************************************/ |
57 | | |
58 | | /** |
59 | | * \brief Create a point. |
60 | | * @param xIn x |
61 | | * @param yIn y |
62 | | * @param zIn z |
63 | | */ |
64 | | |
65 | | OGRPoint::OGRPoint(double xIn, double yIn, double zIn) |
66 | 0 | : x(xIn), y(yIn), z(zIn), m(0.0) |
67 | 0 | { |
68 | 0 | flags = GetEmptyNonEmptyFlag(xIn, yIn) | OGR_G_3D; |
69 | 0 | } |
70 | | |
71 | | /************************************************************************/ |
72 | | /* OGRPoint() */ |
73 | | /************************************************************************/ |
74 | | |
75 | | /** |
76 | | * \brief Create a point. |
77 | | * @param xIn x |
78 | | * @param yIn y |
79 | | */ |
80 | | |
81 | 124k | OGRPoint::OGRPoint(double xIn, double yIn) : x(xIn), y(yIn), z(0.0), m(0.0) |
82 | 124k | { |
83 | 124k | flags = GetEmptyNonEmptyFlag(xIn, yIn); |
84 | 124k | } |
85 | | |
86 | | /************************************************************************/ |
87 | | /* OGRPoint() */ |
88 | | /************************************************************************/ |
89 | | |
90 | | /** |
91 | | * \brief Create a point. |
92 | | * @param xIn x |
93 | | * @param yIn y |
94 | | * @param zIn z |
95 | | * @param mIn m |
96 | | */ |
97 | | |
98 | | OGRPoint::OGRPoint(double xIn, double yIn, double zIn, double mIn) |
99 | 0 | : x(xIn), y(yIn), z(zIn), m(mIn) |
100 | 0 | { |
101 | 0 | flags = GetEmptyNonEmptyFlag(xIn, yIn) | OGR_G_3D | OGR_G_MEASURED; |
102 | 0 | } |
103 | | |
104 | | /************************************************************************/ |
105 | | /* createXYM() */ |
106 | | /************************************************************************/ |
107 | | |
108 | | /** |
109 | | * \brief Create a XYM point. |
110 | | * @param x x |
111 | | * @param y y |
112 | | * @param m m |
113 | | * @since GDAL 3.1 |
114 | | */ |
115 | | |
116 | | OGRPoint *OGRPoint::createXYM(double x, double y, double m) |
117 | 0 | { |
118 | 0 | auto p = new OGRPoint(x, y, 0, m); |
119 | 0 | p->flags &= ~OGR_G_3D; |
120 | 0 | return p; |
121 | 0 | } |
122 | | |
123 | | /************************************************************************/ |
124 | | /* OGRPoint( const OGRPoint& ) */ |
125 | | /************************************************************************/ |
126 | | |
127 | | /** |
128 | | * \brief Copy constructor. |
129 | | * |
130 | | * Note: before GDAL 2.1, only the default implementation of the constructor |
131 | | * existed, which could be unsafe to use. |
132 | | * |
133 | | * @since GDAL 2.1 |
134 | | */ |
135 | | |
136 | 0 | OGRPoint::OGRPoint(const OGRPoint &) = default; |
137 | | |
138 | | /************************************************************************/ |
139 | | /* operator=( const OGRPoint& ) */ |
140 | | /************************************************************************/ |
141 | | |
142 | | /** |
143 | | * \brief Assignment operator. |
144 | | * |
145 | | * Note: before GDAL 2.1, only the default implementation of the operator |
146 | | * existed, which could be unsafe to use. |
147 | | * |
148 | | * @since GDAL 2.1 |
149 | | */ |
150 | | |
151 | | OGRPoint &OGRPoint::operator=(const OGRPoint &other) |
152 | 0 | { |
153 | 0 | if (this != &other) |
154 | 0 | { |
155 | | // Slightly more efficient to avoid OGRGeometry::operator=(other); |
156 | | // but do what it does to avoid a call to empty() |
157 | 0 | assignSpatialReference(other.getSpatialReference()); |
158 | 0 | flags = other.flags; |
159 | |
|
160 | 0 | x = other.x; |
161 | 0 | y = other.y; |
162 | 0 | z = other.z; |
163 | 0 | m = other.m; |
164 | 0 | } |
165 | 0 | return *this; |
166 | 0 | } |
167 | | |
168 | | /************************************************************************/ |
169 | | /* clone() */ |
170 | | /* */ |
171 | | /* Make a new object that is a copy of this object. */ |
172 | | /************************************************************************/ |
173 | | |
174 | | OGRPoint *OGRPoint::clone() const |
175 | | |
176 | 0 | { |
177 | 0 | return new (std::nothrow) OGRPoint(*this); |
178 | 0 | } |
179 | | |
180 | | /************************************************************************/ |
181 | | /* empty() */ |
182 | | /************************************************************************/ |
183 | | void OGRPoint::empty() |
184 | | |
185 | 5.59k | { |
186 | 5.59k | x = 0.0; |
187 | 5.59k | y = 0.0; |
188 | 5.59k | z = 0.0; |
189 | 5.59k | m = 0.0; |
190 | 5.59k | flags &= ~OGR_G_NOT_EMPTY_POINT; |
191 | 5.59k | } |
192 | | |
193 | | /************************************************************************/ |
194 | | /* getDimension() */ |
195 | | /************************************************************************/ |
196 | | |
197 | | int OGRPoint::getDimension() const |
198 | | |
199 | 0 | { |
200 | 0 | return 0; |
201 | 0 | } |
202 | | |
203 | | /************************************************************************/ |
204 | | /* getGeometryType() */ |
205 | | /************************************************************************/ |
206 | | |
207 | | OGRwkbGeometryType OGRPoint::getGeometryType() const |
208 | | |
209 | 127k | { |
210 | 127k | if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED)) |
211 | 101k | return wkbPointZM; |
212 | 26.2k | else if (flags & OGR_G_MEASURED) |
213 | 1.81k | return wkbPointM; |
214 | 24.3k | else if (flags & OGR_G_3D) |
215 | 19.6k | return wkbPoint25D; |
216 | 4.72k | else |
217 | 4.72k | return wkbPoint; |
218 | 127k | } |
219 | | |
220 | | /************************************************************************/ |
221 | | /* getGeometryName() */ |
222 | | /************************************************************************/ |
223 | | |
224 | | const char *OGRPoint::getGeometryName() const |
225 | | |
226 | 4.88k | { |
227 | 4.88k | return "POINT"; |
228 | 4.88k | } |
229 | | |
230 | | /************************************************************************/ |
231 | | /* flattenTo2D() */ |
232 | | /************************************************************************/ |
233 | | |
234 | | void OGRPoint::flattenTo2D() |
235 | | |
236 | 0 | { |
237 | 0 | z = 0.0; |
238 | 0 | m = 0.0; |
239 | 0 | flags &= ~OGR_G_3D; |
240 | 0 | setMeasured(FALSE); |
241 | 0 | } |
242 | | |
243 | | /************************************************************************/ |
244 | | /* setCoordinateDimension() */ |
245 | | /************************************************************************/ |
246 | | |
247 | | bool OGRPoint::setCoordinateDimension(int nNewDimension) |
248 | | |
249 | 0 | { |
250 | 0 | if (nNewDimension == 2) |
251 | 0 | flattenTo2D(); |
252 | 0 | else if (nNewDimension == 3) |
253 | 0 | flags |= OGR_G_3D; |
254 | |
|
255 | 0 | setMeasured(FALSE); |
256 | 0 | return true; |
257 | 0 | } |
258 | | |
259 | | /************************************************************************/ |
260 | | /* WkbSize() */ |
261 | | /* */ |
262 | | /* Return the size of this object in well known binary */ |
263 | | /* representation including the byte order, and type information. */ |
264 | | /************************************************************************/ |
265 | | |
266 | | size_t OGRPoint::WkbSize() const |
267 | | |
268 | 0 | { |
269 | 0 | if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED)) |
270 | 0 | return 37; |
271 | 0 | else if ((flags & OGR_G_3D) || (flags & OGR_G_MEASURED)) |
272 | 0 | return 29; |
273 | 0 | else |
274 | 0 | return 21; |
275 | 0 | } |
276 | | |
277 | | /************************************************************************/ |
278 | | /* importFromWkb() */ |
279 | | /* */ |
280 | | /* Initialize from serialized stream in well known binary */ |
281 | | /* format. */ |
282 | | /************************************************************************/ |
283 | | |
284 | | OGRErr OGRPoint::importFromWkb(const unsigned char *pabyData, size_t nSize, |
285 | | OGRwkbVariant eWkbVariant, |
286 | | size_t &nBytesConsumedOut) |
287 | | |
288 | 0 | { |
289 | 0 | nBytesConsumedOut = 0; |
290 | 0 | OGRwkbByteOrder eByteOrder = wkbNDR; |
291 | |
|
292 | 0 | flags = 0; |
293 | 0 | OGRErr eErr = |
294 | 0 | importPreambleFromWkb(pabyData, nSize, eByteOrder, eWkbVariant); |
295 | 0 | pabyData += 5; |
296 | 0 | if (eErr != OGRERR_NONE) |
297 | 0 | return eErr; |
298 | | |
299 | 0 | if (nSize != static_cast<size_t>(-1)) |
300 | 0 | { |
301 | 0 | if ((nSize < 37) && ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED))) |
302 | 0 | return OGRERR_NOT_ENOUGH_DATA; |
303 | 0 | else if ((nSize < 29) && |
304 | 0 | ((flags & OGR_G_3D) || (flags & OGR_G_MEASURED))) |
305 | 0 | return OGRERR_NOT_ENOUGH_DATA; |
306 | 0 | else if (nSize < 21) |
307 | 0 | return OGRERR_NOT_ENOUGH_DATA; |
308 | 0 | } |
309 | | |
310 | 0 | nBytesConsumedOut = 5 + 8 * (2 + ((flags & OGR_G_3D) ? 1 : 0) + |
311 | 0 | ((flags & OGR_G_MEASURED) ? 1 : 0)); |
312 | | |
313 | | /* -------------------------------------------------------------------- */ |
314 | | /* Get the vertex. */ |
315 | | /* -------------------------------------------------------------------- */ |
316 | 0 | memcpy(&x, pabyData, 8); |
317 | 0 | pabyData += 8; |
318 | 0 | memcpy(&y, pabyData, 8); |
319 | 0 | pabyData += 8; |
320 | |
|
321 | 0 | if (OGR_SWAP(eByteOrder)) |
322 | 0 | { |
323 | 0 | CPL_SWAPDOUBLE(&x); |
324 | 0 | CPL_SWAPDOUBLE(&y); |
325 | 0 | } |
326 | |
|
327 | 0 | if (flags & OGR_G_3D) |
328 | 0 | { |
329 | 0 | memcpy(&z, pabyData, 8); |
330 | 0 | pabyData += 8; |
331 | 0 | if (OGR_SWAP(eByteOrder)) |
332 | 0 | CPL_SWAPDOUBLE(&z); |
333 | 0 | } |
334 | 0 | else |
335 | 0 | { |
336 | 0 | z = 0; |
337 | 0 | } |
338 | 0 | if (flags & OGR_G_MEASURED) |
339 | 0 | { |
340 | 0 | memcpy(&m, pabyData, 8); |
341 | | /*pabyData += 8; */ |
342 | 0 | if (OGR_SWAP(eByteOrder)) |
343 | 0 | { |
344 | 0 | CPL_SWAPDOUBLE(&m); |
345 | 0 | } |
346 | 0 | } |
347 | 0 | else |
348 | 0 | { |
349 | 0 | m = 0; |
350 | 0 | } |
351 | | |
352 | | // Detect coordinates are not NaN --> NOT EMPTY. |
353 | 0 | if (!(std::isnan(x) && std::isnan(y))) |
354 | 0 | flags |= OGR_G_NOT_EMPTY_POINT; |
355 | |
|
356 | 0 | return OGRERR_NONE; |
357 | 0 | } |
358 | | |
359 | | /************************************************************************/ |
360 | | /* exportToWkb() */ |
361 | | /* */ |
362 | | /* Build a well known binary representation of this object. */ |
363 | | /************************************************************************/ |
364 | | |
365 | | OGRErr OGRPoint::exportToWkb(unsigned char *pabyData, |
366 | | const OGRwkbExportOptions *psOptions) const |
367 | | |
368 | 0 | { |
369 | 0 | if (!psOptions) |
370 | 0 | { |
371 | 0 | static const OGRwkbExportOptions defaultOptions; |
372 | 0 | psOptions = &defaultOptions; |
373 | 0 | } |
374 | | |
375 | | /* -------------------------------------------------------------------- */ |
376 | | /* Set the byte order. */ |
377 | | /* -------------------------------------------------------------------- */ |
378 | 0 | pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER( |
379 | 0 | static_cast<unsigned char>(psOptions->eByteOrder)); |
380 | 0 | pabyData += 1; |
381 | | |
382 | | /* -------------------------------------------------------------------- */ |
383 | | /* Set the geometry feature type. */ |
384 | | /* -------------------------------------------------------------------- */ |
385 | |
|
386 | 0 | GUInt32 nGType = getGeometryType(); |
387 | |
|
388 | 0 | if (psOptions->eWkbVariant == wkbVariantPostGIS1) |
389 | 0 | { |
390 | 0 | nGType = wkbFlatten(nGType); |
391 | 0 | if (Is3D()) |
392 | | // Explicitly set wkb25DBit. |
393 | 0 | nGType = |
394 | 0 | static_cast<OGRwkbGeometryType>(nGType | wkb25DBitInternalUse); |
395 | 0 | if (IsMeasured()) |
396 | 0 | nGType = static_cast<OGRwkbGeometryType>(nGType | 0x40000000); |
397 | 0 | } |
398 | 0 | else if (psOptions->eWkbVariant == wkbVariantIso) |
399 | 0 | { |
400 | 0 | nGType = getIsoGeometryType(); |
401 | 0 | } |
402 | |
|
403 | 0 | if (psOptions->eByteOrder == wkbNDR) |
404 | 0 | { |
405 | 0 | CPL_LSBPTR32(&nGType); |
406 | 0 | } |
407 | 0 | else |
408 | 0 | { |
409 | 0 | CPL_MSBPTR32(&nGType); |
410 | 0 | } |
411 | |
|
412 | 0 | memcpy(pabyData, &nGType, 4); |
413 | 0 | pabyData += 4; |
414 | | |
415 | | /* -------------------------------------------------------------------- */ |
416 | | /* Copy in the raw data. Swap if needed. */ |
417 | | /* -------------------------------------------------------------------- */ |
418 | |
|
419 | 0 | if (IsEmpty() && psOptions->eWkbVariant == wkbVariantIso) |
420 | 0 | { |
421 | 0 | const double dNan = std::numeric_limits<double>::quiet_NaN(); |
422 | 0 | memcpy(pabyData, &dNan, 8); |
423 | 0 | if (OGR_SWAP(psOptions->eByteOrder)) |
424 | 0 | CPL_SWAPDOUBLE(pabyData); |
425 | 0 | pabyData += 8; |
426 | 0 | memcpy(pabyData, &dNan, 8); |
427 | 0 | if (OGR_SWAP(psOptions->eByteOrder)) |
428 | 0 | CPL_SWAPDOUBLE(pabyData); |
429 | 0 | pabyData += 8; |
430 | 0 | if (flags & OGR_G_3D) |
431 | 0 | { |
432 | 0 | memcpy(pabyData, &dNan, 8); |
433 | 0 | if (OGR_SWAP(psOptions->eByteOrder)) |
434 | 0 | CPL_SWAPDOUBLE(pabyData); |
435 | 0 | pabyData += 8; |
436 | 0 | } |
437 | 0 | if (flags & OGR_G_MEASURED) |
438 | 0 | { |
439 | 0 | memcpy(pabyData, &dNan, 8); |
440 | 0 | if (OGR_SWAP(psOptions->eByteOrder)) |
441 | 0 | CPL_SWAPDOUBLE(pabyData); |
442 | 0 | } |
443 | 0 | } |
444 | 0 | else |
445 | 0 | { |
446 | 0 | memcpy(pabyData, &x, 8); |
447 | 0 | memcpy(pabyData + 8, &y, 8); |
448 | 0 | OGRRoundCoordinatesIEEE754XYValues<0>( |
449 | 0 | psOptions->sPrecision.nXYBitPrecision, pabyData, 1); |
450 | 0 | if (OGR_SWAP(psOptions->eByteOrder)) |
451 | 0 | { |
452 | 0 | CPL_SWAPDOUBLE(pabyData); |
453 | 0 | CPL_SWAPDOUBLE(pabyData + 8); |
454 | 0 | } |
455 | 0 | pabyData += 16; |
456 | 0 | if (flags & OGR_G_3D) |
457 | 0 | { |
458 | 0 | memcpy(pabyData, &z, 8); |
459 | 0 | OGRRoundCoordinatesIEEE754<0>(psOptions->sPrecision.nZBitPrecision, |
460 | 0 | pabyData, 1); |
461 | 0 | if (OGR_SWAP(psOptions->eByteOrder)) |
462 | 0 | CPL_SWAPDOUBLE(pabyData); |
463 | 0 | pabyData += 8; |
464 | 0 | } |
465 | 0 | if (flags & OGR_G_MEASURED) |
466 | 0 | { |
467 | 0 | memcpy(pabyData, &m, 8); |
468 | 0 | OGRRoundCoordinatesIEEE754<0>(psOptions->sPrecision.nMBitPrecision, |
469 | 0 | pabyData, 1); |
470 | 0 | if (OGR_SWAP(psOptions->eByteOrder)) |
471 | 0 | CPL_SWAPDOUBLE(pabyData); |
472 | 0 | } |
473 | 0 | } |
474 | |
|
475 | 0 | return OGRERR_NONE; |
476 | 0 | } |
477 | | |
478 | | /************************************************************************/ |
479 | | /* importFromWkt() */ |
480 | | /* */ |
481 | | /* Instantiate point from well known text format ``POINT */ |
482 | | /* (x,y)''. */ |
483 | | /************************************************************************/ |
484 | | |
485 | | OGRErr OGRPoint::importFromWkt(const char **ppszInput) |
486 | | |
487 | 4.88k | { |
488 | 4.88k | int bHasZ = FALSE; |
489 | 4.88k | int bHasM = FALSE; |
490 | 4.88k | bool bIsEmpty = false; |
491 | 4.88k | OGRErr eErr = importPreambleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty); |
492 | 4.88k | flags = 0; |
493 | 4.88k | if (eErr != OGRERR_NONE) |
494 | 12 | return eErr; |
495 | 4.87k | if (bHasZ) |
496 | 586 | flags |= OGR_G_3D; |
497 | 4.87k | if (bHasM) |
498 | 797 | flags |= OGR_G_MEASURED; |
499 | 4.87k | if (bIsEmpty) |
500 | 198 | { |
501 | 198 | return OGRERR_NONE; |
502 | 198 | } |
503 | 4.67k | else |
504 | 4.67k | { |
505 | 4.67k | flags |= OGR_G_NOT_EMPTY_POINT; |
506 | 4.67k | } |
507 | | |
508 | 4.67k | const char *pszInput = *ppszInput; |
509 | | |
510 | | /* -------------------------------------------------------------------- */ |
511 | | /* Read the point list which should consist of exactly one point. */ |
512 | | /* -------------------------------------------------------------------- */ |
513 | 4.67k | OGRRawPoint *poPoints = nullptr; |
514 | 4.67k | double *padfZ = nullptr; |
515 | 4.67k | double *padfM = nullptr; |
516 | 4.67k | int nMaxPoint = 0; |
517 | 4.67k | int nPoints = 0; |
518 | 4.67k | int flagsFromInput = flags; |
519 | | |
520 | 4.67k | pszInput = OGRWktReadPointsM(pszInput, &poPoints, &padfZ, &padfM, |
521 | 4.67k | &flagsFromInput, &nMaxPoint, &nPoints); |
522 | 4.67k | if (pszInput == nullptr || nPoints != 1) |
523 | 2.15k | { |
524 | 2.15k | CPLFree(poPoints); |
525 | 2.15k | CPLFree(padfZ); |
526 | 2.15k | CPLFree(padfM); |
527 | 2.15k | return OGRERR_CORRUPT_DATA; |
528 | 2.15k | } |
529 | 2.52k | if ((flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D)) |
530 | 575 | { |
531 | 575 | flags |= OGR_G_3D; |
532 | 575 | bHasZ = TRUE; |
533 | 575 | } |
534 | 2.52k | if ((flagsFromInput & OGR_G_MEASURED) && !(flags & OGR_G_MEASURED)) |
535 | 194 | { |
536 | 194 | flags |= OGR_G_MEASURED; |
537 | 194 | bHasM = TRUE; |
538 | 194 | } |
539 | | |
540 | 2.52k | x = poPoints[0].x; |
541 | 2.52k | y = poPoints[0].y; |
542 | | |
543 | 2.52k | CPLFree(poPoints); |
544 | | |
545 | 2.52k | if (bHasZ) |
546 | 1.14k | { |
547 | 1.14k | if (padfZ != nullptr) |
548 | 1.14k | z = padfZ[0]; |
549 | 1.14k | } |
550 | 2.52k | if (bHasM) |
551 | 951 | { |
552 | 951 | if (padfM != nullptr) |
553 | 951 | m = padfM[0]; |
554 | 951 | } |
555 | | |
556 | 2.52k | CPLFree(padfZ); |
557 | 2.52k | CPLFree(padfM); |
558 | | |
559 | 2.52k | *ppszInput = pszInput; |
560 | | |
561 | 2.52k | return OGRERR_NONE; |
562 | 4.67k | } |
563 | | |
564 | | /************************************************************************/ |
565 | | /* exportToWkt() */ |
566 | | /* */ |
567 | | /* Translate this structure into its well known text format */ |
568 | | /* equivalent. */ |
569 | | /************************************************************************/ |
570 | | |
571 | | std::string OGRPoint::exportToWkt(const OGRWktOptions &opts, OGRErr *err) const |
572 | 0 | { |
573 | 0 | std::string wkt = getGeometryName() + wktTypeString(opts.variant); |
574 | 0 | if (IsEmpty()) |
575 | 0 | { |
576 | 0 | wkt += "EMPTY"; |
577 | 0 | } |
578 | 0 | else |
579 | 0 | { |
580 | 0 | wkt += "("; |
581 | |
|
582 | 0 | bool measured = ((opts.variant == wkbVariantIso) && IsMeasured()); |
583 | 0 | wkt += OGRMakeWktCoordinateM(x, y, z, m, Is3D(), measured, opts); |
584 | |
|
585 | 0 | wkt += ")"; |
586 | 0 | } |
587 | |
|
588 | 0 | if (err) |
589 | 0 | *err = OGRERR_NONE; |
590 | 0 | return wkt; |
591 | 0 | } |
592 | | |
593 | | /************************************************************************/ |
594 | | /* getEnvelope() */ |
595 | | /************************************************************************/ |
596 | | |
597 | | void OGRPoint::getEnvelope(OGREnvelope *psEnvelope) const |
598 | | |
599 | 0 | { |
600 | 0 | psEnvelope->MinX = getX(); |
601 | 0 | psEnvelope->MaxX = getX(); |
602 | 0 | psEnvelope->MinY = getY(); |
603 | 0 | psEnvelope->MaxY = getY(); |
604 | 0 | } |
605 | | |
606 | | /************************************************************************/ |
607 | | /* getEnvelope() */ |
608 | | /************************************************************************/ |
609 | | |
610 | | void OGRPoint::getEnvelope(OGREnvelope3D *psEnvelope) const |
611 | | |
612 | 0 | { |
613 | 0 | psEnvelope->MinX = getX(); |
614 | 0 | psEnvelope->MaxX = getX(); |
615 | 0 | psEnvelope->MinY = getY(); |
616 | 0 | psEnvelope->MaxY = getY(); |
617 | 0 | psEnvelope->MinZ = getZ(); |
618 | 0 | psEnvelope->MaxZ = getZ(); |
619 | 0 | } |
620 | | |
621 | | /** |
622 | | * \fn double OGRPoint::getX() const; |
623 | | * |
624 | | * \brief Fetch X coordinate. |
625 | | * |
626 | | * Relates to the SFCOM IPoint::get_X() method. |
627 | | * |
628 | | * @return the X coordinate of this point. |
629 | | */ |
630 | | |
631 | | /** |
632 | | * \fn double OGRPoint::getY() const; |
633 | | * |
634 | | * \brief Fetch Y coordinate. |
635 | | * |
636 | | * Relates to the SFCOM IPoint::get_Y() method. |
637 | | * |
638 | | * @return the Y coordinate of this point. |
639 | | */ |
640 | | |
641 | | /** |
642 | | * \fn double OGRPoint::getZ() const; |
643 | | * |
644 | | * \brief Fetch Z coordinate. |
645 | | * |
646 | | * Relates to the SFCOM IPoint::get_Z() method. |
647 | | * |
648 | | * @return the Z coordinate of this point, or zero if it is a 2D point. |
649 | | */ |
650 | | |
651 | | /** |
652 | | * \fn void OGRPoint::setX( double xIn ); |
653 | | * |
654 | | * \brief Assign point X coordinate. |
655 | | * |
656 | | * There is no corresponding SFCOM method. |
657 | | */ |
658 | | |
659 | | /** |
660 | | * \fn void OGRPoint::setY( double yIn ); |
661 | | * |
662 | | * \brief Assign point Y coordinate. |
663 | | * |
664 | | * There is no corresponding SFCOM method. |
665 | | */ |
666 | | |
667 | | /** |
668 | | * \fn void OGRPoint::setZ( double zIn ); |
669 | | * |
670 | | * \brief Assign point Z coordinate. |
671 | | * Calling this method will force the geometry |
672 | | * coordinate dimension to 3D (wkbPoint|wkbZ). |
673 | | * |
674 | | * There is no corresponding SFCOM method. |
675 | | */ |
676 | | |
677 | | /************************************************************************/ |
678 | | /* Equal() */ |
679 | | /************************************************************************/ |
680 | | |
681 | | OGRBoolean OGRPoint::Equals(const OGRGeometry *poOther) const |
682 | | |
683 | 0 | { |
684 | 0 | if (poOther == this) |
685 | 0 | return TRUE; |
686 | | |
687 | 0 | if (poOther->getGeometryType() != getGeometryType()) |
688 | 0 | return FALSE; |
689 | | |
690 | 0 | const auto poOPoint = poOther->toPoint(); |
691 | 0 | if (flags != poOPoint->flags) |
692 | 0 | return FALSE; |
693 | | |
694 | 0 | if (IsEmpty()) |
695 | 0 | return TRUE; |
696 | | |
697 | | // Should eventually test the SRS. |
698 | 0 | if (poOPoint->getX() != getX() || poOPoint->getY() != getY() || |
699 | 0 | poOPoint->getZ() != getZ()) |
700 | 0 | return FALSE; |
701 | | |
702 | 0 | return TRUE; |
703 | 0 | } |
704 | | |
705 | | /************************************************************************/ |
706 | | /* transform() */ |
707 | | /************************************************************************/ |
708 | | |
709 | | OGRErr OGRPoint::transform(OGRCoordinateTransformation *poCT) |
710 | | |
711 | 0 | { |
712 | 0 | if (poCT->Transform(1, &x, &y, &z)) |
713 | 0 | { |
714 | 0 | assignSpatialReference(poCT->GetTargetCS()); |
715 | 0 | return OGRERR_NONE; |
716 | 0 | } |
717 | | |
718 | 0 | return OGRERR_FAILURE; |
719 | 0 | } |
720 | | |
721 | | /************************************************************************/ |
722 | | /* swapXY() */ |
723 | | /************************************************************************/ |
724 | | |
725 | | void OGRPoint::swapXY() |
726 | 0 | { |
727 | 0 | std::swap(x, y); |
728 | 0 | } |
729 | | |
730 | | /************************************************************************/ |
731 | | /* Within() */ |
732 | | /************************************************************************/ |
733 | | |
734 | | OGRBoolean OGRPoint::Within(const OGRGeometry *poOtherGeom) const |
735 | | |
736 | 0 | { |
737 | 0 | if (!IsEmpty() && poOtherGeom != nullptr && |
738 | 0 | wkbFlatten(poOtherGeom->getGeometryType()) == wkbCurvePolygon) |
739 | 0 | { |
740 | 0 | const auto poCurve = poOtherGeom->toCurvePolygon(); |
741 | 0 | return poCurve->Contains(this); |
742 | 0 | } |
743 | | |
744 | 0 | return OGRGeometry::Within(poOtherGeom); |
745 | 0 | } |
746 | | |
747 | | /************************************************************************/ |
748 | | /* Intersects() */ |
749 | | /************************************************************************/ |
750 | | |
751 | | OGRBoolean OGRPoint::Intersects(const OGRGeometry *poOtherGeom) const |
752 | | |
753 | 0 | { |
754 | 0 | if (!IsEmpty() && poOtherGeom != nullptr && |
755 | 0 | wkbFlatten(poOtherGeom->getGeometryType()) == wkbCurvePolygon) |
756 | 0 | { |
757 | 0 | const auto poCurve = poOtherGeom->toCurvePolygon(); |
758 | 0 | return poCurve->Intersects(this); |
759 | 0 | } |
760 | | |
761 | 0 | return OGRGeometry::Intersects(poOtherGeom); |
762 | 0 | } |