GEOS  3.12.0
Coordinate.h
1 /**********************************************************************
2  *
3  * GEOS - Geometry Engine Open Source
4  * http://geos.osgeo.org
5  *
6  * Copyright (C) 2006 Refractions Research Inc.
7  *
8  * This is free software; you can redistribute and/or modify it under
9  * the terms of the GNU Lesser General Public Licence as published
10  * by the Free Software Foundation.
11  * See the COPYING file for more information.
12  *
13  **********************************************************************/
14 
15 #pragma once
16 
17 #include <geos/export.h>
18 #include <geos/constants.h> // for DoubleNotANumber
19 #include <set>
20 #include <unordered_set>
21 #include <stack>
22 #include <vector> // for typedefs
23 #include <string>
24 #include <limits>
25 
26 #ifdef _MSC_VER
27 #pragma warning(push)
28 #pragma warning(disable: 4251) // warning C4251: needs to have dll-interface to be used by clients of class
29 #endif
30 
31 namespace geos {
32 namespace geom { // geos.geom
33 
34 // Forward declarations
35 struct CoordinateLessThan;
36 class CoordinateXYZM;
37 class CoordinateXYM;
38 class Coordinate;
39 
40 enum class CoordinateType : std::uint8_t {
41  XY,
42  XYZ,
43  XYZM,
44  XYM,
45 };
46 
47 enum class Ordinate : std::uint8_t {
48  X,
49  Y,
50  Z,
51  M
52 };
53 
54 GEOS_DLL std::ostream& operator<< (std::ostream&, const CoordinateType);
55 
56 class GEOS_DLL CoordinateXY {
57 
58  const static CoordinateXY _nullCoord;
59 
60 protected:
61  constexpr const static double DEFAULT_X = 0.0;
62  constexpr const static double DEFAULT_Y = 0.0;
63  constexpr const static double DEFAULT_Z = DoubleNotANumber;
64  constexpr const static double DEFAULT_M = DoubleNotANumber;
65 
66 public:
67  CoordinateXY()
68  : x(DEFAULT_X)
69  , y(DEFAULT_Y)
70  {}
71 
72  CoordinateXY(double xNew, double yNew)
73  : x(xNew)
74  , y(yNew)
75  {}
76 
77  template<Ordinate>
78  double get() const;
79 
81  double x;
82 
84  double y;
85 
87  GEOS_DLL friend bool operator==(const CoordinateXY& a, const CoordinateXY& b)
88  {
89  return a.equals2D(b);
90  };
91 
93  GEOS_DLL friend bool operator!=(const CoordinateXY& a, const CoordinateXY& b)
94  {
95  return ! a.equals2D(b);
96  };
97 
98  bool isValid() const
99  {
100  return std::isfinite(x) && std::isfinite(y);
101  };
102 
103  bool equals2D(const CoordinateXY& other) const
104  {
105  if(x != other.x) {
106  return false;
107  }
108  if(y != other.y) {
109  return false;
110  }
111  return true;
112  };
113 
114  bool equals2D(const CoordinateXY& other, double tolerance) const
115  {
116  if (std::abs(x - other.x) > tolerance) {
117  return false;
118  }
119  if (std::abs(y - other.y) > tolerance) {
120  return false;
121  }
122  return true;
123  };
124 
126  bool equals(const CoordinateXY& other) const
127  {
128  return equals2D(other);
129  };
130 
132  inline int compareTo(const CoordinateXY& other) const
133  {
134  if(x < other.x) {
135  return -1;
136  }
137  if(x > other.x) {
138  return 1;
139  }
140  if(y < other.y) {
141  return -1;
142  }
143  if(y > other.y) {
144  return 1;
145  }
146  return 0;
147  };
148 
149  static const CoordinateXY& getNull();
150 
151  double distance(const CoordinateXY& p) const
152  {
153  double dx = x - p.x;
154  double dy = y - p.y;
155  return std::sqrt(dx * dx + dy * dy);
156  };
157 
158  double distanceSquared(const CoordinateXY& p) const
159  {
160  double dx = x - p.x;
161  double dy = y - p.y;
162  return dx * dx + dy * dy;
163  };
164 
165  bool isNull() const
166  {
167  return (std::isnan(x) && std::isnan(y));
168  };
169 
170  void setNull()
171  {
172  x = DoubleNotANumber;
173  y = DoubleNotANumber;
174  };
175 
176  struct GEOS_DLL HashCode
177  {
178  inline std::size_t operator()(const CoordinateXY& c) const
179  {
180  size_t h = std::hash<double>{}(c.x);
181  h ^= std::hash<double>{}(c.y) << 1;
182  // z ordinate ignored for consistency with operator==
183  return h;
184  };
185  };
186 
187  using UnorderedSet = std::unordered_set<Coordinate, HashCode>;
188 
190  std::string toString() const;
191 };
192 
213 // Define the following to make assignments and copy constructions
214 // NON-(will let profilers report usages)
215 //#define PROFILE_COORDINATE_COPIES 1
216 class GEOS_DLL Coordinate : public CoordinateXY {
217 
218 private:
219 
220  static const Coordinate _nullCoord;
221 
222 public:
224  typedef std::set<const Coordinate*, CoordinateLessThan> ConstSet;
225 
227  typedef std::vector<const Coordinate*> ConstVect;
228 
230  typedef std::stack<const Coordinate*> ConstStack;
231 
233  typedef std::vector<Coordinate> Vect;
234 
236  double z;
237 
238  Coordinate()
239  : CoordinateXY()
240  , z(DEFAULT_Z)
241  {};
242 
243  Coordinate(double xNew, double yNew, double zNew = DEFAULT_Z)
244  : CoordinateXY(xNew, yNew)
245  , z(zNew)
246  {};
247 
248  explicit Coordinate(const CoordinateXY& other)
249  : CoordinateXY(other)
250  , z(DEFAULT_Z)
251  {};
252 
253  template<Ordinate>
254  double get() const;
255 
256  void setNull()
257  {
258  CoordinateXY::setNull();
259  z = DoubleNotANumber;
260  };
261 
262  static const Coordinate& getNull();
263 
264  bool isNull() const
265  {
266  return CoordinateXY::isNull() && std::isnan(z);
267  };
268 
270  bool equals3D(const Coordinate& other) const
271  {
272  return (x == other.x) && (y == other.y) &&
273  ((z == other.z) || (std::isnan(z) && std::isnan(other.z)));
274  };
275 
277  std::string toString() const;
278 
279  Coordinate& operator=(const CoordinateXY& other){
280  x = other.x;
281  y = other.y;
282  z = DEFAULT_Z;
283 
284  return *this;
285  }
286 };
287 
288 
289 class GEOS_DLL CoordinateXYM : public CoordinateXY {
290 private:
291  static const CoordinateXYM _nullCoord;
292 
293 public:
294  CoordinateXYM() : CoordinateXYM(DEFAULT_X, DEFAULT_Y, DEFAULT_M) {}
295 
296  explicit CoordinateXYM(const CoordinateXY& c)
297  : CoordinateXY(c)
298  , m(DEFAULT_M) {}
299 
300  CoordinateXYM(double x_, double y_, double m_)
301  : CoordinateXY(x_, y_)
302  , m(m_) {}
303 
304  double m;
305 
306  template<Ordinate>
307  double get() const;
308 
309  static const CoordinateXYM& getNull();
310 
311  void setNull()
312  {
313  CoordinateXY::setNull();
314  m = DoubleNotANumber;
315  };
316 
317  bool isNull() const
318  {
319  return CoordinateXY::isNull() && std::isnan(m);
320  }
321  bool equals3D(const CoordinateXYM& other) const {
322  return x == other.x && y == other.y && (m == other.m || (std::isnan(m) && std::isnan(other.m)));
323  }
324 
325  CoordinateXYM& operator=(const CoordinateXYZM& other);
326 
327  CoordinateXYM& operator=(const CoordinateXY& other) {
328  x = other.x;
329  y = other.y;
330  m = DEFAULT_M;
331 
332  return *this;
333  }
334 
335  std::string toString() const;
336 };
337 
338 
339 class GEOS_DLL CoordinateXYZM : public Coordinate {
340 private:
341  static const CoordinateXYZM _nullCoord;
342 
343 public:
344  CoordinateXYZM() : CoordinateXYZM(DEFAULT_X, DEFAULT_Y, DEFAULT_Z, DEFAULT_M) {}
345 
346  explicit CoordinateXYZM(const CoordinateXY& c)
347  : Coordinate(c)
348  , m(DEFAULT_M) {}
349 
350  explicit CoordinateXYZM(const CoordinateXYM& c)
351  : Coordinate(c)
352  , m(c.m) {}
353 
354  explicit CoordinateXYZM(const Coordinate& c)
355  : Coordinate(c)
356  , m(DEFAULT_M) {}
357 
358  CoordinateXYZM(double x_, double y_, double z_, double m_)
359  : Coordinate(x_, y_, z_)
360  , m(m_) {}
361 
362  double m;
363 
364  template<Ordinate>
365  double get() const;
366 
367  static const CoordinateXYZM& getNull();
368 
369  void setNull()
370  {
371  Coordinate::setNull();
372  m = DoubleNotANumber;
373  };
374 
375 
376  bool isNull() const
377  {
378  return Coordinate::isNull() && std::isnan(m);
379  }
380 
381  bool equals4D(const CoordinateXYZM& other) const {
382  return x == other.x && y == other.y &&
383  (z == other.z || (std::isnan(z) && std::isnan(other.z))) &&
384  (m == other.m || (std::isnan(m) && std::isnan(other.m)));
385  }
386 
387  CoordinateXYZM& operator=(const CoordinateXY& other) {
388  x = other.x;
389  y = other.y;
390  z = DEFAULT_Z;
391  m = DEFAULT_M;
392 
393  return *this;
394  }
395 
396  CoordinateXYZM& operator=(const Coordinate& other) {
397  x = other.x;
398  y = other.y;
399  z = other.z;
400  m = DEFAULT_M;
401 
402  return *this;
403  }
404 
405  CoordinateXYZM& operator=(const CoordinateXYM& other) {
406  x = other.x;
407  y = other.y;
408  z = DEFAULT_Z;
409  m = other.m;
410 
411  return *this;
412  }
413 
414  std::string toString() const;
415 };
416 
417 inline CoordinateXYM&
418 CoordinateXYM::operator=(const CoordinateXYZM& other) {
419  x = other.x;
420  y = other.y;
421  m = other.m;
422 
423  return *this;
424 }
425 
426 
428 struct GEOS_DLL CoordinateLessThan {
429 
430  bool operator()(const CoordinateXY* a, const CoordinateXY* b) const
431  {
432  if(a->compareTo(*b) < 0) {
433  return true;
434  }
435  else {
436  return false;
437  }
438  };
439 
440  bool operator()(const CoordinateXY& a, const CoordinateXY& b) const
441  {
442  if(a.compareTo(b) < 0) {
443  return true;
444  }
445  else {
446  return false;
447  }
448  };
449 
450 };
451 
453 inline bool operator<(const CoordinateXY& a, const CoordinateXY& b)
454 {
455  return CoordinateLessThan()(a, b);
456 }
457 
458 
459 // Generic accessors, XY
460 
461 template<>
462 inline double CoordinateXY::get<Ordinate::X>() const
463 {
464  return x;
465 }
466 
467 template<>
468 inline double CoordinateXY::get<Ordinate::Y>() const
469 {
470  return y;
471 }
472 
473 template<>
474 inline double CoordinateXY::get<Ordinate::Z>() const
475 {
476  return DEFAULT_Z;
477 }
478 
479 template<>
480 inline double CoordinateXY::get<Ordinate::M>() const
481 {
482  return DEFAULT_M;
483 }
484 
485 // Generic accessors, XYZ
486 
487 template<>
488 inline double Coordinate::get<Ordinate::X>() const
489 {
490  return x;
491 }
492 
493 template<>
494 inline double Coordinate::get<Ordinate::Y>() const
495 {
496  return y;
497 }
498 
499 template<>
500 inline double Coordinate::get<Ordinate::Z>() const
501 {
502  return z;
503 }
504 
505 template<>
506 inline double Coordinate::get<Ordinate::M>() const
507 {
508  return DEFAULT_M;
509 }
510 
511 // Generic accessors, XYM
512 
513 template<>
514 inline double CoordinateXYM::get<Ordinate::X>() const
515 {
516  return x;
517 }
518 
519 template<>
520 inline double CoordinateXYM::get<Ordinate::Y>() const
521 {
522  return y;
523 }
524 
525 template<>
526 inline double CoordinateXYM::get<Ordinate::Z>() const
527 {
528  return DEFAULT_Z;
529 }
530 
531 template<>
532 inline double CoordinateXYM::get<Ordinate::M>() const
533 {
534  return m;
535 }
536 
537 // Generic accessors, XYZM
538 
539 template<>
540 inline double CoordinateXYZM::get<Ordinate::X>() const
541 {
542  return x;
543 }
544 
545 template<>
546 inline double CoordinateXYZM::get<Ordinate::Y>() const
547 {
548  return y;
549 }
550 
551 template<>
552 inline double CoordinateXYZM::get<Ordinate::Z>() const
553 {
554  return z;
555 }
556 
557 template<>
558 inline double CoordinateXYZM::get<Ordinate::M>() const
559 {
560  return m;
561 }
562 
563 GEOS_DLL std::ostream& operator<< (std::ostream& os, const CoordinateXY& c);
564 GEOS_DLL std::ostream& operator<< (std::ostream& os, const Coordinate& c);
565 GEOS_DLL std::ostream& operator<< (std::ostream& os, const CoordinateXYM& c);
566 GEOS_DLL std::ostream& operator<< (std::ostream& os, const CoordinateXYZM& c);
567 
568 } // namespace geos.geom
569 } // namespace geos
570 
571 // Add specializations of std::common_type for Coordinate types
572 namespace std {
573  template<> struct common_type<geos::geom::CoordinateXY, geos::geom::CoordinateXY> { using type = geos::geom::CoordinateXY; };
574  template<> struct common_type<geos::geom::CoordinateXY, geos::geom::Coordinate> { using type = geos::geom::Coordinate; };
575  template<> struct common_type<geos::geom::CoordinateXY, geos::geom::CoordinateXYM> { using type = geos::geom::CoordinateXYM; };
576  template<> struct common_type<geos::geom::CoordinateXY, geos::geom::CoordinateXYZM> { using type = geos::geom::CoordinateXYZM; };
577 
578  template<> struct common_type<geos::geom::Coordinate, geos::geom::CoordinateXY> { using type = geos::geom::Coordinate; };
579  template<> struct common_type<geos::geom::Coordinate, geos::geom::Coordinate> { using type = geos::geom::Coordinate; };
580  template<> struct common_type<geos::geom::Coordinate, geos::geom::CoordinateXYM> { using type = geos::geom::CoordinateXYZM; };
581  template<> struct common_type<geos::geom::Coordinate, geos::geom::CoordinateXYZM> { using type = geos::geom::CoordinateXYZM; };
582 
583  template<> struct common_type<geos::geom::CoordinateXYM, geos::geom::CoordinateXY> { using type = geos::geom::CoordinateXYM; };
584  template<> struct common_type<geos::geom::CoordinateXYM, geos::geom::Coordinate> { using type = geos::geom::CoordinateXYZM; };
585  template<> struct common_type<geos::geom::CoordinateXYM, geos::geom::CoordinateXYM> { using type = geos::geom::CoordinateXYM; };
586  template<> struct common_type<geos::geom::CoordinateXYM, geos::geom::CoordinateXYZM> { using type = geos::geom::CoordinateXYZM; };
587 
588  template<> struct common_type<geos::geom::CoordinateXYZM, geos::geom::CoordinateXY> { using type = geos::geom::CoordinateXYZM; };
589  template<> struct common_type<geos::geom::CoordinateXYZM, geos::geom::Coordinate> { using type = geos::geom::CoordinateXYZM; };
590  template<> struct common_type<geos::geom::CoordinateXYZM, geos::geom::CoordinateXYM> { using type = geos::geom::CoordinateXYZM; };
591  template<> struct common_type<geos::geom::CoordinateXYZM, geos::geom::CoordinateXYZM> { using type = geos::geom::CoordinateXYZM; };
592 }
593 
594 #ifdef _MSC_VER
595 #pragma warning(pop)
596 #endif
597 
598 
599 
600 
601 
602 
603 
604 
605 
606 
607 
608 
609 
610 
611 
612 
613 
614 
615 
616 
617 
618 
619 
620 
621 
622 
geos::geom::CoordinateLessThan
Strict weak ordering Functor for Coordinate.
Definition: Coordinate.h:428
geos::geom::Coordinate::ConstVect
std::vector< const Coordinate * > ConstVect
A vector of const Coordinate pointers.
Definition: Coordinate.h:227
geos::geom::Coordinate::ConstSet
std::set< const Coordinate *, CoordinateLessThan > ConstSet
A set of const Coordinate pointers.
Definition: Coordinate.h:224
geos
Basic namespace for all GEOS functionalities.
Definition: Angle.h:25
geos::geom::Coordinate::toString
std::string toString() const
Returns a string of the form (x,y,z) .
geos::geom::Coordinate::Vect
std::vector< Coordinate > Vect
A vector of Coordinate objects (real object, not pointers)
Definition: Coordinate.h:233
geos::geom::Coordinate::ConstStack
std::stack< const Coordinate * > ConstStack
A stack of const Coordinate pointers.
Definition: Coordinate.h:230
geos::geom::Coordinate
Coordinate is the lightweight class used to store coordinates.
Definition: Coordinate.h:216
geos::geom::Coordinate::equals3D
bool equals3D(const Coordinate &other) const
3D comparison
Definition: Coordinate.h:270
geos::geom::operator<
bool operator<(const CoordinateXY &a, const CoordinateXY &b)
Strict weak ordering operator for Coordinate.
Definition: Coordinate.h:453
geos::geom::Coordinate::z
double z
z-coordinate
Definition: Coordinate.h:236