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
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
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
217class GEOS_DLL Coordinate : public CoordinateXY {
218
219private:
220
221 static const Coordinate _nullCoord;
222
223public:
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
294class GEOS_DLL CoordinateXYM : public CoordinateXY {
295private:
296 static const CoordinateXYM _nullCoord;
297
298public:
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
344class GEOS_DLL CoordinateXYZM : public Coordinate {
345private:
346 static const CoordinateXYZM _nullCoord;
347
348public:
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
422inline CoordinateXYM&
423CoordinateXYM::operator=(const CoordinateXYZM& other) {
424 x = other.x;
425 y = other.y;
426 m = other.m;
427
428 return *this;
429}
430
431
433struct 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
458inline bool operator<(const CoordinateXY& a, const CoordinateXY& b)
459{
460 return CoordinateLessThan()(a, b);
461}
462
463
464// Generic accessors, XY
465
466template<>
467inline double CoordinateXY::get<Ordinate::X>() const
468{
469 return x;
470}
471
472template<>
473inline double CoordinateXY::get<Ordinate::Y>() const
474{
475 return y;
476}
477
478template<>
479inline double CoordinateXY::get<Ordinate::Z>() const
480{
481 return DEFAULT_Z;
482}
483
484template<>
485inline double CoordinateXY::get<Ordinate::M>() const
486{
487 return DEFAULT_M;
488}
489
490// Generic accessors, XYZ
491
492template<>
493inline double Coordinate::get<Ordinate::X>() const
494{
495 return x;
496}
497
498template<>
499inline double Coordinate::get<Ordinate::Y>() const
500{
501 return y;
502}
503
504template<>
505inline double Coordinate::get<Ordinate::Z>() const
506{
507 return z;
508}
509
510template<>
511inline double Coordinate::get<Ordinate::M>() const
512{
513 return DEFAULT_M;
514}
515
516// Generic accessors, XYM
517
518template<>
519inline double CoordinateXYM::get<Ordinate::X>() const
520{
521 return x;
522}
523
524template<>
525inline double CoordinateXYM::get<Ordinate::Y>() const
526{
527 return y;
528}
529
530template<>
531inline double CoordinateXYM::get<Ordinate::Z>() const
532{
533 return DEFAULT_Z;
534}
535
536template<>
537inline double CoordinateXYM::get<Ordinate::M>() const
538{
539 return m;
540}
541
542// Generic accessors, XYZM
543
544template<>
545inline double CoordinateXYZM::get<Ordinate::X>() const
546{
547 return x;
548}
549
550template<>
551inline double CoordinateXYZM::get<Ordinate::Y>() const
552{
553 return y;
554}
555
556template<>
557inline double CoordinateXYZM::get<Ordinate::Z>() const
558{
559 return z;
560}
561
562template<>
563inline double CoordinateXYZM::get<Ordinate::M>() const
564{
565 return m;
566}
567
568GEOS_DLL std::ostream& operator<< (std::ostream& os, const CoordinateXY& c);
569GEOS_DLL std::ostream& operator<< (std::ostream& os, const Coordinate& c);
570GEOS_DLL std::ostream& operator<< (std::ostream& os, const CoordinateXYM& c);
571GEOS_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
577namespace 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 geos.h:39
Strict weak ordering Functor for Coordinate.
Definition Coordinate.h:433