1 #ifndef GIS_BG_TRAITS_INCLUDED
2 #define GIS_BG_TRAITS_INCLUDED
3 
4 /* Copyright (c) 2014, 2021, Oracle and/or its affiliates.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License, version 2.0,
8    as published by the Free Software Foundation.
9 
10    This program is also distributed with certain software (including
11    but not limited to OpenSSL) that is licensed under separate terms,
12    as designated in a particular file or component or in included license
13    documentation.  The authors of MySQL hereby grant you an additional
14    permission to link the program and your derivative works with the
15    separately licensed software that they have included with MySQL.
16 
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License, version 2.0, for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software Foundation,
24    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
25 */
26 
27 
28 /* This file defines all boost geometry traits. */
29 
30 #include <boost/static_assert.hpp>
31 
32 #include <boost/geometry/core/access.hpp>
33 #include <boost/geometry/core/coordinate_type.hpp>
34 #include <boost/geometry/core/coordinate_system.hpp>
35 #include <boost/geometry/core/coordinate_dimension.hpp>
36 #include <boost/geometry/core/interior_type.hpp>
37 #include <boost/geometry/core/ring_type.hpp>
38 #include <boost/geometry/core/exterior_ring.hpp>
39 #include <boost/geometry/core/interior_rings.hpp>
40 #include <boost/geometry/core/point_order.hpp>
41 #include <boost/geometry/core/closure.hpp>
42 #include <boost/geometry/core/tags.hpp>
43 #include <boost/geometry/core/cs.hpp>
44 #include <boost/geometry/multi/core/tags.hpp>
45 #include <boost/geometry/util/math.hpp>
46 #include <boost/concept/requires.hpp>
47 
48 #include <boost/geometry/geometries/concepts/point_concept.hpp>
49 #include <boost/geometry/geometries/concepts/linestring_concept.hpp>
50 #include <boost/geometry/geometries/concepts/polygon_concept.hpp>
51 
52 #include "spatial.h"
53 
54 /**
55   Helper class for spherical, spherical_equaltorial(i.e. geography)
56   coordinate systems. Every Geometry subclass will need one.
57 */
58 class Gis_point_spherical: public Gis_point
59 {
60 public:
61   explicit Gis_point_spherical(bool is_bg_adapter= true)
Gis_point(is_bg_adapter)62     :Gis_point(is_bg_adapter)
63   {
64   }
65 
66   /// @brief Default constructor, no initialization.
Gis_point_spherical(const void * ptr,size_t nbytes,const Flags_t & flags,srid_t srid)67   Gis_point_spherical(const void *ptr, size_t nbytes,
68                       const Flags_t &flags, srid_t srid)
69     :Gis_point(ptr, nbytes, flags, srid)
70   {
71   }
72 };
73 
74 
75 class Gis_multi_point_spherical: public Gis_wkb_vector<Gis_point_spherical>
76 {
77   typedef Gis_wkb_vector<Gis_point_spherical> base_type;
78 public:
79   /**** Boost Geometry Adapter Interface ******/
80   explicit Gis_multi_point_spherical(bool is_bg_adapter= true)
81     :base_type(NULL, 0, Flags_t(wkb_multipoint, 0),
82                default_srid, is_bg_adapter)
83   {}
84 
Gis_multi_point_spherical(const void * ptr,size_t nbytes,const Flags_t & flags,srid_t srid)85   Gis_multi_point_spherical(const void *ptr, size_t nbytes,
86                             const Flags_t &flags, srid_t srid)
87     :base_type(ptr, nbytes, flags, srid, true)
88   {
89     set_geotype(wkb_multipoint);
90   }
91 };
92 
93 
94 class Gis_line_string_spherical : public Gis_wkb_vector<Gis_point_spherical>
95 {
96   typedef Gis_wkb_vector<Gis_point_spherical> base_type;
97 public:
98   explicit Gis_line_string_spherical(bool is_bg_adapter= true)
99     :base_type(NULL, 0, Flags_t(wkb_linestring, 0), default_srid, is_bg_adapter)
100   {}
101 
Gis_line_string_spherical(const void * wkb,size_t len,const Flags_t & flags,srid_t srid)102   Gis_line_string_spherical(const void *wkb, size_t len,
103                             const Flags_t &flags, srid_t srid)
104     :base_type(wkb, len, flags, srid, true)
105   {
106     set_geotype(wkb_linestring);
107   }
108 };
109 
110 
111 class Gis_polygon_ring_spherical : public Gis_wkb_vector<Gis_point_spherical>
112 {
113   typedef Gis_wkb_vector<Gis_point_spherical> base_type;
114 public:
Gis_polygon_ring_spherical(const void * wkb,size_t nbytes,const Flags_t & flags,srid_t srid)115   Gis_polygon_ring_spherical(const void *wkb, size_t nbytes,
116                              const Flags_t &flags, srid_t srid)
117     :base_type(wkb, nbytes, flags, srid, true)
118   {
119     set_geotype(wkb_linestring);
120   }
121 
Gis_polygon_ring_spherical()122   Gis_polygon_ring_spherical()
123     :base_type(NULL, 0, Flags_t(Geometry::wkb_linestring, 0),
124                default_srid, true)
125   {}
126 };
127 
128 
129 /*
130   It's OK to derive from Gis_polygon because Gis_polygon doesn't derive from
131   Gis_wkb_vector<T>, and when its rings are accessed, the right ring type will
132   be used and hence the right point type will be used via iterator types.
133 */
134 class Gis_polygon_spherical : public Gis_polygon
135 {
136   typedef Gis_polygon base_type;
137 public:
138   typedef Gis_polygon_ring_spherical ring_type;
139   typedef Gis_wkb_vector<ring_type> inner_container_type;
140 
Gis_polygon_spherical(const void * wkb,size_t nbytes,const Flags_t & flags,srid_t srid)141   Gis_polygon_spherical(const void *wkb, size_t nbytes,
142                         const Flags_t &flags, srid_t srid)
143     :base_type(wkb, nbytes, flags, srid)
144   {
145   }
146 
base_type(isbgadapter)147   explicit Gis_polygon_spherical(bool isbgadapter= true) :base_type(isbgadapter)
148   {
149   }
150 
151   /*
152     We have to define them here because the ring_type isn't the same.
153     The Gis_polygon_ring_spherical has nothing extra than Gis_polygon_ring,
154     so we can do so.
155    */
outer()156   ring_type &outer() const
157   {
158     return *(reinterpret_cast<ring_type *>(&base_type::outer()));
159   }
160 
inners()161   inner_container_type &inners() const
162   {
163     return *(reinterpret_cast<inner_container_type *>(&base_type::inners()));
164   }
165 };
166 
167 
168 class Gis_multi_line_string_spherical :
169   public Gis_wkb_vector<Gis_line_string_spherical>
170 {
171   typedef Gis_wkb_vector<Gis_line_string_spherical> base_type;
172 public:
173   explicit Gis_multi_line_string_spherical(bool is_bg_adapter= true)
174     :base_type(NULL, 0, Flags_t(wkb_multilinestring, 0),
175                default_srid, is_bg_adapter)
176   {}
177 
Gis_multi_line_string_spherical(const void * ptr,size_t nbytes,const Flags_t & flags,srid_t srid)178   Gis_multi_line_string_spherical(const void *ptr, size_t nbytes,
179                                   const Flags_t &flags, srid_t srid)
180     :base_type(ptr, nbytes, flags, srid, true)
181   {
182     set_geotype(wkb_multilinestring);
183   }
184 };
185 
186 
187 class Gis_multi_polygon_spherical : public Gis_wkb_vector<Gis_polygon_spherical>
188 {
189   typedef Gis_wkb_vector<Gis_polygon_spherical> base_type;
190 public:
191   explicit Gis_multi_polygon_spherical(bool is_bg_adapter= true)
192     :base_type(NULL, 0, Flags_t(wkb_multipolygon, 0), default_srid, is_bg_adapter)
193   {}
194 
Gis_multi_polygon_spherical(const void * ptr,size_t nbytes,const Flags_t & flags,srid_t srid)195   Gis_multi_polygon_spherical(const void *ptr, size_t nbytes,
196                               const Flags_t &flags, srid_t srid)
197     :base_type(ptr, nbytes, flags, srid, true)
198   {
199     set_geotype(wkb_multipolygon);
200   }
201 };
202 
203 
204 // Boost Geometry traits.
205 namespace boost { namespace geometry
206 {
207 namespace traits
208 {
209 template<>
210 struct tag<Gis_point>
211 {
212   typedef boost::geometry::point_tag type;
213 };
214 
215 template<>
216 struct coordinate_type<Gis_point>
217 {
218   typedef double type;
219 };
220 
221 template<>
222 struct coordinate_system<Gis_point>
223 {
224   typedef boost::geometry::cs::cartesian type;
225 };
226 
227 template<>
228 struct dimension<Gis_point>
229   : boost::mpl::int_<GEOM_DIM>
230 {};
231 
232 template<std::size_t Dimension>
233 struct access<Gis_point, Dimension>
234 {
235   static inline double get(
236     Gis_point const& p)
237   {
238     return p.get<Dimension>();
239   }
240 
241   static inline void set(
242     Gis_point &p,
243     double const& value)
244   {
245     p.set<Dimension>(value);
246   }
247 };
248 
249 
250 template<>
251 struct tag<Gis_point_spherical>
252 {
253   typedef boost::geometry::point_tag type;
254 };
255 
256 template<>
257 struct coordinate_type<Gis_point_spherical>
258 {
259   typedef double type;
260 };
261 
262 template<>
263 struct coordinate_system<Gis_point_spherical>
264 {
265   typedef boost::geometry::cs::spherical_equatorial<
266     boost::geometry::degree> type;
267 };
268 
269 template<>
270 struct dimension<Gis_point_spherical>
271   : boost::mpl::int_<GEOM_DIM>
272 {};
273 
274 template<std::size_t Dimension>
275 struct access<Gis_point_spherical, Dimension>
276 {
277   static inline double get(
278     Gis_point_spherical const& p)
279   {
280     return p.get<Dimension>();
281   }
282 
283   static inline void set(
284     Gis_point_spherical &p,
285     double const& value)
286   {
287     p.set<Dimension>(value);
288   }
289 };
290 ////////////////////////////////// LINESTRING ////////////////////////////
291 template<>
292 struct tag<Gis_line_string>
293 {
294   typedef boost::geometry::linestring_tag type;
295 };
296 template<>
297 struct tag<Gis_line_string_spherical>
298 {
299   typedef boost::geometry::linestring_tag type;
300 };
301 
302 
303 ////////////////////////////////// POLYGON //////////////////////////////////
304 
305 
306 template<>
307 struct tag
308 <
309   Gis_polygon
310 >
311 {
312   typedef boost::geometry::polygon_tag type;
313 };
314 
315 
316 template<>
317 struct ring_const_type
318 <
319   Gis_polygon
320 >
321 {
322   typedef Gis_polygon::ring_type const& type;
323 };
324 
325 
326 template<>
327 struct ring_mutable_type
328 <
329   Gis_polygon
330 >
331 {
332   typedef Gis_polygon::ring_type& type;
333 };
334 
335 template<>
336 struct interior_const_type
337 <
338   Gis_polygon
339 >
340 {
341   typedef Gis_polygon::inner_container_type const& type;
342 };
343 
344 
345 template<>
346 struct interior_mutable_type
347 <
348   Gis_polygon
349 >
350 {
351   typedef Gis_polygon::inner_container_type& type;
352 };
353 
354 template<>
355 struct exterior_ring
356 <
357   Gis_polygon
358 >
359 {
360   typedef Gis_polygon polygon_type;
361 
362   static inline polygon_type::ring_type& get(polygon_type& p)
363   {
364     return p.outer();
365   }
366 
367   static inline polygon_type::ring_type const& get(
368           polygon_type const& p)
369   {
370     return p.outer();
371   }
372 };
373 
374 template<>
375 struct interior_rings
376 <
377   Gis_polygon
378 >
379 {
380   typedef Gis_polygon polygon_type;
381 
382   static inline polygon_type::inner_container_type& get(
383           polygon_type& p)
384   {
385     return p.inners();
386   }
387 
388   static inline polygon_type::inner_container_type const& get(
389           polygon_type const& p)
390   {
391     return p.inners();
392   }
393 };
394 
395 template<>
396 struct tag
397 <
398   Gis_polygon_spherical
399 >
400 {
401   typedef boost::geometry::polygon_tag type;
402 };
403 
404 
405 template<>
406 struct ring_const_type
407 <
408   Gis_polygon_spherical
409 >
410 {
411   typedef Gis_polygon_spherical::ring_type const& type;
412 };
413 
414 
415 template<>
416 struct ring_mutable_type
417 <
418   Gis_polygon_spherical
419 >
420 {
421   typedef Gis_polygon_spherical::ring_type& type;
422 };
423 
424 template<>
425 struct interior_const_type
426 <
427   Gis_polygon_spherical
428 >
429 {
430   typedef Gis_polygon_spherical::inner_container_type const& type;
431 };
432 
433 
434 template<>
435 struct interior_mutable_type
436 <
437   Gis_polygon_spherical
438 >
439 {
440   typedef Gis_polygon_spherical::inner_container_type& type;
441 };
442 
443 template<>
444 struct exterior_ring
445 <
446   Gis_polygon_spherical
447 >
448 {
449   typedef Gis_polygon_spherical polygon_type;
450 
451   static inline polygon_type::ring_type& get(polygon_type& p)
452   {
453     return p.outer();
454   }
455 
456   static inline polygon_type::ring_type const& get(
457           polygon_type const& p)
458   {
459     return p.outer();
460   }
461 };
462 
463 template<>
464 struct interior_rings
465 <
466   Gis_polygon_spherical
467 >
468 {
469   typedef Gis_polygon_spherical polygon_type;
470 
471   static inline polygon_type::inner_container_type& get(
472           polygon_type& p)
473   {
474     return p.inners();
475   }
476 
477   static inline polygon_type::inner_container_type const& get(
478           polygon_type const& p)
479   {
480     return p.inners();
481   }
482 };
483 ////////////////////////////////// RING //////////////////////////////////
484 template<>
485 struct point_order<Gis_polygon_ring>
486 {
487   static const order_selector value = counterclockwise;
488 };
489 
490 template<>
491 struct closure<Gis_polygon_ring>
492 {
493   static const closure_selector value = closed;
494 };
495 
496 template<>
497 struct tag<Gis_polygon_ring>
498 {
499   typedef boost::geometry::ring_tag type;
500 };
501 
502 
503 template<>
504 struct point_order<Gis_polygon_ring_spherical>
505 {
506   static const order_selector value = counterclockwise;
507 };
508 
509 template<>
510 struct closure<Gis_polygon_ring_spherical>
511 {
512   static const closure_selector value = closed;
513 };
514 
515 template<>
516 struct tag<Gis_polygon_ring_spherical>
517 {
518   typedef boost::geometry::ring_tag type;
519 };
520 
521 
522 ////////////////////////////////// MULTI GEOMETRIES /////////////////////////
523 
524 
525 /////////////////////////////////// multi linestring types /////////////////////
526 template<>
527 struct tag< Gis_multi_line_string>
528 {
529   typedef boost::geometry::multi_linestring_tag type;
530 };
531 
532 template<>
533 struct tag< Gis_multi_line_string_spherical>
534 {
535   typedef boost::geometry::multi_linestring_tag type;
536 };
537 
538 
539 /////////////////////////////////// multi point types /////////////////////
540 
541 
542 template<>
543 struct tag< Gis_multi_point>
544 {
545   typedef boost::geometry::multi_point_tag type;
546 };
547 
548 template<>
549 struct tag< Gis_multi_point_spherical>
550 {
551   typedef boost::geometry::multi_point_tag type;
552 };
553 
554 
555 /////////////////////////////////// multi polygon types /////////////////////
556 template<>
557 struct tag< Gis_multi_polygon>
558 {
559   typedef boost::geometry::multi_polygon_tag type;
560 };
561 
562 template<>
563 struct tag< Gis_multi_polygon_spherical>
564 {
565   typedef boost::geometry::multi_polygon_tag type;
566 };
567 
568 
569 } // namespace traits
570 
571 } // namespace geometry
572 } // namespace boost
573 
574 
575 #endif // !GIS_BG_TRAITS_INCLUDED
576