1 /*
2   Copyright (c) 2017, 2020, Oracle and/or its affiliates.
3 
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License, version 2.0,
6   as published by the Free Software Foundation.
7 
8   This program is also distributed with certain software (including
9   but not limited to OpenSSL) that is licensed under separate terms,
10   as designated in a particular file or component or in included license
11   documentation.  The authors of MySQL hereby grant you an additional
12   permission to link the program and your derivative works with the
13   separately licensed software that they have included with MySQL.
14 
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License, version 2.0, for more details.
19 
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include "my_config.h"
26 
27 #include <gtest/gtest.h>
28 #include <memory>  // unique_ptr
29 
30 #include "sql/gis/geometries.h"
31 #include "sql/gis/geometries_cs.h"
32 #include "sql/gis/geometry_visitor.h"
33 
34 namespace geometries_unittest {
35 
36 struct Cartesian_types {
37   typedef gis::Cartesian_point Point;
38   typedef gis::Cartesian_linestring Linestring;
39   typedef gis::Cartesian_linearring Linearring;
40   typedef gis::Cartesian_polygon Polygon;
41   typedef gis::Cartesian_geometrycollection Geometrycollection;
42   typedef gis::Cartesian_multipoint Multipoint;
43   typedef gis::Cartesian_multilinestring Multilinestring;
44   typedef gis::Cartesian_multipolygon Multipolygon;
45 
coordinate_systemgeometries_unittest::Cartesian_types46   static gis::Coordinate_system coordinate_system() {
47     return gis::Coordinate_system::kCartesian;
48   }
49 };
50 
51 struct Geographic_types {
52   typedef gis::Geographic_point Point;
53   typedef gis::Geographic_linestring Linestring;
54   typedef gis::Geographic_linearring Linearring;
55   typedef gis::Geographic_polygon Polygon;
56   typedef gis::Geographic_geometrycollection Geometrycollection;
57   typedef gis::Geographic_multipoint Multipoint;
58   typedef gis::Geographic_multilinestring Multilinestring;
59   typedef gis::Geographic_multipolygon Multipolygon;
60 
coordinate_systemgeometries_unittest::Geographic_types61   static gis::Coordinate_system coordinate_system() {
62     return gis::Coordinate_system::kGeographic;
63   }
64 };
65 
66 template <typename Types>
67 class GeometriesTest : public ::testing::Test {
68  public:
GeometriesTest()69   GeometriesTest() {}
70 
~GeometriesTest()71   ~GeometriesTest() {}
72 };
73 
74 typedef ::testing::Types<Cartesian_types, Geographic_types> Types;
75 TYPED_TEST_SUITE(GeometriesTest, Types);
76 
TYPED_TEST(GeometriesTest,Point)77 TYPED_TEST(GeometriesTest, Point) {
78   typename TypeParam::Point pt;
79   EXPECT_EQ(gis::Geometry_type::kPoint, pt.type());
80   EXPECT_EQ(TypeParam::coordinate_system(), pt.coordinate_system());
81   EXPECT_TRUE(std::isnan(pt.x()));
82   EXPECT_TRUE(std::isnan(pt.y()));
83   EXPECT_TRUE(pt.is_empty());
84 
85   gis::Nop_visitor visitor;
86   EXPECT_FALSE(pt.accept(&visitor));
87 
88   typename TypeParam::Point pt2(0.0, 0.0);
89   EXPECT_EQ(0.0, pt2.x());
90   EXPECT_EQ(0.0, pt2.y());
91 
92   pt.x(-1.0);
93   pt.y(-1.0);
94   EXPECT_EQ(-1.0, pt.x());
95   EXPECT_EQ(-1.0, pt.y());
96   EXPECT_FALSE(pt.is_empty());
97 
98   pt.x(1.0);
99   pt.y(1.0);
100   EXPECT_EQ(1.0, pt.x());
101   EXPECT_EQ(1.0, pt.y());
102 
103   pt.x(1.7976931348623157e308);
104   pt.y(-1.7976931348623157e308);
105   EXPECT_EQ(1.7976931348623157e308, pt.x());
106   EXPECT_EQ(-1.7976931348623157e308, pt.y());
107 }
108 
TYPED_TEST(GeometriesTest,Curve)109 TYPED_TEST(GeometriesTest, Curve) {}
110 
TYPED_TEST(GeometriesTest,Linestring)111 TYPED_TEST(GeometriesTest, Linestring) {
112   typename TypeParam::Linestring ls;
113   EXPECT_EQ(gis::Geometry_type::kLinestring, ls.type());
114   EXPECT_EQ(TypeParam::coordinate_system(), ls.coordinate_system());
115   EXPECT_EQ(0U, ls.size());
116   EXPECT_TRUE(ls.empty());
117   EXPECT_TRUE(ls.is_empty());
118 
119   ls.push_back(typename TypeParam::Point(0.0, 0.0));
120   ls.push_back(typename TypeParam::Point(10.0, 10.0));
121   ls.push_back(typename TypeParam::Point(20.0, 0.0));
122   ls.push_back(typename TypeParam::Point(30.0, 10.0));
123   EXPECT_EQ(4U, ls.size());
124   EXPECT_FALSE(ls.empty());
125   EXPECT_FALSE(ls.is_empty());
126 
127   gis::Nop_visitor visitor;
128   EXPECT_FALSE(ls.accept(&visitor));
129 
130   EXPECT_EQ(0.0, ls[0].x());
131   EXPECT_EQ(0.0, ls[0].y());
132   EXPECT_EQ(30.0, ls[3].x());
133   EXPECT_EQ(10.0, ls[3].y());
134 }
135 
TYPED_TEST(GeometriesTest,Linearring)136 TYPED_TEST(GeometriesTest, Linearring) {
137   typename TypeParam::Linearring lr;
138   EXPECT_EQ(gis::Geometry_type::kLinestring, lr.type());
139   EXPECT_EQ(TypeParam::coordinate_system(), lr.coordinate_system());
140   EXPECT_EQ(0U, lr.size());
141   EXPECT_TRUE(lr.empty());
142   EXPECT_TRUE(lr.is_empty());
143 
144   lr.push_back(typename TypeParam::Point(0.0, 0.0));
145   lr.push_back(typename TypeParam::Point(10.0, 10.0));
146   lr.push_back(typename TypeParam::Point(20.0, 0.0));
147   lr.push_back(typename TypeParam::Point(0.0, 10.0));
148   EXPECT_EQ(4U, lr.size());
149   EXPECT_FALSE(lr.empty());
150   EXPECT_FALSE(lr.is_empty());
151 
152   gis::Nop_visitor visitor;
153   EXPECT_FALSE(lr.accept(&visitor));
154 
155   EXPECT_EQ(10.0, lr[1].x());
156   EXPECT_EQ(10.0, lr[1].y());
157   EXPECT_EQ(20.0, lr[2].x());
158   EXPECT_EQ(0.0, lr[2].y());
159 }
160 
TYPED_TEST(GeometriesTest,Surface)161 TYPED_TEST(GeometriesTest, Surface) {}
162 
TYPED_TEST(GeometriesTest,Polygon)163 TYPED_TEST(GeometriesTest, Polygon) {
164   typename TypeParam::Polygon py;
165   EXPECT_EQ(gis::Geometry_type::kPolygon, py.type());
166   EXPECT_EQ(TypeParam::coordinate_system(), py.coordinate_system());
167   EXPECT_EQ(0U, py.size());
168   EXPECT_TRUE(py.empty());
169   EXPECT_TRUE(py.is_empty());
170 
171   typename TypeParam::Linearring exterior;
172   exterior.push_back(typename TypeParam::Point(0.0, 0.0));
173   exterior.push_back(typename TypeParam::Point(10.0, 0.0));
174   exterior.push_back(typename TypeParam::Point(10.0, 10.0));
175   exterior.push_back(typename TypeParam::Point(0.0, 10.0));
176   exterior.push_back(typename TypeParam::Point(0.0, 0.0));
177   py.push_back(exterior);
178   EXPECT_FALSE(py.empty());
179   EXPECT_FALSE(py.is_empty());
180 
181   typename TypeParam::Linearring interior;
182   interior.push_back(typename TypeParam::Point(2.0, 2.0));
183   interior.push_back(typename TypeParam::Point(2.0, 8.0));
184   interior.push_back(typename TypeParam::Point(8.0, 8.0));
185   interior.push_back(typename TypeParam::Point(8.0, 2.0));
186   interior.push_back(typename TypeParam::Point(2.0, 2.0));
187   py.push_back(std::move(interior));
188 
189   EXPECT_EQ(2U, py.size());
190   EXPECT_FALSE(py.empty());
191   EXPECT_EQ(1U, py.interior_rings().size());
192   EXPECT_FALSE(py.interior_ring(0).empty());
193 
194   gis::Nop_visitor visitor;
195   EXPECT_FALSE(py.accept(&visitor));
196 }
197 
TYPED_TEST(GeometriesTest,Geometrycollection)198 TYPED_TEST(GeometriesTest, Geometrycollection) {
199   typename TypeParam::Geometrycollection gc;
200   EXPECT_EQ(gis::Geometry_type::kGeometrycollection, gc.type());
201   EXPECT_EQ(TypeParam::coordinate_system(), gc.coordinate_system());
202   EXPECT_TRUE(gc.empty());
203   EXPECT_TRUE(gc.is_empty());
204 
205   gc.push_back(typename TypeParam::Geometrycollection());
206   EXPECT_FALSE(gc.empty());
207   EXPECT_TRUE(gc.is_empty());
208 
209   typename TypeParam::Geometrycollection gc2;
210   gc2.push_back(typename TypeParam::Geometrycollection());
211   gc.push_back(std::move(gc2));
212   EXPECT_TRUE(gc.is_empty());
213 
214   gc.push_back(typename TypeParam::Point(0.0, 0.0));
215   gc.push_back(typename TypeParam::Point(10.0, 0.0));
216   gc.push_back(typename TypeParam::Point(10.0, 10.0));
217   gc.push_back(typename TypeParam::Point(0.0, 10.0));
218   gc.push_back(typename TypeParam::Point(0.0, 0.0));
219 
220   typename TypeParam::Linestring ls;
221   ls.push_back(typename TypeParam::Point(0.0, 0.0));
222   ls.push_back(typename TypeParam::Point(10.0, 0.0));
223   ls.push_back(typename TypeParam::Point(10.0, 10.0));
224   ls.push_back(typename TypeParam::Point(0.0, 10.0));
225   ls.push_back(typename TypeParam::Point(0.0, 0.0));
226   gc.push_back(std::move(ls));
227 
228   typename TypeParam::Linearring exterior;
229   exterior.push_back(typename TypeParam::Point(0.0, 0.0));
230   exterior.push_back(typename TypeParam::Point(10.0, 0.0));
231   exterior.push_back(typename TypeParam::Point(10.0, 10.0));
232   exterior.push_back(typename TypeParam::Point(0.0, 10.0));
233   exterior.push_back(typename TypeParam::Point(0.0, 0.0));
234   typename TypeParam::Polygon py;
235   py.push_back(std::move(exterior));
236   gc.push_back(std::move(py));
237 
238   typename TypeParam::Multipoint mpt;
239   mpt.push_back(typename TypeParam::Point(0.0, 0.0));
240   gc.push_back(std::move(mpt));
241 
242   typename TypeParam::Linestring ls2;
243   ls2.push_back(typename TypeParam::Point(0.0, 0.0));
244   ls2.push_back(typename TypeParam::Point(1.0, 1.0));
245   typename TypeParam::Multilinestring mls;
246   mls.push_back(std::move(ls2));
247   gc.push_back(std::move(mls));
248 
249   typename TypeParam::Multipolygon mpy;
250   gc.push_back(std::move(mpy));
251 
252   typename TypeParam::Geometrycollection inner_gc;
253   gc.push_back(std::move(inner_gc));
254 
255   EXPECT_EQ(13U, gc.size());
256   EXPECT_FALSE(gc.empty());
257   EXPECT_FALSE(gc.is_empty());
258 
259   gis::Nop_visitor visitor;
260   EXPECT_FALSE(gc.accept(&visitor));
261 
262   typename TypeParam::Geometrycollection gc_copy = gc;
263   EXPECT_EQ(13U, gc_copy.size());
264   EXPECT_FALSE(gc.empty());
265   EXPECT_FALSE(gc.is_empty());
266 }
267 
TYPED_TEST(GeometriesTest,Multipoint)268 TYPED_TEST(GeometriesTest, Multipoint) {
269   typename TypeParam::Multipoint mpt;
270   EXPECT_EQ(gis::Geometry_type::kMultipoint, mpt.type());
271   EXPECT_EQ(TypeParam::coordinate_system(), mpt.coordinate_system());
272   EXPECT_TRUE(mpt.empty());
273   EXPECT_TRUE(mpt.is_empty());
274 
275   mpt.push_back(typename TypeParam::Point(0.0, 0.0));
276   EXPECT_EQ(1U, mpt.size());
277   EXPECT_FALSE(mpt.empty());
278   EXPECT_FALSE(mpt.is_empty());
279 
280   mpt.push_back(typename TypeParam::Point(1.0, 1.0));
281   EXPECT_EQ(2U, mpt.size());
282 
283   gis::Nop_visitor visitor;
284   EXPECT_FALSE(mpt.accept(&visitor));
285 }
286 
TYPED_TEST(GeometriesTest,Multicurve)287 TYPED_TEST(GeometriesTest, Multicurve) {
288   std::unique_ptr<gis::Multicurve> mc(new
289                                       typename TypeParam::Multilinestring());
290   EXPECT_EQ(0U, mc->size());
291   EXPECT_TRUE(mc->empty());
292   EXPECT_TRUE(mc->is_empty());
293 
294   gis::Nop_visitor visitor;
295   EXPECT_FALSE(mc->accept(&visitor));
296 }
297 
TYPED_TEST(GeometriesTest,Multilinestring)298 TYPED_TEST(GeometriesTest, Multilinestring) {
299   typename TypeParam::Multilinestring mls;
300   EXPECT_EQ(gis::Geometry_type::kMultilinestring, mls.type());
301   EXPECT_EQ(TypeParam::coordinate_system(), mls.coordinate_system());
302   EXPECT_TRUE(mls.empty());
303   EXPECT_TRUE(mls.is_empty());
304 
305   typename TypeParam::Linestring ls;
306   ls.push_back(typename TypeParam::Point(0.0, 0.0));
307   ls.push_back(typename TypeParam::Point(10.0, 0.0));
308   ls.push_back(typename TypeParam::Point(10.0, 10.0));
309   ls.push_back(typename TypeParam::Point(0.0, 10.0));
310   ls.push_back(typename TypeParam::Point(0.0, 0.0));
311   mls.push_back(std::move(ls));
312   EXPECT_EQ(1U, mls.size());
313   EXPECT_FALSE(mls.empty());
314   EXPECT_FALSE(mls.is_empty());
315 
316   typename TypeParam::Linestring ls2;
317   ls.push_back(typename TypeParam::Point(0.0, 0.0));
318   ls.push_back(typename TypeParam::Point(20.0, 20.0));
319   mls.push_back(std::move(ls));
320   EXPECT_EQ(2U, mls.size());
321 
322   gis::Nop_visitor visitor;
323   EXPECT_FALSE(mls.accept(&visitor));
324 }
325 
TYPED_TEST(GeometriesTest,Multisurface)326 TYPED_TEST(GeometriesTest, Multisurface) {
327   std::unique_ptr<gis::Multisurface> ms(new typename TypeParam::Multipolygon());
328   EXPECT_EQ(0U, ms->size());
329   EXPECT_TRUE(ms->empty());
330   EXPECT_TRUE(ms->is_empty());
331 
332   gis::Nop_visitor visitor;
333   EXPECT_FALSE(ms->accept(&visitor));
334 }
335 
TYPED_TEST(GeometriesTest,Multipolygon)336 TYPED_TEST(GeometriesTest, Multipolygon) {
337   typename TypeParam::Multipolygon mpy;
338   EXPECT_EQ(gis::Geometry_type::kMultipolygon, mpy.type());
339   EXPECT_EQ(TypeParam::coordinate_system(), mpy.coordinate_system());
340   EXPECT_TRUE(mpy.empty());
341   EXPECT_TRUE(mpy.is_empty());
342 
343   typename TypeParam::Linearring exterior;
344   exterior.push_back(typename TypeParam::Point(0.0, 0.0));
345   exterior.push_back(typename TypeParam::Point(10.0, 0.0));
346   exterior.push_back(typename TypeParam::Point(10.0, 10.0));
347   exterior.push_back(typename TypeParam::Point(0.0, 10.0));
348   exterior.push_back(typename TypeParam::Point(0.0, 0.0));
349 
350   typename TypeParam::Linearring interior;
351   interior.push_back(typename TypeParam::Point(2.0, 2.0));
352   interior.push_back(typename TypeParam::Point(2.0, 8.0));
353   interior.push_back(typename TypeParam::Point(8.0, 8.0));
354   interior.push_back(typename TypeParam::Point(8.0, 2.0));
355   interior.push_back(typename TypeParam::Point(2.0, 2.0));
356 
357   typename TypeParam::Polygon py;
358   py.push_back(std::move(exterior));
359   py.push_back(std::move(interior));
360   mpy.push_back(std::move(py));
361   EXPECT_EQ(1U, mpy.size());
362   EXPECT_FALSE(mpy.empty());
363   EXPECT_FALSE(mpy.is_empty());
364 
365   mpy.push_back(typename TypeParam::Polygon());
366   EXPECT_EQ(2U, mpy.size());
367 
368   gis::Nop_visitor visitor;
369   EXPECT_FALSE(mpy.accept(&visitor));
370 }
371 
372 }  // namespace geometries_unittest
373