Shapes
GIS made easy, a lightweight header-only planar geometry library for Modern C++
point.hpp
1 #pragma once
2 
3 #include <ciso646>
4 #include <iostream>
5 #include <initializer_list>
6 #include <stdexcept>
7 #include <memory>
8 #include <tuple>
9 #include <string>
10 #include <type_traits>
11 #include <sstream>
12 #include <iomanip>
13 #include <regex>
14 #include <json/json.hpp>
15 #include <simo/geom/detail/geometry.hpp>
16 #include <simo/exceptions.hpp>
17 #include <simo/io/wkt_reader.hpp>
18 #include <simo/io/polyline.hpp>
19 
20 namespace simo
21 {
22 namespace shapes
23 {
24 
25 #ifdef __GNUC__
26 # pragma GCC diagnostic push
27 # pragma GCC diagnostic ignored "-Wpedantic"
28 #endif
29 
30 #ifdef __clang__
31 # pragma clang diagnostic push
32 # pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
33 # pragma clang diagnostic ignored "-Wnested-anon-types"
34 #endif
35 
36 #ifdef _MSC_VER
37 # pragma warning(push)
38 # pragma warning(disable : 4201)
39 #endif
40 
41 template <class T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
42 class basic_point : public basic_geometry<basic_point<T>>
43 {
44  public:
45  using value_type = T;
46  using reference = T&;
47  using const_reference = const T&;
48  using iterator = T*;
49  using const_iterator = const T*;
50  using difference_type = std::ptrdiff_t;
51  using size_type = size_t;
52  using reverse_iterator = std::reverse_iterator<iterator>;
53  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
54 
55  using point_type = basic_point;
56  using coord_type = T;
57  using coord_iterator = typename std::vector<coord_type>::iterator;
58  using coord_const_iterator = typename std::vector<coord_type>::const_iterator;
59 
60  static const size_type N = 2;
61 
62  union
63  {
64  struct
65  {
66  T x;
67  T y;
68  };
69 
70  struct
71  {
72  T lng;
73  T lat;
74  };
75 
76  T coords[N];
77  };
78 
83  : x(0), y(0) {}
84 
90  basic_point(T x, T y)
91  : x(x), y(y) {}
92 
93  explicit basic_point(coord_iterator begin, coord_iterator end)
94  {
96  assert(std::distance(begin, end) == N);
97  size_t i = 0;
98  for (auto it = begin; it != end; ++it)
99  {
100  coords[i++] = *it;
101  }
102  }
103 
104  explicit basic_point(coord_const_iterator begin, coord_const_iterator end)
105  {
107  assert(std::distance(begin, end) == N);
108  size_t i = 0;
109  for (auto it = begin; it != end; ++it)
110  {
111  coords[i++] = *it;
112  }
113  }
114 
115  size_type size() const noexcept
116  {
117  return this->ndim();
118  }
119 
120  // operators
121 
122  reference operator[](size_t pos)
123  {
124  assert(pos < N);
125  return coords[pos];
126  }
127 
128  friend bool operator==(const basic_point<T>& lhs, const basic_point<T>& rhs)
129  {
130  return lhs.x == rhs.x and lhs.y == rhs.y;
131  }
132 
133  friend bool operator!=(const basic_point<T>& lhs, const basic_point<T>& rhs)
134  {
135  return not operator==(lhs, rhs);
136  }
137 
138  // polyline
139 
140  static basic_point<T> from_polyline(const std::string& polyline, std::int32_t precision = 5)
141  {
142  auto coords = polyline::decode(polyline, precision);
143  if (coords.size() > N)
144  {
145  throw exceptions::parse_error("too many points");
146  }
147  return {coords[0], coords[1]};
148  }
149 
150  std::string polyline(std::int32_t precision = 5) const
151  {
152  return polyline::encode(lat, precision) + polyline::encode(lng, precision);
153  }
154 
155  size_type max_size() const
156  {
157  return N;
158  }
159 
160  bool empty()
161  {
162  return begin() == end();
163  }
164 
165  // iterators
166 
167  iterator begin()
168  {
169  return coords;
170  }
171 
172  iterator end()
173  {
174  return coords + N;
175  }
176 
177  const_iterator begin() const
178  {
179  return coords;
180  }
181  const_iterator end() const
182  {
183  return coords + N;
184  }
185 
186  reverse_iterator rbegin()
187  {
188  return coords + N - 1;
189  }
190 
191  reverse_iterator rend()
192  {
193  return coords - 1;
194  }
195 
196  const_reverse_iterator rbegin() const
197  {
198  return coords + N - 1;
199  }
200 
201  const_reverse_iterator rend() const
202  {
203  return coords - 1;
204  }
205 
206  private:
208  friend class basic_geometry<basic_point<T>>;
209 
211  geometry_type geom_type_() const noexcept
212  {
213  return geometry_type::POINT;
214  }
215 
217  bool is_closed_() const noexcept
218  {
219  return true;
220  }
221 
223  void throw_for_invalid_() const
224  {
225  // do nothing
226  }
227 
229  bounds_t bounds_() const
230  {
231  return {x, y, x, y};
232  }
233 
234  // json
235 
237  static basic_point<T> from_json_(const std::string& json)
238  {
240  try
241  {
242  auto j = nlohmann::json::parse(json);
243  auto geom_type = j.at("type").get<std::string>();
244  if (geom_type != "Point")
245  {
246  throw exceptions::parse_error("invalid geometry type");
247  }
248  auto coords = j.at("coordinates").get<std::vector<double>>();
249  return {coords.at(0), coords.at(1)};
250  }
251  catch (const std::out_of_range& e)
252  {
253  throw exceptions::parse_error("invalid json: " + std::string(e.what()));
254  }
255  catch (const nlohmann::json::exception& e)
256  {
257  throw exceptions::parse_error("invalid json: " + std::string(e.what()));
258  }
259  catch (const exceptions::geometry_error& e)
260  {
261  throw exceptions::parse_error("invalid geometry: " + std::string(e.what()));
262  }
263  }
264 
266  std::string json_(std::int32_t precision = -1) const
267  {
268  std::stringstream ss;
269  if (precision >= 0)
270  {
271  ss << std::setprecision(precision);
272  }
273  ss << "{\"type\":\"Point\",\"coordinates\":"
274  << "[" << x << "," << y << "]}";
275  return ss.str();
276  }
277 
278  // wkt
279 
281  static basic_point<T> from_wkt_(const std::string& wkt)
282  {
283  wkt_reader reader{};
284  auto result = reader.read(wkt);
285  auto data = result.data;
286  if (data.geom_type != geometry_type::POINT)
287  {
288  throw exceptions::parse_error("invalid wkt string");
289  }
290  return {data.coords[0], data.coords[1]};
291  }
292 
294  std::string wkt_(std::int32_t precision = -1) const
295  {
296  std::stringstream ss;
297  if (precision >= 0)
298  {
299  ss << std::setprecision(precision);
300  }
301  ss << "POINT "
302  << "(" << x << " " << y << ")";
303  return ss.str();
304  }
305 };
306 
307 // xyz
308 
309 template <class T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
310 class basic_point_z : public basic_geometry<basic_point_z<T>>
311 {
312  public:
313  using value_type = T;
314  using reference = T&;
315  using const_reference = const T&;
316  using iterator = T*;
317  using const_iterator = const T*;
318  using difference_type = std::ptrdiff_t;
319  using size_type = size_t;
320  using reverse_iterator = std::reverse_iterator<iterator>;
321  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
322 
323  using point_type = basic_point_z;
324  using coord_type = value_type;
325  using coord_iterator = typename std::vector<coord_type>::iterator;
326  using coord_const_iterator = typename std::vector<coord_type>::const_iterator;
327 
328  static const size_type N = 3;
329 
330  union
331  {
332  struct
333  {
334  T x;
335  T y;
336  T z;
337  };
338 
339  struct
340  {
341  T lng;
342  T lat;
343  T height;
344  };
345 
346  T coords[N];
347  };
348 
349  basic_point_z()
350  : x(0), y(0), z(0) {}
351 
352  basic_point_z(T x, T y, T z)
353  : x(x), y(y), z(z) {}
354 
355  explicit basic_point_z(coord_iterator begin, coord_iterator end)
356  {
357  assert(std::distance(begin, end) == N);
358  size_t i = 0;
359  for (auto it = begin; it != end; ++it)
360  {
361  coords[i++] = *it;
362  }
363  }
364 
365  explicit basic_point_z(coord_const_iterator begin, coord_const_iterator end)
366  {
367  assert(std::distance(begin, end) == N);
368  size_t i = 0;
369  for (auto it = begin; it != end; ++it)
370  {
371  coords[i++] = *it;
372  }
373  }
374 
375  std::size_t size() const noexcept
376  {
377  return this->ndim();
378  }
379 
380  // operators
381 
382  T& operator[](size_t pos)
383  {
384  assert(pos < N);
385  return coords[pos];
386  }
387 
388  friend bool operator==(const basic_point_z<T>& lhs, const basic_point_z<T>& rhs)
389  {
390  return lhs.x == rhs.x and lhs.y == rhs.y and lhs.z == rhs.z;
391  }
392 
393  friend bool operator!=(const basic_point_z<T>& lhs, const basic_point_z<T>& rhs)
394  {
395  return not operator==(lhs, rhs);
396  }
397 
398  size_type max_size() const
399  {
400  return N;
401  }
402 
403  bool empty()
404  {
405  return begin() == end();
406  }
407 
408  // iterators
409 
410  iterator begin()
411  {
412  return coords;
413  }
414 
415  iterator end()
416  {
417  return coords + N;
418  }
419 
420  const_iterator begin() const
421  {
422  return coords;
423  }
424  const_iterator end() const
425  {
426  return coords + N;
427  }
428 
429  reverse_iterator rbegin()
430  {
431  return coords + N - 1;
432  }
433 
434  reverse_iterator rend()
435  {
436  return coords - 1;
437  }
438 
439  const_reverse_iterator rbegin() const
440  {
441  return coords + N - 1;
442  }
443 
444  const_reverse_iterator rend() const
445  {
446  return coords - 1;
447  }
448 
449  private:
451  friend class basic_geometry<basic_point_z<T>>;
452 
454  geometry_type geom_type_() const noexcept
455  {
456  return geometry_type::POINTZ;
457  }
458 
460  bool is_closed_() const noexcept
461  {
462  return true;
463  }
464 
466  void throw_for_invalid_() const
467  {
468  // do nothing
469  }
470 
472  bounds_t bounds_() const
473  {
474  return {x, y, x, y};
475  }
476 
477  // json
478 
480  static basic_point_z<T> from_json_(const std::string& json)
481  {
483  try
484  {
485  auto j = nlohmann::json::parse(json);
486  auto geom_type = j.at("type").get<std::string>();
487  if (geom_type != "Point")
488  {
489  throw exceptions::parse_error("invalid geometry type");
490  }
491  auto coords = j.at("coordinates").get<std::vector<double>>();
492  return {coords.at(0), coords.at(1), coords.at(2)};
493  }
494  catch (const std::out_of_range& e)
495  {
496  throw exceptions::parse_error("invalid json: " + std::string(e.what()));
497  }
498  catch (const nlohmann::json::exception& e)
499  {
500  throw exceptions::parse_error("invalid json: " + std::string(e.what()));
501  }
502  catch (const exceptions::geometry_error& e)
503  {
504  throw exceptions::parse_error("invalid geometry: " + std::string(e.what()));
505  }
506  }
507 
509  std::string json_(std::int32_t precision = -1) const
510  {
511  std::stringstream ss;
512  if (precision >= 0)
513  {
514  ss << std::setprecision(precision);
515  }
516  ss << "{\"type\":\"Point\",\"coordinates\":"
517  << "[" << x << "," << y << "," << z << "]}";
518  return ss.str();
519  }
520 
521  // wkt
522 
524  static basic_point_z<T> from_wkt_(const std::string& wkt)
525  {
526  wkt_reader reader{};
527  auto result = reader.read(wkt);
528  auto data = result.data;
529  if (data.geom_type != geometry_type::POINTZ)
530  {
531  throw exceptions::parse_error("invalid wkt string");
532  }
533  return {data.coords[0], data.coords[1], data.coords[2]};
534  }
535 
537  std::string wkt_(std::int32_t precision = -1) const
538  {
539  std::stringstream ss;
540  if (precision >= 0)
541  {
542  ss << std::setprecision(precision);
543  }
544  ss << "POINT Z "
545  << "(" << x << " " << y << " " << z << ")";
546  return ss.str();
547  }
548 };
549 
550 // xym
551 
552 template <class T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
553 class basic_point_m : public basic_geometry<basic_point_m<T>>
554 {
555  public:
556  using value_type = T;
557  using reference = T&;
558  using const_reference = const T&;
559  using iterator = T*;
560  using const_iterator = const T*;
561  using difference_type = std::ptrdiff_t;
562  using size_type = size_t;
563  using reverse_iterator = std::reverse_iterator<iterator>;
564  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
565 
566  using point_type = basic_point_m;
567  using coord_type = value_type;
568  using coord_iterator = typename std::vector<coord_type>::iterator;
569  using coord_const_iterator = typename std::vector<coord_type>::const_iterator;
570 
571  static const size_type N = 3;
572 
573  union
574  {
575  struct
576  {
577  T x;
578  T y;
579  T m;
580  };
581 
582  struct
583  {
584  T lng;
585  T lat;
586  T measure;
587  };
588 
589  T coords[N];
590  };
591 
592  basic_point_m()
593  : x(0), y(0), m(0) {}
594 
595  basic_point_m(T x, T y, T m)
596  : x(x), y(y), m(m) {}
597 
598  explicit basic_point_m(coord_iterator begin, coord_iterator end)
599  {
600  assert(std::distance(begin, end) == N);
601  size_t i = 0;
602  for (auto it = begin; it != end; ++it)
603  {
604  coords[i++] = *it;
605  }
606  }
607 
608  explicit basic_point_m(coord_const_iterator begin, coord_const_iterator end)
609  {
610  assert(std::distance(begin, end) == N);
611  size_t i = 0;
612  for (auto it = begin; it != end; ++it)
613  {
614  coords[i++] = *it;
615  }
616  }
617 
618  std::size_t size() const noexcept
619  {
620  return this->ndim();
621  }
622 
623  // operators
624 
625  T& operator[](size_t pos)
626  {
627  assert(pos < N);
628  return coords[pos];
629  }
630 
631  friend bool operator==(const basic_point_m<T>& lhs, const basic_point_m<T>& rhs)
632  {
633  return lhs.x == rhs.x and lhs.y == rhs.y and lhs.m == rhs.m;
634  }
635 
636  friend bool operator!=(const basic_point_m<T>& lhs, const basic_point_m<T>& rhs)
637  {
638  return not operator==(lhs, rhs);
639  }
640 
641  size_type max_size() const
642  {
643  return N;
644  }
645 
646  bool empty()
647  {
648  return begin() == end();
649  }
650 
651  // iterators
652 
653  iterator begin()
654  {
655  return coords;
656  }
657 
658  iterator end()
659  {
660  return coords + N;
661  }
662 
663  const_iterator begin() const
664  {
665  return coords;
666  }
667  const_iterator end() const
668  {
669  return coords + N;
670  }
671 
672  reverse_iterator rbegin()
673  {
674  return coords + N - 1;
675  }
676 
677  reverse_iterator rend()
678  {
679  return coords - 1;
680  }
681 
682  const_reverse_iterator rbegin() const
683  {
684  return coords + N - 1;
685  }
686 
687  const_reverse_iterator rend() const
688  {
689  return coords - 1;
690  }
691 
692  private:
694  friend class basic_geometry<basic_point_m<T>>;
695 
697  geometry_type geom_type_() const noexcept
698  {
699  return geometry_type::POINTM;
700  }
701 
703  bool is_closed_() const noexcept
704  {
705  return true;
706  }
707 
709  void throw_for_invalid_() const
710  {
711  // do nothing
712  }
713 
715  bounds_t bounds_() const
716  {
717  return {x, y, x, y};
718  }
719 
720  // json
721 
723  static basic_point_m<T> from_json_(const std::string& json)
724  {
726  try
727  {
728  auto j = nlohmann::json::parse(json);
729  auto geom_type = j.at("type").get<std::string>();
730  if (geom_type != "Point")
731  {
732  throw exceptions::parse_error("invalid geometry type");
733  }
734  auto coords = j.at("coordinates").get<std::vector<double>>();
735  return {coords.at(0), coords.at(1), coords.at(2)};
736  }
737  catch (const std::out_of_range& e)
738  {
739  throw exceptions::parse_error("invalid json: " + std::string(e.what()));
740  }
741  catch (const nlohmann::json::exception& e)
742  {
743  throw exceptions::parse_error("invalid json: " + std::string(e.what()));
744  }
745  catch (const exceptions::geometry_error& e)
746  {
747  throw exceptions::parse_error("invalid geometry: " + std::string(e.what()));
748  }
749  }
750 
752  std::string json_(std::int32_t precision = -1) const
753  {
754  std::stringstream ss;
755  if (precision >= 0)
756  {
757  ss << std::setprecision(precision);
758  }
759  ss << "{\"type\":\"Point\",\"coordinates\":"
760  << "[" << x << "," << y << "," << m << "]}";
761  return ss.str();
762  }
763 
764  // wkt
765 
767  static basic_point_m<T> from_wkt_(const std::string& wkt)
768  {
769  wkt_reader reader{};
770  auto result = reader.read(wkt);
771  auto data = result.data;
772  if (data.geom_type != geometry_type::POINTM)
773  {
774  throw exceptions::parse_error("invalid wkt string");
775  }
776  return {data.coords[0], data.coords[1], data.coords[2]};
777  }
778 
779  std::string wkt_(std::int32_t precision = -1) const
780  {
781  std::stringstream ss;
782  if (precision >= 0)
783  {
784  ss << std::setprecision(precision);
785  }
786  ss << "POINT M "
787  << "(" << x << " " << y << " " << m << ")";
788  return ss.str();
789  }
790 };
791 
792 // xyzm
793 
794 template <class T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
795 class basic_point_zm : public basic_geometry<basic_point_zm<T>>
796 {
797  public:
798  using value_type = T;
799  using reference = T&;
800  using const_reference = const T&;
801  using iterator = T*;
802  using const_iterator = const T*;
803  using difference_type = std::ptrdiff_t;
804  using size_type = size_t;
805  using reverse_iterator = std::reverse_iterator<iterator>;
806  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
807 
808  using point_type = basic_point_zm;
809  using coord_type = value_type;
810  using coord_iterator = typename std::vector<coord_type>::iterator;
811  using coord_const_iterator = typename std::vector<coord_type>::const_iterator;
812 
813  static const size_type N = 4;
814 
815  union
816  {
817  struct
818  {
819  T x;
820  T y;
821  T z;
822  T m;
823  };
824 
825  struct
826  {
827  T lng;
828  T lat;
829  T height;
830  T measure;
831  };
832 
833  T coords[N];
834  };
835 
837  : x(0), y(0), z(0), m(0) {}
838 
839  basic_point_zm(T x, T y, T z, T m)
840  : x(x), y(y), z(z), m(m) {}
841 
842  explicit basic_point_zm(coord_iterator begin, coord_iterator end)
843  {
844  assert(std::distance(begin, end) == N);
845  size_t i = 0;
846  for (auto it = begin; it != end; ++it)
847  {
848  coords[i++] = *it;
849  }
850  }
851 
852  explicit basic_point_zm(coord_const_iterator begin, coord_const_iterator end)
853  {
854  assert(std::distance(begin, end) == N);
855  size_t i = 0;
856  for (auto it = begin; it != end; ++it)
857  {
858  coords[i++] = *it;
859  }
860  }
861 
862  std::size_t size() const noexcept
863  {
864  return this->ndim();
865  }
866 
867  // operators
868 
869  T& operator[](size_t pos)
870  {
871  assert(pos < N);
872  return coords[pos];
873  }
874 
875  friend bool operator==(const basic_point_zm<T>& lhs, const basic_point_zm<T>& rhs)
876  {
877  return lhs.x == rhs.x and lhs.y == rhs.y and lhs.z == rhs.z and lhs.m == rhs.m;
878  }
879 
880  friend bool operator!=(const basic_point_zm<T>& lhs, const basic_point_zm<T>& rhs)
881  {
882  return not operator==(lhs, rhs);
883  }
884 
885  size_type max_size() const
886  {
887  return N;
888  }
889 
890  bool empty()
891  {
892  return begin() == end();
893  }
894 
895  // iterators
896 
897  iterator begin()
898  {
899  return coords;
900  }
901 
902  iterator end()
903  {
904  return coords + N;
905  }
906 
907  const_iterator begin() const
908  {
909  return coords;
910  }
911  const_iterator end() const
912  {
913  return coords + N;
914  }
915 
916  reverse_iterator rbegin()
917  {
918  return coords + N - 1;
919  }
920 
921  reverse_iterator rend()
922  {
923  return coords - 1;
924  }
925 
926  const_reverse_iterator rbegin() const
927  {
928  return coords + N - 1;
929  }
930 
931  const_reverse_iterator rend() const
932  {
933  return coords - 1;
934  }
935 
936  private:
938  friend class basic_geometry<basic_point_zm<T>>;
939 
941  geometry_type geom_type_() const noexcept
942  {
943  return geometry_type::POINTZM;
944  }
945 
947  bool is_closed_() const noexcept
948  {
949  return true;
950  }
951 
953  void throw_for_invalid_() const
954  {
955  // do nothing
956  }
957 
959  bounds_t bounds_() const
960  {
961  return {x, y, x, y};
962  }
963 
964  // json
965 
967  static basic_point_zm<T> from_json_(const std::string& json)
968  {
970  try
971  {
972  auto j = nlohmann::json::parse(json);
973  auto geom_type = j.at("type").get<std::string>();
974  if (geom_type != "Point")
975  {
976  throw exceptions::parse_error("invalid geometry type");
977  }
978  auto coords = j.at("coordinates").get<std::vector<double>>();
979  return {coords.at(0), coords.at(1), coords.at(2), coords.at(3)};
980  }
981  catch (const std::out_of_range& e)
982  {
983  throw exceptions::parse_error("invalid json: " + std::string(e.what()));
984  }
985  catch (const nlohmann::json::exception& e)
986  {
987  throw exceptions::parse_error("invalid json: " + std::string(e.what()));
988  }
989  catch (const exceptions::geometry_error& e)
990  {
991  throw exceptions::parse_error("invalid geometry: " + std::string(e.what()));
992  }
993  }
994 
996  std::string json_(std::int32_t precision = -1) const
997  {
998  std::stringstream ss;
999  if (precision >= 0)
1000  {
1001  ss << std::setprecision(precision);
1002  }
1003  ss << "{\"type\":\"Point\",\"coordinates\":"
1004  << "[" << x << "," << y << "," << z << "," << m << "]}";
1005  return ss.str();
1006  }
1007 
1008  // wkt
1009 
1011  static basic_point_zm<T> from_wkt_(const std::string& wkt)
1012  {
1013  wkt_reader reader{};
1014  auto result = reader.read(wkt);
1015  auto data = result.data;
1016  if (data.geom_type != geometry_type::POINTZM)
1017  {
1018  throw exceptions::parse_error("invalid wkt string");
1019  }
1020  return {data.coords[0], data.coords[1], data.coords[2], data.coords[3]};
1021  }
1022 
1024  std::string wkt_(std::int32_t precision = -1) const
1025  {
1026  std::stringstream ss;
1027  if (precision >= 0)
1028  {
1029  ss << std::setprecision(precision);
1030  }
1031  ss << "POINT ZM "
1032  << "(" << x << " " << y << " " << z << " " << m << ")";
1033  return ss.str();
1034  }
1035 };
1036 
1037 #ifdef __GNUC__
1038 # pragma GCC diagnostic pop
1039 #endif
1040 
1041 #ifdef __clang__
1042 # pragma clang diagnostic pop
1043 #endif
1044 
1045 #ifdef _MSC_VER
1046 # pragma warning(pop)
1047 #endif
1048 
1049 template <typename>
1050 struct is_basic_point : std::false_type
1051 {};
1052 
1053 template <typename T>
1054 struct is_basic_point<basic_point<T>> : std::true_type
1055 {};
1056 
1057 template <typename>
1058 struct is_basic_point_z : std::false_type
1059 {};
1060 
1061 template <typename T>
1062 struct is_basic_point_z<basic_point_z<T>> : std::true_type
1063 {};
1064 
1065 template <typename>
1066 struct is_basic_point_m : std::false_type
1067 {};
1068 
1069 template <typename T>
1070 struct is_basic_point_m<basic_point_m<T>> : std::true_type
1071 {};
1072 
1073 template <typename>
1074 struct is_basic_point_zm : std::false_type
1075 {};
1076 
1077 template <typename T>
1078 struct is_basic_point_zm<basic_point_zm<T>> : std::true_type
1079 {};
1080 
1081 } // namespace shapes
1082 } // namespace simo
geometry_type geom_type() const noexcept
Returns the geometry type.
Definition: geometry.hpp:35
Base class for all geometries.
Definition: geometry.hpp:26
wkt_data data
the parser result data
Definition: wkt_parser.hpp:44
wkt_result read(const std::string &wkt)
parse the given wkt string
Definition: wkt_reader.hpp:47
Exception thrown when a geometry error is found.
Definition: exceptions.hpp:121
const char * what() const noexceptoverride
Returns the exception reason.
Definition: exceptions.hpp:39
Represents an axis-aligned bounding box.
Definition: bounds.hpp:18
basic_point(T x, T y)
Creates a point from the given coordinates.
Definition: point.hpp:90
basic_point()
Creates a empty point.
Definition: point.hpp:82
Exception thrown when an error has been found while parsing.
Definition: exceptions.hpp:67
std::string json(std::int32_t precision=-1) const
Dumps the geojson representation of the geometry.
Definition: geometry.hpp:255
std::string wkt(std::int32_t precision=-1) const
Dumps the wkt representation of the geometry.
Definition: geometry.hpp:283
basic_point(coord_iterator begin, coord_iterator end)
Definition: point.hpp:93
basic_point(coord_const_iterator begin, coord_const_iterator end)
Definition: point.hpp:104
size_t ndim() const noexcept
Returns the number of dimensions of the geometry.
Definition: geometry.hpp:142