1 // Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
2 //
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License, version 2.0,
5 // as published by the Free Software Foundation.
6 //
7 // This program is also distributed with certain software (including
8 // but not limited to OpenSSL) that is licensed under separate terms,
9 // as designated in a particular file or component or in included license
10 // documentation. The authors of MySQL hereby grant you an additional
11 // permission to link the program and your derivative works with the
12 // separately licensed software that they have included with MySQL.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License, version 2.0, for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22
23 #include "sql/gis/geometries.h"
24
25 #include <utility> // std::swap
26
27 #include "my_dbug.h"
28 #include "sql/gis/geometries_cs.h"
29 #include "sql/gis/geometry_visitor.h"
30
31 namespace gis {
32
accept(Geometry_visitor * v)33 bool Point::accept(Geometry_visitor *v) { return v->visit(this); }
34
35 template <>
get() const36 double Point::get<0>() const {
37 return m_x;
38 }
39
40 template <>
get() const41 double Point::get<1>() const {
42 return m_y;
43 }
44
x() const45 double Point::x() const { return get<0>(); }
46
y() const47 double Point::y() const { return get<1>(); }
48
49 template <>
set(double d)50 void Point::set<0>(double d) {
51 m_x = d;
52 }
53
54 template <>
set(double d)55 void Point::set<1>(double d) {
56 m_y = d;
57 }
58
x(double d)59 void Point::x(double d) { set<0>(d); }
60
y(double d)61 void Point::y(double d) { set<1>(d); }
62
accept(Geometry_visitor * v)63 bool Cartesian_linestring::accept(Geometry_visitor *v) {
64 if (!v->visit_enter(this) && m_points.size() > 0) {
65 if (m_points[0].accept(v)) return true;
66 for (decltype(m_points)::size_type i = 1; i < m_points.size(); i++) {
67 if (v->visit(this) || m_points[i].accept(v)) return true;
68 }
69 }
70 return v->visit_leave(this);
71 }
72
push_back(const Point & pt)73 void Cartesian_linestring::push_back(const Point &pt) {
74 DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kCartesian);
75 m_points.push_back(static_cast<const Cartesian_point &>(pt));
76 }
77
push_back(Point && pt)78 void Cartesian_linestring::push_back(Point &&pt) {
79 DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kCartesian);
80 m_points.push_back(static_cast<Cartesian_point &&>(pt));
81 }
82
empty() const83 bool Cartesian_linestring::empty() const { return m_points.empty(); }
84
accept(Geometry_visitor * v)85 bool Geographic_linestring::accept(Geometry_visitor *v) {
86 if (!v->visit_enter(this) && m_points.size() > 0) {
87 if (m_points[0].accept(v)) return true;
88 for (decltype(m_points)::size_type i = 1; i < m_points.size(); i++) {
89 if (v->visit(this) || m_points[i].accept(v)) return true;
90 }
91 }
92 return v->visit_leave(this);
93 }
94
push_back(const Point & pt)95 void Geographic_linestring::push_back(const Point &pt) {
96 DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kGeographic);
97 m_points.push_back(static_cast<const Geographic_point &>(pt));
98 }
99
push_back(Point && pt)100 void Geographic_linestring::push_back(Point &&pt) {
101 DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kGeographic);
102 m_points.push_back(static_cast<Geographic_point &&>(pt));
103 }
104
empty() const105 bool Geographic_linestring::empty() const { return m_points.empty(); }
106
accept(Geometry_visitor * v)107 bool Cartesian_linearring::accept(Geometry_visitor *v) {
108 if (!v->visit_enter(this) && m_points.size() > 0) {
109 if (m_points[0].accept(v)) return true;
110 for (decltype(m_points)::size_type i = 1; i < m_points.size(); i++) {
111 if (v->visit(this) || m_points[i].accept(v)) return true;
112 }
113 }
114 return v->visit_leave(this);
115 }
116
accept(Geometry_visitor * v)117 bool Geographic_linearring::accept(Geometry_visitor *v) {
118 if (!v->visit_enter(this) && m_points.size() > 0) {
119 if (m_points[0].accept(v)) return true;
120 for (decltype(m_points)::size_type i = 1; i < m_points.size(); i++) {
121 if (v->visit(this) || m_points[i].accept(v)) return true;
122 }
123 }
124 return v->visit_leave(this);
125 }
126
accept(Geometry_visitor * v)127 bool Cartesian_polygon::accept(Geometry_visitor *v) {
128 if (!v->visit_enter(this)) {
129 if (m_exterior_ring.accept(v)) return true;
130 for (auto &&ring : m_interior_rings) {
131 if (v->visit(this) || ring.accept(v)) return true;
132 }
133 }
134 return v->visit_leave(this);
135 }
136
push_back(const Linearring & lr)137 void Cartesian_polygon::push_back(const Linearring &lr) {
138 DBUG_ASSERT(lr.coordinate_system() == Coordinate_system::kCartesian);
139 if (m_exterior_ring.empty() && m_interior_rings.empty())
140 m_exterior_ring = static_cast<const Cartesian_linearring &>(lr);
141 else
142 m_interior_rings.push_back(static_cast<const Cartesian_linearring &>(lr));
143 }
144
push_back(Linearring && lr)145 void Cartesian_polygon::push_back(Linearring &&lr) {
146 DBUG_ASSERT(lr.coordinate_system() == Coordinate_system::kCartesian);
147 if (m_exterior_ring.empty() && m_interior_rings.empty())
148 m_exterior_ring = static_cast<Cartesian_linearring &&>(lr);
149 else
150 m_interior_rings.push_back(static_cast<Cartesian_linearring &&>(lr));
151 }
152
empty() const153 bool Cartesian_polygon::empty() const {
154 return m_exterior_ring.empty() && m_interior_rings.empty();
155 }
156
size() const157 std::size_t Cartesian_polygon::size() const {
158 std::size_t sz = m_interior_rings.size();
159 if (!m_exterior_ring.empty()) sz++;
160 return sz;
161 }
162
interior_ring(std::size_t n)163 Linearring &Cartesian_polygon::interior_ring(std::size_t n) {
164 return m_interior_rings[n];
165 }
166
accept(Geometry_visitor * v)167 bool Geographic_polygon::accept(Geometry_visitor *v) {
168 if (!v->visit_enter(this)) {
169 if (m_exterior_ring.accept(v)) return true;
170 for (auto &&ring : m_interior_rings) {
171 if (v->visit(this) || ring.accept(v)) return true;
172 }
173 }
174 return v->visit_leave(this);
175 }
176
cartesian_exterior_ring() const177 Cartesian_linearring &Cartesian_polygon::cartesian_exterior_ring() const {
178 return const_cast<Cartesian_linearring &>(m_exterior_ring);
179 }
180
181 // Doxygen doesn't understand decltype as it is used here.
182 #ifndef IN_DOXYGEN
183
184 decltype(Cartesian_polygon::m_interior_rings) &
interior_rings()185 Cartesian_polygon::interior_rings() {
186 return m_interior_rings;
187 }
188
189 decltype(Cartesian_polygon::m_interior_rings) const &
const_interior_rings() const190 Cartesian_polygon::const_interior_rings() const {
191 return m_interior_rings;
192 }
193
194 #endif // IN_DOXYGEN
195
push_back(const Linearring & lr)196 void Geographic_polygon::push_back(const Linearring &lr) {
197 DBUG_ASSERT(lr.coordinate_system() == Coordinate_system::kGeographic);
198 if (m_exterior_ring.empty() && m_interior_rings.empty())
199 m_exterior_ring = static_cast<const Geographic_linearring &>(lr);
200 else
201 m_interior_rings.push_back(static_cast<const Geographic_linearring &>(lr));
202 }
203
push_back(Linearring && lr)204 void Geographic_polygon::push_back(Linearring &&lr) {
205 DBUG_ASSERT(lr.coordinate_system() == Coordinate_system::kGeographic);
206 if (m_exterior_ring.empty() && m_interior_rings.empty())
207 m_exterior_ring = static_cast<Geographic_linearring &&>(lr);
208 else
209 m_interior_rings.push_back(static_cast<Geographic_linearring &&>(lr));
210 }
211
empty() const212 bool Geographic_polygon::empty() const {
213 return m_exterior_ring.empty() && m_interior_rings.empty();
214 }
215
size() const216 std::size_t Geographic_polygon::size() const {
217 std::size_t sz = m_interior_rings.size();
218 if (!m_exterior_ring.empty()) sz++;
219 return sz;
220 }
221
geographic_exterior_ring() const222 Geographic_linearring &Geographic_polygon::geographic_exterior_ring() const {
223 return const_cast<Geographic_linearring &>(m_exterior_ring);
224 }
225
interior_ring(std::size_t n)226 Linearring &Geographic_polygon::interior_ring(std::size_t n) {
227 return m_interior_rings[n];
228 }
229
230 // Doxygen doesn't understand decltype as it is used here.
231 #ifndef IN_DOXYGEN
232
233 decltype(Geographic_polygon::m_interior_rings) &
interior_rings()234 Geographic_polygon::interior_rings() {
235 return m_interior_rings;
236 }
237
238 decltype(Geographic_polygon::m_interior_rings) const &
const_interior_rings() const239 Geographic_polygon::const_interior_rings() const {
240 return m_interior_rings;
241 }
242
243 #endif // IN_DOXYGEN
244
Cartesian_geometrycollection(const Cartesian_geometrycollection & gc)245 Cartesian_geometrycollection::Cartesian_geometrycollection(
246 const Cartesian_geometrycollection &gc)
247 : m_geometries(
248 Malloc_allocator<Geometry *>(key_memory_Geometry_objects_data)) {
249 for (Geometry *g : gc.m_geometries) {
250 switch (g->type()) {
251 case Geometry_type::kPoint:
252 m_geometries.push_back(
253 new Cartesian_point(*static_cast<Cartesian_point *>(g)));
254 break;
255 case Geometry_type::kLinestring:
256 m_geometries.push_back(
257 new Cartesian_linestring(*static_cast<Cartesian_linestring *>(g)));
258 break;
259 case Geometry_type::kPolygon:
260 m_geometries.push_back(
261 new Cartesian_polygon(*static_cast<Cartesian_polygon *>(g)));
262 break;
263 case Geometry_type::kGeometrycollection:
264 m_geometries.push_back(new Cartesian_geometrycollection(
265 *static_cast<Cartesian_geometrycollection *>(g)));
266 break;
267 case Geometry_type::kMultipoint:
268 m_geometries.push_back(
269 new Cartesian_multipoint(*static_cast<Cartesian_multipoint *>(g)));
270 break;
271 case Geometry_type::kMultilinestring:
272 m_geometries.push_back(new Cartesian_multilinestring(
273 *static_cast<Cartesian_multilinestring *>(g)));
274 break;
275 case Geometry_type::kMultipolygon:
276 m_geometries.push_back(new Cartesian_multipolygon(
277 *static_cast<Cartesian_multipolygon *>(g)));
278 break;
279 default:
280 DBUG_ASSERT(false); /* purecov: inspected */
281 }
282 }
283 }
284
accept(Geometry_visitor * v)285 bool Cartesian_geometrycollection::accept(Geometry_visitor *v) {
286 if (!v->visit_enter(this) && m_geometries.size() > 0) {
287 if (m_geometries[0]->accept(v)) return true;
288 for (decltype(m_geometries)::size_type i = 1; i < m_geometries.size();
289 i++) {
290 if (v->visit(this) || m_geometries[i]->accept(v)) return true;
291 }
292 }
293 return v->visit_leave(this);
294 }
295
push_back(const Geometry & g)296 void Cartesian_geometrycollection::push_back(const Geometry &g) {
297 switch (g.type()) {
298 case Geometry_type::kPoint:
299 m_geometries.push_back(
300 new Cartesian_point(static_cast<const Cartesian_point &>(g)));
301 break;
302 case Geometry_type::kLinestring:
303 m_geometries.push_back(new Cartesian_linestring(
304 static_cast<const Cartesian_linestring &>(g)));
305 break;
306 case Geometry_type::kPolygon:
307 m_geometries.push_back(
308 new Cartesian_polygon(static_cast<const Cartesian_polygon &>(g)));
309 break;
310 case Geometry_type::kGeometrycollection:
311 m_geometries.push_back(new Cartesian_geometrycollection(
312 static_cast<const Cartesian_geometrycollection &>(g)));
313 break;
314 case Geometry_type::kMultipoint:
315 m_geometries.push_back(new Cartesian_multipoint(
316 static_cast<const Cartesian_multipoint &>(g)));
317 break;
318 case Geometry_type::kMultilinestring:
319 m_geometries.push_back(new Cartesian_multilinestring(
320 static_cast<const Cartesian_multilinestring &>(g)));
321 break;
322 case Geometry_type::kMultipolygon:
323 m_geometries.push_back(new Cartesian_multipolygon(
324 static_cast<const Cartesian_multipolygon &>(g)));
325 break;
326 default:
327 DBUG_ASSERT(false); /* purecov: inspected */
328 }
329 }
330
push_back(Geometry && g)331 void Cartesian_geometrycollection::push_back(Geometry &&g) {
332 switch (g.type()) {
333 case Geometry_type::kPoint:
334 m_geometries.push_back(
335 new Cartesian_point(static_cast<Cartesian_point &&>(g)));
336 break;
337 case Geometry_type::kLinestring:
338 m_geometries.push_back(
339 new Cartesian_linestring(static_cast<Cartesian_linestring &&>(g)));
340 break;
341 case Geometry_type::kPolygon:
342 m_geometries.push_back(
343 new Cartesian_polygon(static_cast<Cartesian_polygon &&>(g)));
344 break;
345 case Geometry_type::kGeometrycollection:
346 m_geometries.push_back(new Cartesian_geometrycollection(
347 static_cast<Cartesian_geometrycollection &&>(g)));
348 break;
349 case Geometry_type::kMultipoint:
350 m_geometries.push_back(
351 new Cartesian_multipoint(static_cast<Cartesian_multipoint &&>(g)));
352 break;
353 case Geometry_type::kMultilinestring:
354 m_geometries.push_back(new Cartesian_multilinestring(
355 static_cast<Cartesian_multilinestring &&>(g)));
356 break;
357 case Geometry_type::kMultipolygon:
358 m_geometries.push_back(new Cartesian_multipolygon(
359 static_cast<Cartesian_multipolygon &&>(g)));
360 break;
361 default:
362 DBUG_ASSERT(false); /* purecov: inspected */
363 }
364 }
365
empty() const366 bool Cartesian_geometrycollection::empty() const {
367 return m_geometries.empty();
368 }
369
Geographic_geometrycollection(const Geographic_geometrycollection & gc)370 Geographic_geometrycollection::Geographic_geometrycollection(
371 const Geographic_geometrycollection &gc)
372 : m_geometries(
373 Malloc_allocator<Geometry *>(key_memory_Geometry_objects_data)) {
374 for (Geometry *g : gc.m_geometries) {
375 switch (g->type()) {
376 case Geometry_type::kPoint:
377 m_geometries.push_back(
378 new Geographic_point(*static_cast<Geographic_point *>(g)));
379 break;
380 case Geometry_type::kLinestring:
381 m_geometries.push_back(new Geographic_linestring(
382 *static_cast<Geographic_linestring *>(g)));
383 break;
384 case Geometry_type::kPolygon:
385 m_geometries.push_back(
386 new Geographic_polygon(*static_cast<Geographic_polygon *>(g)));
387 break;
388 case Geometry_type::kGeometrycollection:
389 m_geometries.push_back(new Geographic_geometrycollection(
390 *static_cast<Geographic_geometrycollection *>(g)));
391 break;
392 case Geometry_type::kMultipoint:
393 m_geometries.push_back(new Geographic_multipoint(
394 *static_cast<Geographic_multipoint *>(g)));
395 break;
396 case Geometry_type::kMultilinestring:
397 m_geometries.push_back(new Geographic_multilinestring(
398 *static_cast<Geographic_multilinestring *>(g)));
399 break;
400 case Geometry_type::kMultipolygon:
401 m_geometries.push_back(new Geographic_multipolygon(
402 *static_cast<Geographic_multipolygon *>(g)));
403 break;
404 default:
405 DBUG_ASSERT(false); /* purecov: inspected */
406 }
407 }
408 }
409
accept(Geometry_visitor * v)410 bool Geographic_geometrycollection::accept(Geometry_visitor *v) {
411 if (!v->visit_enter(this) && m_geometries.size() > 0) {
412 if (m_geometries[0]->accept(v)) return true;
413 for (decltype(m_geometries)::size_type i = 1; i < m_geometries.size();
414 i++) {
415 if (v->visit(this) || m_geometries[i]->accept(v)) return true;
416 }
417 }
418 return v->visit_leave(this);
419 }
420
push_back(const Geometry & g)421 void Geographic_geometrycollection::push_back(const Geometry &g) {
422 switch (g.type()) {
423 case Geometry_type::kPoint:
424 m_geometries.push_back(
425 new Geographic_point(static_cast<const Geographic_point &>(g)));
426 break;
427 case Geometry_type::kLinestring:
428 m_geometries.push_back(new Geographic_linestring(
429 static_cast<const Geographic_linestring &>(g)));
430 break;
431 case Geometry_type::kPolygon:
432 m_geometries.push_back(
433 new Geographic_polygon(static_cast<const Geographic_polygon &>(g)));
434 break;
435 case Geometry_type::kGeometrycollection:
436 m_geometries.push_back(new Geographic_geometrycollection(
437 static_cast<const Geographic_geometrycollection &>(g)));
438 break;
439 case Geometry_type::kMultipoint:
440 m_geometries.push_back(new Geographic_multipoint(
441 static_cast<const Geographic_multipoint &>(g)));
442 break;
443 case Geometry_type::kMultilinestring:
444 m_geometries.push_back(new Geographic_multilinestring(
445 static_cast<const Geographic_multilinestring &>(g)));
446 break;
447 case Geometry_type::kMultipolygon:
448 m_geometries.push_back(new Geographic_multipolygon(
449 static_cast<const Geographic_multipolygon &>(g)));
450 break;
451 default:
452 DBUG_ASSERT(false); /* purecov: inspected */
453 }
454 }
455
push_back(Geometry && g)456 void Geographic_geometrycollection::push_back(Geometry &&g) {
457 switch (g.type()) {
458 case Geometry_type::kPoint:
459 m_geometries.push_back(
460 new Geographic_point(static_cast<Geographic_point &&>(g)));
461 break;
462 case Geometry_type::kLinestring:
463 m_geometries.push_back(
464 new Geographic_linestring(static_cast<Geographic_linestring &&>(g)));
465 break;
466 case Geometry_type::kPolygon:
467 m_geometries.push_back(
468 new Geographic_polygon(static_cast<Geographic_polygon &&>(g)));
469 break;
470 case Geometry_type::kGeometrycollection:
471 m_geometries.push_back(new Geographic_geometrycollection(
472 static_cast<Geographic_geometrycollection &&>(g)));
473 break;
474 case Geometry_type::kMultipoint:
475 m_geometries.push_back(
476 new Geographic_multipoint(static_cast<Geographic_multipoint &&>(g)));
477 break;
478 case Geometry_type::kMultilinestring:
479 m_geometries.push_back(new Geographic_multilinestring(
480 static_cast<Geographic_multilinestring &&>(g)));
481 break;
482 case Geometry_type::kMultipolygon:
483 m_geometries.push_back(new Geographic_multipolygon(
484 static_cast<Geographic_multipolygon &&>(g)));
485 break;
486 default:
487 DBUG_ASSERT(false); /* purecov: inspected */
488 }
489 }
490
empty() const491 bool Geographic_geometrycollection::empty() const {
492 return m_geometries.empty();
493 }
494
accept(Geometry_visitor * v)495 bool Cartesian_multipoint::accept(Geometry_visitor *v) {
496 if (!v->visit_enter(this) && m_points.size() > 0) {
497 if (m_points[0].accept(v)) return true;
498 for (decltype(m_points)::size_type i = 1; i < m_points.size(); i++) {
499 if (v->visit(this) || m_points[i].accept(v)) return true;
500 }
501 }
502 return v->visit_leave(this);
503 }
504
push_back(const Geometry & pt)505 void Cartesian_multipoint::push_back(const Geometry &pt) {
506 DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kCartesian);
507 m_points.push_back(static_cast<const Cartesian_point &>(pt));
508 }
509
push_back(Geometry && pt)510 void Cartesian_multipoint::push_back(Geometry &&pt) {
511 DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kCartesian);
512 m_points.push_back(static_cast<Cartesian_point &&>(pt));
513 }
514
empty() const515 bool Cartesian_multipoint::empty() const { return m_points.empty(); }
516
accept(Geometry_visitor * v)517 bool Geographic_multipoint::accept(Geometry_visitor *v) {
518 if (!v->visit_enter(this) && m_points.size() > 0) {
519 if (m_points[0].accept(v)) return true;
520 for (decltype(m_points)::size_type i = 1; i < m_points.size(); i++) {
521 if (v->visit(this) || m_points[i].accept(v)) return true;
522 }
523 }
524 return v->visit_leave(this);
525 }
526
push_back(const Geometry & pt)527 void Geographic_multipoint::push_back(const Geometry &pt) {
528 DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kGeographic);
529 m_points.push_back(static_cast<const Geographic_point &>(pt));
530 }
531
push_back(Geometry && pt)532 void Geographic_multipoint::push_back(Geometry &&pt) {
533 DBUG_ASSERT(pt.coordinate_system() == Coordinate_system::kGeographic);
534 m_points.push_back(static_cast<Geographic_point &&>(pt));
535 }
536
empty() const537 bool Geographic_multipoint::empty() const { return m_points.empty(); }
538
accept(Geometry_visitor * v)539 bool Cartesian_multilinestring::accept(Geometry_visitor *v) {
540 if (!v->visit_enter(this) && m_linestrings.size() > 0) {
541 if (m_linestrings[0].accept(v)) return true;
542 for (decltype(m_linestrings)::size_type i = 1; i < m_linestrings.size();
543 i++) {
544 if (v->visit(this) || m_linestrings[i].accept(v)) return true;
545 }
546 }
547 return v->visit_leave(this);
548 }
549
push_back(const Geometry & ls)550 void Cartesian_multilinestring::push_back(const Geometry &ls) {
551 DBUG_ASSERT(ls.coordinate_system() == Coordinate_system::kCartesian);
552 m_linestrings.push_back(static_cast<const Cartesian_linestring &>(ls));
553 }
554
push_back(Geometry && ls)555 void Cartesian_multilinestring::push_back(Geometry &&ls) {
556 DBUG_ASSERT(ls.coordinate_system() == Coordinate_system::kCartesian);
557 m_linestrings.push_back(static_cast<Cartesian_linestring &&>(ls));
558 }
559
empty() const560 bool Cartesian_multilinestring::empty() const { return m_linestrings.empty(); }
561
accept(Geometry_visitor * v)562 bool Geographic_multilinestring::accept(Geometry_visitor *v) {
563 if (!v->visit_enter(this) && m_linestrings.size() > 0) {
564 if (m_linestrings[0].accept(v)) return true;
565 for (decltype(m_linestrings)::size_type i = 1; i < m_linestrings.size();
566 i++) {
567 if (v->visit(this) || m_linestrings[i].accept(v)) return true;
568 }
569 }
570 return v->visit_leave(this);
571 }
572
push_back(const Geometry & ls)573 void Geographic_multilinestring::push_back(const Geometry &ls) {
574 DBUG_ASSERT(ls.coordinate_system() == Coordinate_system::kGeographic);
575 m_linestrings.push_back(static_cast<const Geographic_linestring &>(ls));
576 }
577
push_back(Geometry && ls)578 void Geographic_multilinestring::push_back(Geometry &&ls) {
579 DBUG_ASSERT(ls.coordinate_system() == Coordinate_system::kGeographic);
580 m_linestrings.push_back(static_cast<Geographic_linestring &&>(ls));
581 }
582
empty() const583 bool Geographic_multilinestring::empty() const { return m_linestrings.empty(); }
584
accept(Geometry_visitor * v)585 bool Cartesian_multipolygon::accept(Geometry_visitor *v) {
586 if (!v->visit_enter(this) && m_polygons.size() > 0) {
587 if (m_polygons[0].accept(v)) return true;
588 for (decltype(m_polygons)::size_type i = 1; i < m_polygons.size(); i++) {
589 if (v->visit(this) || m_polygons[i].accept(v)) return true;
590 }
591 }
592 return v->visit_leave(this);
593 }
594
push_back(const Geometry & py)595 void Cartesian_multipolygon::push_back(const Geometry &py) {
596 DBUG_ASSERT(py.coordinate_system() == Coordinate_system::kCartesian);
597 m_polygons.push_back(static_cast<const Cartesian_polygon &>(py));
598 }
599
push_back(Geometry && py)600 void Cartesian_multipolygon::push_back(Geometry &&py) {
601 DBUG_ASSERT(py.coordinate_system() == Coordinate_system::kCartesian);
602 m_polygons.push_back(static_cast<Cartesian_polygon &&>(py));
603 }
604
empty() const605 bool Cartesian_multipolygon::empty() const { return m_polygons.empty(); }
606
accept(Geometry_visitor * v)607 bool Geographic_multipolygon::accept(Geometry_visitor *v) {
608 if (!v->visit_enter(this) && m_polygons.size() > 0) {
609 if (m_polygons[0].accept(v)) return true;
610 for (decltype(m_polygons)::size_type i = 1; i < m_polygons.size(); i++) {
611 if (v->visit(this) || m_polygons[i].accept(v)) return true;
612 }
613 }
614 return v->visit_leave(this);
615 }
616
push_back(const Geometry & py)617 void Geographic_multipolygon::push_back(const Geometry &py) {
618 DBUG_ASSERT(py.coordinate_system() == Coordinate_system::kGeographic);
619 m_polygons.push_back(static_cast<const Geographic_polygon &>(py));
620 }
621
push_back(Geometry && py)622 void Geographic_multipolygon::push_back(Geometry &&py) {
623 DBUG_ASSERT(py.coordinate_system() == Coordinate_system::kGeographic);
624 m_polygons.push_back(static_cast<Geographic_polygon &&>(py));
625 }
626
empty() const627 bool Geographic_multipolygon::empty() const { return m_polygons.empty(); }
628
type_to_name(Geometry_type type)629 const char *type_to_name(Geometry_type type) {
630 switch (type) {
631 case Geometry_type::kPoint:
632 return "POINT";
633 case Geometry_type::kLinestring:
634 return "LINESTRING";
635 case Geometry_type::kPolygon:
636 return "POLYGON";
637 case Geometry_type::kGeometrycollection:
638 return "GEOMCOLLECTION";
639 case Geometry_type::kMultipoint:
640 return "MULTIPOINT";
641 case Geometry_type::kMultilinestring:
642 return "MULTILINESTRING";
643 case Geometry_type::kMultipolygon:
644 return "MULTIPOLYGON";
645 default:
646 /* purecov: begin inspected */
647 DBUG_ASSERT(false);
648 return "UNKNOWN";
649 /* purecov: end */
650 }
651 }
652
653 } // namespace gis
654