1 #ifndef SQL_GIS_GEOMETRIES_CS_H_INCLUDED
2 #define SQL_GIS_GEOMETRIES_CS_H_INCLUDED
3 
4 // Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
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
24 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
25 
26 /// @file
27 ///
28 /// This file declares the coordinate system specific subclasses of
29 /// the geometry class hierarchy. The rest of the hierarchy is defined
30 /// in geometries.h.
31 ///
32 /// For most of the server, including geometries.h should be
33 /// enough. This header is only needed if the code needs to access
34 /// coordinate system specific members.
35 ///
36 /// @see geometries.h
37 
38 #include <vector>
39 
40 #include "sql/gis/geometries.h"
41 #include "sql/malloc_allocator.h"
42 
43 namespace gis {
44 
45 /// A Cartesian 2d point.
46 class Cartesian_point : public Point {
47  public:
48   Cartesian_point() = default;
Cartesian_point(double x,double y)49   Cartesian_point(double x, double y) : Point(x, y) {}
coordinate_system()50   Coordinate_system coordinate_system() const override {
51     return Coordinate_system::kCartesian;
52   }
53 };
54 
55 /// A geographic (ellipsoidal) 2d point.
56 class Geographic_point : public Point {
57  public:
58   Geographic_point() = default;
Geographic_point(double x,double y)59   Geographic_point(double x, double y) : Point(x, y) {}
coordinate_system()60   Coordinate_system coordinate_system() const override {
61     return Coordinate_system::kGeographic;
62   }
63 };
64 
65 /// A Cartesian 2d linestring.
66 class Cartesian_linestring : public Linestring {
67  protected:
68   /// String of points constituting the linestring.
69   ///
70   /// The line starts in the first point, goes through all intermediate points,
71   /// and ends in the last point.
72   std::vector<Cartesian_point, Malloc_allocator<Cartesian_point>> m_points;
73 
74  public:
75   typedef decltype(m_points)::value_type value_type;
76   typedef decltype(m_points)::iterator iterator;
77   typedef decltype(m_points)::const_iterator const_iterator;
78 
Cartesian_linestring()79   Cartesian_linestring()
80       : m_points(Malloc_allocator<Cartesian_point>(
81             key_memory_Geometry_objects_data)) {}
82 
coordinate_system()83   Coordinate_system coordinate_system() const override {
84     return Coordinate_system::kCartesian;
85   }
86   bool accept(Geometry_visitor *v) override;
87   void push_back(const Point &pt) override;
88   void push_back(Point &&pt) override;
89   bool empty() const override;
size()90   std::size_t size() const override { return m_points.size(); }
resize(std::size_t count)91   void resize(std::size_t count) { m_points.resize(count); }
clear()92   void clear() noexcept override { m_points.clear(); }
93 
back()94   Cartesian_point &back() { return m_points.back(); }
back()95   const Cartesian_point &back() const { return m_points.back(); }
96 
begin()97   iterator begin() noexcept { return m_points.begin(); }
begin()98   const_iterator begin() const noexcept { return m_points.begin(); }
99 
end()100   iterator end() noexcept { return m_points.end(); }
end()101   const_iterator end() const noexcept { return m_points.end(); }
102 
103   Cartesian_point &operator[](std::size_t i) override { return m_points[i]; }
104   const Cartesian_point &operator[](std::size_t i) const override {
105     return m_points[i];
106   }
107 };
108 
109 /// A geographic (ellipsoidal) 2d linestring.
110 ///
111 /// The linestring follows the geodetic between each pair of points.
112 class Geographic_linestring : public Linestring {
113  protected:
114   /// String of points constituting the linestring.
115   ///
116   /// The line starts in the first point, goes through all intermediate points,
117   /// and ends in the last point.
118   std::vector<Geographic_point, Malloc_allocator<Geographic_point>> m_points;
119 
120  public:
121   typedef decltype(m_points)::value_type value_type;
122   typedef decltype(m_points)::iterator iterator;
123   typedef decltype(m_points)::const_iterator const_iterator;
124 
Geographic_linestring()125   Geographic_linestring()
126       : m_points(Malloc_allocator<Geographic_point>(
127             key_memory_Geometry_objects_data)) {}
128 
coordinate_system()129   Coordinate_system coordinate_system() const override {
130     return Coordinate_system::kGeographic;
131   }
132   bool accept(Geometry_visitor *v) override;
133   void push_back(const Point &pt) override;
134   void push_back(Point &&pt) override;
135   bool empty() const override;
size()136   std::size_t size() const override { return m_points.size(); }
resize(std::size_t count)137   void resize(std::size_t count) { m_points.resize(count); }
clear()138   void clear() noexcept override { m_points.clear(); }
139 
back()140   Geographic_point &back() { return m_points.back(); }
back()141   const Geographic_point &back() const { return m_points.back(); }
142 
begin()143   iterator begin() noexcept { return m_points.begin(); }
begin()144   const_iterator begin() const noexcept { return m_points.begin(); }
145 
end()146   iterator end() noexcept { return m_points.end(); }
end()147   const_iterator end() const noexcept { return m_points.end(); }
148 
149   Geographic_point &operator[](std::size_t i) override { return m_points[i]; }
150   const Geographic_point &operator[](std::size_t i) const override {
151     return m_points[i];
152   }
153 };
154 
155 /// A Cartesian 2d linear ring.
156 class Cartesian_linearring : public Cartesian_linestring, public Linearring {
157  public:
type()158   Geometry_type type() const override { return Linearring::type(); }
coordinate_system()159   Coordinate_system coordinate_system() const override {
160     return Coordinate_system::kCartesian;
161   }
162   bool accept(Geometry_visitor *v) override;
is_empty()163   bool is_empty() const override { return Cartesian_linestring::is_empty(); }
push_back(const gis::Point & pt)164   void push_back(const gis::Point &pt) override {
165     Cartesian_linestring::push_back(pt);
166   }
push_back(gis::Point && pt)167   void push_back(gis::Point &&pt) override {
168     Cartesian_linestring::push_back(std::forward<Point &&>(pt));
169   }
empty()170   bool empty() const override { return Cartesian_linestring::empty(); }
size()171   std::size_t size() const override { return Cartesian_linestring::size(); }
clear()172   void clear() noexcept override { Cartesian_linestring::clear(); }
173 
174   Cartesian_point &operator[](std::size_t i) override {
175     return Cartesian_linestring::operator[](i);
176   }
177   const Cartesian_point &operator[](std::size_t i) const override {
178     return Cartesian_linestring::operator[](i);
179   }
180 };
181 
182 /// A geographic (ellipsoidal) 2d linear ring.
183 class Geographic_linearring : public Geographic_linestring, public Linearring {
184  public:
type()185   Geometry_type type() const override { return Linearring::type(); }
coordinate_system()186   Coordinate_system coordinate_system() const override {
187     return Coordinate_system::kGeographic;
188   }
189   bool accept(Geometry_visitor *v) override;
is_empty()190   bool is_empty() const override { return Geographic_linestring::is_empty(); }
push_back(const gis::Point & pt)191   void push_back(const gis::Point &pt) override {
192     Geographic_linestring::push_back(pt);
193   }
push_back(gis::Point && pt)194   void push_back(gis::Point &&pt) override {
195     Geographic_linestring::push_back(std::forward<Point &&>(pt));
196   }
empty()197   bool empty() const override { return Geographic_linestring::empty(); }
size()198   std::size_t size() const override { return Geographic_linestring::size(); }
clear()199   void clear() noexcept override { Geographic_linestring::clear(); }
200 
201   Geographic_point &operator[](std::size_t i) override {
202     return Geographic_linestring::operator[](i);
203   }
204   const Geographic_point &operator[](std::size_t i) const override {
205     return Geographic_linestring::operator[](i);
206   }
207 };
208 
209 /// A Cartesian 2d polygon.
210 class Cartesian_polygon : public Polygon {
211  private:
212   /// Exterior ring.
213   Cartesian_linearring m_exterior_ring;
214 
215   /// Interior rings (holes).
216   std::vector<Cartesian_linearring, Malloc_allocator<Cartesian_linearring>>
217       m_interior_rings;
218 
219  public:
Cartesian_polygon()220   Cartesian_polygon()
221       : m_interior_rings(Malloc_allocator<Cartesian_linearring>(
222             key_memory_Geometry_objects_data)) {}
coordinate_system()223   Coordinate_system coordinate_system() const override {
224     return Coordinate_system::kCartesian;
225   }
226   bool accept(Geometry_visitor *v) override;
227   void push_back(const Linearring &lr) override;
228   void push_back(Linearring &&lr) override;
229   bool empty() const override;
230 
231   /// Get list of interior rings.
232   ///
233   /// This function is used by the interface to Boost.Geometry.
234   ///
235   /// @return The list of interior rings
236   decltype(m_interior_rings) &interior_rings();
237 
238   /// Get list of interior rings.
239   ///
240   /// This function is used by the interface to Boost.Geometry.
241   ///
242   /// @return The list of interior rings
243   decltype(m_interior_rings) const &const_interior_rings() const;
244 
245   std::size_t size() const override;
246 
247   /// Get the exterior ring.
248   ///
249   /// This function is used by the interface to Boost.Geometry.
250   ///
251   /// @return The exterior ring.
252   Cartesian_linearring &cartesian_exterior_ring() const;
exterior_ring()253   Linearring &exterior_ring() override { return m_exterior_ring; }
254 
255   Linearring &interior_ring(std::size_t n) override;
256 };
257 
258 /// A geographic (ellipsoidal) 2d polygon.
259 class Geographic_polygon : public Polygon {
260  private:
261   /// Exterior ring.
262   Geographic_linearring m_exterior_ring;
263 
264   /// Interior rings (holes).
265   std::vector<Geographic_linearring, Malloc_allocator<Geographic_linearring>>
266       m_interior_rings;
267 
268  public:
Geographic_polygon()269   Geographic_polygon()
270       : m_interior_rings(Malloc_allocator<Geographic_linearring>(
271             key_memory_Geometry_objects_data)) {}
coordinate_system()272   Coordinate_system coordinate_system() const override {
273     return Coordinate_system::kGeographic;
274   }
275   bool accept(Geometry_visitor *v) override;
276   void push_back(const Linearring &lr) override;
277   void push_back(Linearring &&lr) override;
278   bool empty() const override;
279 
280   /// Get list of interior rings.
281   ///
282   /// This function is used by the interface to Boost.Geometry.
283   ///
284   /// @return The list of interior rings
285   decltype(m_interior_rings) &interior_rings();
286 
287   /// Get list of interior rings.
288   ///
289   /// This function is used by the interface to Boost.Geometry.
290   ///
291   /// @return The list of interior rings
292   decltype(m_interior_rings) const &const_interior_rings() const;
293 
294   std::size_t size() const override;
295 
296   /// Get the exterior ring.
297   ///
298   /// This function is used by the interface to Boost.Geometry.
299   ///
300   /// @return The exterior ring.
301   Geographic_linearring &geographic_exterior_ring() const;
exterior_ring()302   Linearring &exterior_ring() override { return m_exterior_ring; }
303 
304   Linearring &interior_ring(std::size_t n) override;
305 };
306 
307 /// A Cartesian 2d geometry collection.
308 class Cartesian_geometrycollection : public Geometrycollection {
309  private:
310   /// List of geometries in the collection.
311   std::vector<Geometry *, Malloc_allocator<Geometry *>> m_geometries;
312 
313  public:
314   typedef decltype(m_geometries)::iterator iterator;
315   typedef decltype(m_geometries)::const_iterator const_iterator;
316 
Cartesian_geometrycollection()317   Cartesian_geometrycollection()
318       : m_geometries(
319             Malloc_allocator<Geometry *>(key_memory_Geometry_objects_data)) {}
320   Cartesian_geometrycollection(const Cartesian_geometrycollection &gc);
Cartesian_geometrycollection(Cartesian_geometrycollection && gc)321   Cartesian_geometrycollection(Cartesian_geometrycollection &&gc) noexcept
322       : m_geometries(
323             Malloc_allocator<Geometry *>(key_memory_Geometry_objects_data)) {
324     m_geometries = std::move(gc.m_geometries);
325   }
~Cartesian_geometrycollection()326   ~Cartesian_geometrycollection() override {
327     for (Geometry *g : m_geometries) {
328       delete g;
329     }
330   }
coordinate_system()331   Coordinate_system coordinate_system() const override {
332     return Coordinate_system::kCartesian;
333   }
334   bool accept(Geometry_visitor *v) override;
is_empty()335   bool is_empty() const override {
336     for (const auto g : m_geometries) {
337       if (!g->is_empty()) return false;
338     }
339     return true;
340   }
341   void push_back(const Geometry &g) override;
342   void push_back(Geometry &&g) override;
343   bool empty() const override;
size()344   std::size_t size() const override { return m_geometries.size(); }
resize(std::size_t count)345   void resize(std::size_t count) override { m_geometries.resize(count); }
clear()346   void clear() noexcept override { m_geometries.clear(); }
347 
begin()348   iterator begin() noexcept { return m_geometries.begin(); }
begin()349   const_iterator begin() const noexcept { return m_geometries.begin(); }
350 
end()351   iterator end() noexcept { return m_geometries.end(); }
end()352   const_iterator end() const noexcept { return m_geometries.end(); }
353 
354   Geometry &operator[](std::size_t i) override { return *m_geometries[i]; }
355   const Geometry &operator[](std::size_t i) const override {
356     return *m_geometries[i];
357   }
358 };
359 
360 /// A geographic (ellipsoidal) 2d geometry collection.
361 class Geographic_geometrycollection : public Geometrycollection {
362  private:
363   /// List of geometries in the collection.
364   std::vector<Geometry *, Malloc_allocator<Geometry *>> m_geometries;
365 
366  public:
367   typedef decltype(m_geometries)::iterator iterator;
368   typedef decltype(m_geometries)::const_iterator const_iterator;
369 
Geographic_geometrycollection()370   Geographic_geometrycollection()
371       : m_geometries(
372             Malloc_allocator<Geometry *>(key_memory_Geometry_objects_data)) {}
373   Geographic_geometrycollection(const Geographic_geometrycollection &gc);
Geographic_geometrycollection(Geographic_geometrycollection && gc)374   Geographic_geometrycollection(Geographic_geometrycollection &&gc) noexcept
375       : m_geometries(
376             Malloc_allocator<Geometry *>(key_memory_Geometry_objects_data)) {
377     m_geometries = std::move(gc.m_geometries);
378   }
~Geographic_geometrycollection()379   ~Geographic_geometrycollection() override {
380     for (Geometry *g : m_geometries) {
381       delete g;
382     }
383   }
coordinate_system()384   Coordinate_system coordinate_system() const override {
385     return Coordinate_system::kGeographic;
386   }
387   bool accept(Geometry_visitor *v) override;
is_empty()388   bool is_empty() const override {
389     for (const auto g : m_geometries) {
390       if (!g->is_empty()) return false;
391     }
392     return true;
393   }
394   void push_back(const Geometry &g) override;
395   void push_back(Geometry &&g) override;
396   bool empty() const override;
size()397   std::size_t size() const override { return m_geometries.size(); }
resize(std::size_t count)398   void resize(std::size_t count) override { m_geometries.resize(count); }
clear()399   void clear() noexcept override { m_geometries.clear(); }
400 
begin()401   iterator begin() noexcept { return m_geometries.begin(); }
begin()402   const_iterator begin() const noexcept { return m_geometries.begin(); }
403 
end()404   iterator end() noexcept { return m_geometries.end(); }
end()405   const_iterator end() const noexcept { return m_geometries.end(); }
406 
407   Geometry &operator[](std::size_t i) override { return *m_geometries[i]; }
408   const Geometry &operator[](std::size_t i) const override {
409     return *m_geometries[i];
410   }
411 };
412 
413 /// A Cartesian 2d multipoint.
414 class Cartesian_multipoint : public Multipoint {
415  private:
416   /// List of points in the collection.
417   std::vector<Cartesian_point, Malloc_allocator<Cartesian_point>> m_points;
418 
419  public:
420   typedef decltype(m_points)::value_type value_type;
421   typedef decltype(m_points)::iterator iterator;
422   typedef decltype(m_points)::const_iterator const_iterator;
423 
Cartesian_multipoint()424   Cartesian_multipoint()
425       : m_points(Malloc_allocator<Cartesian_point>(
426             key_memory_Geometry_objects_data)) {}
427 
coordinate_system()428   Coordinate_system coordinate_system() const override {
429     return Coordinate_system::kCartesian;
430   }
431   bool accept(Geometry_visitor *v) override;
is_empty()432   bool is_empty() const override {
433     for (const auto &pt : m_points) {
434       if (!pt.is_empty()) return false;
435     }
436     return true;
437   }
438   void push_back(const Geometry &g) override;
439   void push_back(Geometry &&g) override;
440   bool empty() const override;
size()441   std::size_t size() const override { return m_points.size(); }
resize(std::size_t count)442   void resize(std::size_t count) override { m_points.resize(count); }
clear()443   void clear() noexcept override { m_points.clear(); }
444 
begin()445   iterator begin() noexcept { return m_points.begin(); }
begin()446   const_iterator begin() const noexcept { return m_points.begin(); }
447 
end()448   iterator end() noexcept { return m_points.end(); }
end()449   const_iterator end() const noexcept { return m_points.end(); }
450 
451   Cartesian_point &operator[](std::size_t i) override { return m_points[i]; }
452   const Cartesian_point &operator[](std::size_t i) const override {
453     return m_points[i];
454   }
455 };
456 
457 /// A geographic (ellipsoidal) 2d multipoint.
458 class Geographic_multipoint : public Multipoint {
459  private:
460   /// List of points in the collection.
461   std::vector<Geographic_point, Malloc_allocator<Geographic_point>> m_points;
462 
463  public:
464   typedef decltype(m_points)::value_type value_type;
465   typedef decltype(m_points)::iterator iterator;
466   typedef decltype(m_points)::const_iterator const_iterator;
467 
Geographic_multipoint()468   Geographic_multipoint()
469       : m_points(Malloc_allocator<Geographic_point>(
470             key_memory_Geometry_objects_data)) {}
coordinate_system()471   Coordinate_system coordinate_system() const override {
472     return Coordinate_system::kGeographic;
473   }
474   bool accept(Geometry_visitor *v) override;
is_empty()475   bool is_empty() const override {
476     for (const auto &pt : m_points) {
477       if (!pt.is_empty()) return false;
478     }
479     return true;
480   }
481   void push_back(const Geometry &g) override;
482   void push_back(Geometry &&g) override;
483   bool empty() const override;
size()484   std::size_t size() const override { return m_points.size(); }
resize(std::size_t count)485   void resize(std::size_t count) override { m_points.resize(count); }
clear()486   void clear() noexcept override { m_points.clear(); }
487 
begin()488   iterator begin() noexcept { return m_points.begin(); }
begin()489   const_iterator begin() const noexcept { return m_points.begin(); }
490 
end()491   iterator end() noexcept { return m_points.end(); }
end()492   const_iterator end() const noexcept { return m_points.end(); }
493 
494   Geographic_point &operator[](std::size_t i) override { return m_points[i]; }
495   const Geographic_point &operator[](std::size_t i) const override {
496     return m_points[i];
497   }
498 };
499 
500 /// A Cartesian 2d multilinestring.
501 class Cartesian_multilinestring : public Multilinestring {
502  private:
503   /// List of linestrings in the collection.
504   std::vector<Cartesian_linestring, Malloc_allocator<Cartesian_linestring>>
505       m_linestrings;
506 
507  public:
508   typedef decltype(m_linestrings)::value_type value_type;
509   typedef decltype(m_linestrings)::iterator iterator;
510   typedef decltype(m_linestrings)::const_iterator const_iterator;
511 
Cartesian_multilinestring()512   Cartesian_multilinestring()
513       : m_linestrings(Malloc_allocator<Cartesian_linestring>(
514             key_memory_Geometry_objects_data)) {}
515 
coordinate_system()516   Coordinate_system coordinate_system() const override {
517     return Coordinate_system::kCartesian;
518   }
519   bool accept(Geometry_visitor *v) override;
is_empty()520   bool is_empty() const override {
521     for (const auto &ls : m_linestrings) {
522       if (!ls.is_empty()) return false;
523     }
524     return true;
525   }
526   void push_back(const Geometry &g) override;
527   void push_back(Geometry &&g) override;
528   bool empty() const override;
size()529   std::size_t size() const override { return m_linestrings.size(); }
resize(std::size_t count)530   void resize(std::size_t count) override { m_linestrings.resize(count); }
clear()531   void clear() noexcept override { m_linestrings.clear(); }
532 
back()533   Cartesian_linestring &back() { return m_linestrings.back(); }
back()534   const Cartesian_linestring &back() const { return m_linestrings.back(); }
535 
begin()536   iterator begin() noexcept { return m_linestrings.begin(); }
begin()537   const_iterator begin() const noexcept { return m_linestrings.begin(); }
538 
end()539   iterator end() noexcept { return m_linestrings.end(); }
end()540   const_iterator end() const noexcept { return m_linestrings.end(); }
541 
542   Cartesian_linestring &operator[](std::size_t i) override {
543     return m_linestrings[i];
544   }
545   const Geometry &operator[](std::size_t i) const override {
546     return m_linestrings[i];
547   }
548 };
549 
550 /// A geographic (ellipsoidal) 2d multilinestring.
551 class Geographic_multilinestring : public Multilinestring {
552  private:
553   /// List of linestrings in the collection.
554   std::vector<Geographic_linestring, Malloc_allocator<Geographic_linestring>>
555       m_linestrings;
556 
557  public:
558   typedef decltype(m_linestrings)::value_type value_type;
559   typedef decltype(m_linestrings)::iterator iterator;
560   typedef decltype(m_linestrings)::const_iterator const_iterator;
561 
Geographic_multilinestring()562   Geographic_multilinestring()
563       : m_linestrings(Malloc_allocator<Geographic_linestring>(
564             key_memory_Geometry_objects_data)) {}
565 
coordinate_system()566   Coordinate_system coordinate_system() const override {
567     return Coordinate_system::kGeographic;
568   }
569   bool accept(Geometry_visitor *v) override;
is_empty()570   bool is_empty() const override {
571     for (const auto &ls : m_linestrings) {
572       if (!ls.is_empty()) return false;
573     }
574     return true;
575   }
576   void push_back(const Geometry &g) override;
577   void push_back(Geometry &&g) override;
578   bool empty() const override;
size()579   std::size_t size() const override { return m_linestrings.size(); }
resize(std::size_t count)580   void resize(std::size_t count) override { m_linestrings.resize(count); }
clear()581   void clear() noexcept override { m_linestrings.clear(); }
582 
back()583   Geographic_linestring &back() { return m_linestrings.back(); }
back()584   const Geographic_linestring &back() const { return m_linestrings.back(); }
585 
begin()586   iterator begin() noexcept { return m_linestrings.begin(); }
begin()587   const_iterator begin() const noexcept { return m_linestrings.begin(); }
588 
end()589   iterator end() noexcept { return m_linestrings.end(); }
end()590   const_iterator end() const noexcept { return m_linestrings.end(); }
591 
592   Geographic_linestring &operator[](std::size_t i) override {
593     return m_linestrings[i];
594   }
595   const Geometry &operator[](std::size_t i) const override {
596     return m_linestrings[i];
597   }
598 };
599 
600 /// A Cartesian 2d multipolygon.
601 class Cartesian_multipolygon : public Multipolygon {
602  private:
603   /// List of polygons in the collection.
604   std::vector<Cartesian_polygon, Malloc_allocator<Cartesian_polygon>>
605       m_polygons;
606 
607  public:
608   typedef decltype(m_polygons)::value_type value_type;
609   typedef decltype(m_polygons)::iterator iterator;
610   typedef decltype(m_polygons)::const_iterator const_iterator;
611 
Cartesian_multipolygon()612   Cartesian_multipolygon()
613       : m_polygons(Malloc_allocator<Cartesian_polygon>(
614             key_memory_Geometry_objects_data)) {}
615 
coordinate_system()616   Coordinate_system coordinate_system() const override {
617     return Coordinate_system::kCartesian;
618   }
619   bool accept(Geometry_visitor *v) override;
is_empty()620   bool is_empty() const override {
621     for (const auto &py : m_polygons) {
622       if (!py.is_empty()) return false;
623     }
624     return true;
625   }
626   void push_back(const Geometry &g) override;
627   void push_back(Geometry &&g) override;
628   bool empty() const override;
size()629   std::size_t size() const override { return m_polygons.size(); }
resize(std::size_t count)630   void resize(std::size_t count) override { m_polygons.resize(count); }
clear()631   void clear() noexcept override { m_polygons.clear(); }
632 
begin()633   iterator begin() noexcept { return m_polygons.begin(); }
begin()634   const_iterator begin() const noexcept { return m_polygons.begin(); }
635 
end()636   iterator end() noexcept { return m_polygons.end(); }
end()637   const_iterator end() const noexcept { return m_polygons.end(); }
638 
639   Cartesian_polygon &operator[](std::size_t i) override {
640     return m_polygons[i];
641   }
642   const Geometry &operator[](std::size_t i) const override {
643     return m_polygons[i];
644   }
645 };
646 
647 /// A geographic (ellipsoidal) 2d multipolygon.
648 class Geographic_multipolygon : public Multipolygon {
649  private:
650   /// List of polygons in the collection.
651   std::vector<Geographic_polygon, Malloc_allocator<Geographic_polygon>>
652       m_polygons;
653 
654  public:
655   typedef decltype(m_polygons)::value_type value_type;
656   typedef decltype(m_polygons)::iterator iterator;
657   typedef decltype(m_polygons)::const_iterator const_iterator;
658 
Geographic_multipolygon()659   Geographic_multipolygon()
660       : m_polygons(Malloc_allocator<Geographic_polygon>(
661             key_memory_Geometry_objects_data)) {}
662 
coordinate_system()663   Coordinate_system coordinate_system() const override {
664     return Coordinate_system::kGeographic;
665   }
666   bool accept(Geometry_visitor *v) override;
is_empty()667   bool is_empty() const override {
668     for (const auto &py : m_polygons) {
669       if (!py.is_empty()) return false;
670     }
671     return true;
672   }
673   void push_back(const Geometry &g) override;
674   void push_back(Geometry &&g) override;
675   bool empty() const override;
size()676   std::size_t size() const override { return m_polygons.size(); }
resize(std::size_t count)677   void resize(std::size_t count) override { m_polygons.resize(count); }
clear()678   void clear() noexcept override { m_polygons.clear(); }
679 
begin()680   iterator begin() noexcept { return m_polygons.begin(); }
begin()681   const_iterator begin() const noexcept { return m_polygons.begin(); }
682 
end()683   iterator end() noexcept { return m_polygons.end(); }
end()684   const_iterator end() const noexcept { return m_polygons.end(); }
685 
686   Geographic_polygon &operator[](std::size_t i) override {
687     return m_polygons[i];
688   }
689   const Geometry &operator[](std::size_t i) const override {
690     return m_polygons[i];
691   }
692 };
693 
694 }  // namespace gis
695 
696 #endif  // SQL_GIS_GEOMETRIES_CS_H_INCLUDED
697