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