GEOS  3.13.0dev
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 
Coordinate is the lightweight class used to store coordinates.
Definition: Coordinate.h:216
std::string toString() const
Returns a string of the form (x,y,z) .
std::set< const Coordinate *, CoordinateLessThan > ConstSet
A set of const Coordinate pointers.
Definition: Coordinate.h:224
std::vector< Coordinate > Vect
A vector of Coordinate objects (real object, not pointers)
Definition: Coordinate.h:233
std::vector< const Coordinate * > ConstVect
A vector of const Coordinate pointers.
Definition: Coordinate.h:227
std::stack< const Coordinate * > ConstStack
A stack of const Coordinate pointers.
Definition: Coordinate.h:230
bool equals3D(const Coordinate &other) const
3D comparison
Definition: Coordinate.h:270
double z
z-coordinate
Definition: Coordinate.h:236
bool operator<(const CoordinateXY &a, const CoordinateXY &b)
Strict weak ordering operator for Coordinate.
Definition: Coordinate.h:453
Basic namespace for all GEOS functionalities.
Definition: Angle.h:25
Strict weak ordering Functor for Coordinate.
Definition: Coordinate.h:428