GEOS 3.15.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
32namespace geos {
33namespace geom { // geos.geom
34
35// Forward declarations
36struct CoordinateLessThan;
37class CoordinateXYZM;
38class CoordinateXYM;
39class Coordinate;
40
41enum class CoordinateType : std::uint8_t {
42 XY,
43 XYZ,
44 XYZM,
45 XYM,
46};
47
48enum class Ordinate : std::uint8_t {
49 X,
50 Y,
51 Z,
52 M
53};
54
55GEOS_DLL std::ostream& operator<< (std::ostream&, const CoordinateType);
56
57class GEOS_DLL CoordinateXY {
58
59 const static CoordinateXY _nullCoord;
60
61protected:
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
67public:
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
81 template<Ordinate>
82 static constexpr bool has();
83
85 double x;
86
88 double y;
89
91 GEOS_DLL friend bool operator==(const CoordinateXY& a, const CoordinateXY& b)
92 {
93 return a.equals2D(b);
94 };
95
97 GEOS_DLL friend bool operator!=(const CoordinateXY& a, const CoordinateXY& b)
98 {
99 return ! a.equals2D(b);
100 };
101
102 bool isValid() const
103 {
104 return std::isfinite(x) && std::isfinite(y);
105 };
106
107 bool equals2D(const CoordinateXY& other) const
108 {
109 if(x != other.x) {
110 return false;
111 }
112 if(y != other.y) {
113 return false;
114 }
115 return true;
116 };
117
118 bool equals2D(const CoordinateXY& other, double tolerance) const
119 {
120 if (std::abs(x - other.x) > tolerance) {
121 return false;
122 }
123 if (std::abs(y - other.y) > tolerance) {
124 return false;
125 }
126 return true;
127 };
128
130 bool equals(const CoordinateXY& other) const
131 {
132 return equals2D(other);
133 };
134
136 inline int compareTo(const CoordinateXY& other) const
137 {
138 if(x < other.x) {
139 return -1;
140 }
141 if(x > other.x) {
142 return 1;
143 }
144 if(y < other.y) {
145 return -1;
146 }
147 if(y > other.y) {
148 return 1;
149 }
150 return 0;
151 };
152
153 static const CoordinateXY& getNull();
154
155 double distance(const CoordinateXY& p) const
156 {
157 double dx = x - p.x;
158 double dy = y - p.y;
159 return std::sqrt(dx * dx + dy * dy);
160 };
161
162 double distanceSquared(const CoordinateXY& p) const
163 {
164 double dx = x - p.x;
165 double dy = y - p.y;
166 return dx * dx + dy * dy;
167 };
168
169 bool isNull() const
170 {
171 return (std::isnan(x) && std::isnan(y));
172 };
173
174 void setNull()
175 {
176 x = DoubleNotANumber;
177 y = DoubleNotANumber;
178 };
179
180 struct GEOS_DLL HashCode
181 {
182 inline std::size_t operator()(const CoordinateXY& c) const
183 {
184 size_t h = std::hash<double>{}(c.x);
185 h ^= std::hash<double>{}(c.y) << 1;
186 // z ordinate ignored for consistency with operator==
187 return h;
188 };
189 };
190
191 using UnorderedSet = std::unordered_set<Coordinate, HashCode>;
192
194 std::string toString() const;
195};
196
217// Define the following to make assignments and copy constructions
218// NON-(will let profilers report usages)
219//#define PROFILE_COORDINATE_COPIES 1
220class GEOS_DLL Coordinate : public CoordinateXY {
221
222private:
223
224 static const Coordinate _nullCoord;
225
226public:
228 typedef std::set<const Coordinate*, CoordinateLessThan> ConstSet;
229 typedef std::set<const CoordinateXY*, CoordinateLessThan> ConstXYSet;
230
232 typedef std::vector<const Coordinate*> ConstVect;
233
235 typedef std::stack<const Coordinate*> ConstStack;
236
238 typedef std::vector<Coordinate> Vect;
239
241 typedef std::map<const CoordinateXY*, int, CoordinateLessThan> ConstIntMap;
242
244 double z;
245
246 Coordinate()
247 : CoordinateXY()
248 , z(DEFAULT_Z)
249 {};
250
251 Coordinate(double xNew, double yNew, double zNew = DEFAULT_Z)
252 : CoordinateXY(xNew, yNew)
253 , z(zNew)
254 {};
255
256 explicit Coordinate(const CoordinateXY& other)
257 : CoordinateXY(other)
258 , z(DEFAULT_Z)
259 {};
260
261 template<Ordinate>
262 static constexpr bool has();
263
264 template<Ordinate>
265 double get() const;
266
267 void setNull()
268 {
269 CoordinateXY::setNull();
270 z = DoubleNotANumber;
271 };
272
273 static const Coordinate& getNull();
274
275 bool isNull() const
276 {
277 return CoordinateXY::isNull() && std::isnan(z);
278 };
279
281 bool equals3D(const Coordinate& other) const
282 {
283 return (x == other.x) && (y == other.y) &&
284 ((z == other.z) || (std::isnan(z) && std::isnan(other.z)));
285 };
286
288 std::string toString() const;
289
290 Coordinate& operator=(const CoordinateXY& other){
291 x = other.x;
292 y = other.y;
293 z = DEFAULT_Z;
294
295 return *this;
296 }
297};
298
299
300class GEOS_DLL CoordinateXYM : public CoordinateXY {
301private:
302 static const CoordinateXYM _nullCoord;
303
304public:
305 CoordinateXYM() : CoordinateXYM(DEFAULT_X, DEFAULT_Y, DEFAULT_M) {}
306
307 explicit CoordinateXYM(const CoordinateXY& c)
308 : CoordinateXY(c)
309 , m(DEFAULT_M) {}
310
311 CoordinateXYM(double x_, double y_, double m_)
312 : CoordinateXY(x_, y_)
313 , m(m_) {}
314
315 double m;
316
317 template<Ordinate>
318 static constexpr bool has();
319
320 template<Ordinate>
321 double get() const;
322
323 static const CoordinateXYM& getNull();
324
325 void setNull()
326 {
327 CoordinateXY::setNull();
328 m = DoubleNotANumber;
329 };
330
331 bool isNull() const
332 {
333 return CoordinateXY::isNull() && std::isnan(m);
334 }
335 bool equals3D(const CoordinateXYM& other) const {
336 return x == other.x && y == other.y && (m == other.m || (std::isnan(m) && std::isnan(other.m)));
337 }
338
339 CoordinateXYM& operator=(const CoordinateXYZM& other);
340
341 CoordinateXYM& operator=(const CoordinateXY& other) {
342 x = other.x;
343 y = other.y;
344 m = DEFAULT_M;
345
346 return *this;
347 }
348
349 std::string toString() const;
350};
351
352
353class GEOS_DLL CoordinateXYZM : public Coordinate {
354private:
355 static const CoordinateXYZM _nullCoord;
356
357public:
358 CoordinateXYZM() : CoordinateXYZM(DEFAULT_X, DEFAULT_Y, DEFAULT_Z, DEFAULT_M) {}
359
360 explicit CoordinateXYZM(const CoordinateXY& c)
361 : Coordinate(c)
362 , m(DEFAULT_M) {}
363
364 explicit CoordinateXYZM(const CoordinateXYM& c)
365 : Coordinate(c)
366 , m(c.m) {}
367
368 explicit CoordinateXYZM(const Coordinate& c)
369 : Coordinate(c)
370 , m(DEFAULT_M) {}
371
372 CoordinateXYZM(double x_, double y_, double z_, double m_)
373 : Coordinate(x_, y_, z_)
374 , m(m_) {}
375
376 double m;
377
378 template<Ordinate>
379 static constexpr bool has();
380
381 template<Ordinate>
382 double get() const;
383
384 static const CoordinateXYZM& getNull();
385
386 void setNull()
387 {
388 Coordinate::setNull();
389 m = DoubleNotANumber;
390 };
391
392
393 bool isNull() const
394 {
395 return Coordinate::isNull() && std::isnan(m);
396 }
397
398 bool equals4D(const CoordinateXYZM& other) const {
399 return x == other.x && y == other.y &&
400 (z == other.z || (std::isnan(z) && std::isnan(other.z))) &&
401 (m == other.m || (std::isnan(m) && std::isnan(other.m)));
402 }
403
404 CoordinateXYZM& operator=(const CoordinateXY& other) {
405 x = other.x;
406 y = other.y;
407 z = DEFAULT_Z;
408 m = DEFAULT_M;
409
410 return *this;
411 }
412
413 CoordinateXYZM& operator=(const Coordinate& other) {
414 x = other.x;
415 y = other.y;
416 z = other.z;
417 m = DEFAULT_M;
418
419 return *this;
420 }
421
422 CoordinateXYZM& operator=(const CoordinateXYM& other) {
423 x = other.x;
424 y = other.y;
425 z = DEFAULT_Z;
426 m = other.m;
427
428 return *this;
429 }
430
431 std::string toString() const;
432};
433
434inline CoordinateXYM&
435CoordinateXYM::operator=(const CoordinateXYZM& other) {
436 x = other.x;
437 y = other.y;
438 m = other.m;
439
440 return *this;
441}
442
443
445struct GEOS_DLL CoordinateLessThan {
446
447 bool operator()(const CoordinateXY* a, const CoordinateXY* b) const
448 {
449 if(a->compareTo(*b) < 0) {
450 return true;
451 }
452 else {
453 return false;
454 }
455 };
456
457 bool operator()(const CoordinateXY& a, const CoordinateXY& b) const
458 {
459 if(a.compareTo(b) < 0) {
460 return true;
461 }
462 else {
463 return false;
464 }
465 };
466
467};
468
470inline bool operator<(const CoordinateXY& a, const CoordinateXY& b)
471{
472 return CoordinateLessThan()(a, b);
473}
474
475
476// Generic accessors, XY
477
478template<>
479constexpr bool CoordinateXY::has<Ordinate::X>()
480{
481 return true;
482}
483
484template<>
485constexpr bool CoordinateXY::has<Ordinate::Y>()
486{
487 return true;
488}
489
490template<>
491constexpr bool CoordinateXY::has<Ordinate::Z>()
492{
493 return false;
494}
495
496template<>
497constexpr bool CoordinateXY::has<Ordinate::M>()
498{
499 return false;
500}
501
502template<>
503inline double CoordinateXY::get<Ordinate::X>() const
504{
505 return x;
506}
507
508template<>
509inline double CoordinateXY::get<Ordinate::Y>() const
510{
511 return y;
512}
513
514template<>
515inline double CoordinateXY::get<Ordinate::Z>() const
516{
517 return DEFAULT_Z;
518}
519
520template<>
521inline double CoordinateXY::get<Ordinate::M>() const
522{
523 return DEFAULT_M;
524}
525
526// Generic accessors, XYZ
527
528template<>
529constexpr bool Coordinate::has<Ordinate::X>()
530{
531 return true;
532}
533
534template<>
535constexpr bool Coordinate::has<Ordinate::Y>()
536{
537 return true;
538}
539
540template<>
541constexpr bool Coordinate::has<Ordinate::Z>()
542{
543 return true;
544}
545
546template<>
547constexpr bool Coordinate::has<Ordinate::M>()
548{
549 return false;
550}
551
552template<>
553inline double Coordinate::get<Ordinate::X>() const
554{
555 return x;
556}
557
558template<>
559inline double Coordinate::get<Ordinate::Y>() const
560{
561 return y;
562}
563
564template<>
565inline double Coordinate::get<Ordinate::Z>() const
566{
567 return z;
568}
569
570template<>
571inline double Coordinate::get<Ordinate::M>() const
572{
573 return DEFAULT_M;
574}
575
576// Generic accessors, XYM
577
578template<>
579constexpr bool CoordinateXYM::has<Ordinate::X>()
580{
581 return true;
582}
583
584template<>
585constexpr bool CoordinateXYM::has<Ordinate::Y>()
586{
587 return true;
588}
589
590template<>
591constexpr bool CoordinateXYM::has<Ordinate::Z>()
592{
593 return false;
594}
595
596template<>
597constexpr bool CoordinateXYM::has<Ordinate::M>()
598{
599 return true;
600}
601
602template<>
603inline double CoordinateXYM::get<Ordinate::X>() const
604{
605 return x;
606}
607
608template<>
609inline double CoordinateXYM::get<Ordinate::Y>() const
610{
611 return y;
612}
613
614template<>
615inline double CoordinateXYM::get<Ordinate::Z>() const
616{
617 return DEFAULT_Z;
618}
619
620template<>
621inline double CoordinateXYM::get<Ordinate::M>() const
622{
623 return m;
624}
625
626// Generic accessors, XYZM
627
628template<>
629constexpr bool CoordinateXYZM::has<Ordinate::X>()
630{
631 return true;
632}
633
634template<>
635constexpr bool CoordinateXYZM::has<Ordinate::Y>()
636{
637 return true;
638}
639
640template<>
641constexpr bool CoordinateXYZM::has<Ordinate::Z>()
642{
643 return true;
644}
645
646template<>
647constexpr bool CoordinateXYZM::has<Ordinate::M>()
648{
649 return true;
650}
651
652template<>
653inline double CoordinateXYZM::get<Ordinate::X>() const
654{
655 return x;
656}
657
658template<>
659inline double CoordinateXYZM::get<Ordinate::Y>() const
660{
661 return y;
662}
663
664template<>
665inline double CoordinateXYZM::get<Ordinate::Z>() const
666{
667 return z;
668}
669
670template<>
671inline double CoordinateXYZM::get<Ordinate::M>() const
672{
673 return m;
674}
675
676GEOS_DLL std::ostream& operator<< (std::ostream& os, const CoordinateXY& c);
677GEOS_DLL std::ostream& operator<< (std::ostream& os, const Coordinate& c);
678GEOS_DLL std::ostream& operator<< (std::ostream& os, const CoordinateXYM& c);
679GEOS_DLL std::ostream& operator<< (std::ostream& os, const CoordinateXYZM& c);
680
681} // namespace geos.geom
682} // namespace geos
683
684// Add specializations of std::common_type for Coordinate types
685namespace std {
686 template<> struct common_type<geos::geom::CoordinateXY, geos::geom::CoordinateXY> { using type = geos::geom::CoordinateXY; };
687 template<> struct common_type<geos::geom::CoordinateXY, geos::geom::Coordinate> { using type = geos::geom::Coordinate; };
688 template<> struct common_type<geos::geom::CoordinateXY, geos::geom::CoordinateXYM> { using type = geos::geom::CoordinateXYM; };
689 template<> struct common_type<geos::geom::CoordinateXY, geos::geom::CoordinateXYZM> { using type = geos::geom::CoordinateXYZM; };
690
691 template<> struct common_type<geos::geom::Coordinate, geos::geom::CoordinateXY> { using type = geos::geom::Coordinate; };
692 template<> struct common_type<geos::geom::Coordinate, geos::geom::Coordinate> { using type = geos::geom::Coordinate; };
693 template<> struct common_type<geos::geom::Coordinate, geos::geom::CoordinateXYM> { using type = geos::geom::CoordinateXYZM; };
694 template<> struct common_type<geos::geom::Coordinate, geos::geom::CoordinateXYZM> { using type = geos::geom::CoordinateXYZM; };
695
696 template<> struct common_type<geos::geom::CoordinateXYM, geos::geom::CoordinateXY> { using type = geos::geom::CoordinateXYM; };
697 template<> struct common_type<geos::geom::CoordinateXYM, geos::geom::Coordinate> { using type = geos::geom::CoordinateXYZM; };
698 template<> struct common_type<geos::geom::CoordinateXYM, geos::geom::CoordinateXYM> { using type = geos::geom::CoordinateXYM; };
699 template<> struct common_type<geos::geom::CoordinateXYM, geos::geom::CoordinateXYZM> { using type = geos::geom::CoordinateXYZM; };
700
701 template<> struct common_type<geos::geom::CoordinateXYZM, geos::geom::CoordinateXY> { using type = geos::geom::CoordinateXYZM; };
702 template<> struct common_type<geos::geom::CoordinateXYZM, geos::geom::Coordinate> { using type = geos::geom::CoordinateXYZM; };
703 template<> struct common_type<geos::geom::CoordinateXYZM, geos::geom::CoordinateXYM> { using type = geos::geom::CoordinateXYZM; };
704 template<> struct common_type<geos::geom::CoordinateXYZM, geos::geom::CoordinateXYZM> { using type = geos::geom::CoordinateXYZM; };
705}
706
707#ifdef _MSC_VER
708#pragma warning(pop)
709#endif
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
Coordinate is the lightweight class used to store coordinates.
Definition Coordinate.h:220
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:241
std::set< const Coordinate *, CoordinateLessThan > ConstSet
A set of const Coordinate pointers.
Definition Coordinate.h:228
std::vector< Coordinate > Vect
A vector of Coordinate objects (real object, not pointers)
Definition Coordinate.h:238
std::vector< const Coordinate * > ConstVect
A vector of const Coordinate pointers.
Definition Coordinate.h:232
std::stack< const Coordinate * > ConstStack
A stack of const Coordinate pointers.
Definition Coordinate.h:235
bool equals3D(const Coordinate &other) const
3D comparison
Definition Coordinate.h:281
double z
z-coordinate
Definition Coordinate.h:244
bool operator<(const CoordinateXY &a, const CoordinateXY &b)
Strict weak ordering operator for Coordinate.
Definition Coordinate.h:470
Basic namespace for all GEOS functionalities.
Definition geos.h:38
Strict weak ordering Functor for Coordinate.
Definition Coordinate.h:445