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