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