Line data Source code
1 : ///////////////////////////////////////////////////////////////////////////////
2 : //
3 : // Project: C++ Test Suite for GDAL/OGR
4 : // Purpose: Test ogr_wkb.h
5 : // Author: Even Rouault <even.rouault at spatialys.com>
6 : //
7 : ///////////////////////////////////////////////////////////////////////////////
8 : // Copyright (c) 2023, Even Rouault <even.rouault at spatialys.com>
9 : /*
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "gdal_unit_test.h"
30 :
31 : #include "ogr_geometry.h"
32 : #include "ogr_wkb.h"
33 :
34 : #include "gtest_include.h"
35 :
36 : #include <limits>
37 :
38 : namespace
39 : {
40 :
41 : struct test_ogr_wkb : public ::testing::Test
42 : {
43 : };
44 :
45 : class OGRWKBGetEnvelopeFixture
46 : : public test_ogr_wkb,
47 : public ::testing::WithParamInterface<std::tuple<
48 : const char *, double, double, double, double, const char *>>
49 : {
50 : static constexpr double INF = std::numeric_limits<double>::infinity();
51 :
52 : public:
53 : static std::vector<
54 : std::tuple<const char *, double, double, double, double, const char *>>
55 1 : GetTupleValues()
56 : {
57 : return {
58 : std::make_tuple("POINT(1 2)", 1, 2, 1, 2, "POINT"),
59 : std::make_tuple("POINT EMPTY", INF, INF, -INF, -INF, "POINT_EMPTY"),
60 : std::make_tuple("POINT Z (1 2 3)", 1, 2, 1, 2, "POINT_3D"),
61 : std::make_tuple("LINESTRING(3 4,1 2)", 1, 2, 3, 4, "LINESTRING"),
62 : std::make_tuple("LINESTRING EMPTY", INF, INF, -INF, -INF,
63 : "LINESTRING_EMPTY"),
64 : std::make_tuple("LINESTRING Z (3 4 5,1 2 6)", 1, 2, 3, 4,
65 : "LINESTRING_3D"),
66 : std::make_tuple("POLYGON((0 1,0 2,3 2,0 1))", 0, 1, 3, 2,
67 : "POLYGON"),
68 : std::make_tuple("POLYGON EMPTY", INF, INF, -INF, -INF,
69 : "POLYGON_EMPTY"),
70 : std::make_tuple("POLYGON Z ((0 1 10,0 2 20,3 2 20,0 1 10))", 0, 1,
71 : 3, 2, "POLYGON_3D"),
72 : std::make_tuple("MULTIPOINT((1 2),(3 4))", 1, 2, 3, 4,
73 : "MULTIPOINT"),
74 : std::make_tuple("MULTIPOINT EMPTY", INF, INF, -INF, -INF,
75 : "MULTIPOINT_EMPTY"),
76 : std::make_tuple("MULTIPOINT Z ((1 2 10),(3 4 20))", 1, 2, 3, 4,
77 : "MULTIPOINT_3D"),
78 : std::make_tuple("MULTILINESTRING((3 4,1 2),(5 6,7 8))", 1, 2, 7, 8,
79 : "MULTILINESTRING"),
80 : std::make_tuple("MULTILINESTRING EMPTY", INF, INF, -INF, -INF,
81 : "MULTILINESTRING_EMPTY"),
82 : std::make_tuple(
83 : "MULTILINESTRING Z ((3 4 10,1 2 20),(5 6 10,7 8 20))", 1, 2, 7,
84 : 8, "MULTILINESTRING_3D"),
85 : std::make_tuple(
86 : "MULTIPOLYGON(((0 1,0 2,3 2,0 1)),((0 -1,0 -2,-3 -2,0 -1)))",
87 : -3, -2, 3, 2, "MULTIPOLYGON"),
88 : std::make_tuple("MULTIPOLYGON EMPTY", INF, INF, -INF, -INF,
89 : "MULTIPOLYGON_EMPTY"),
90 : std::make_tuple("MULTIPOLYGON Z (((0 1 10,0 2 20,3 2 20,0 1 "
91 : "10)),((0 -1 -10,0 -2 -20,-3 -2 -20,0 -1 -10)))",
92 : -3, -2, 3, 2, "MULTIPOLYGON_3D"),
93 : std::make_tuple("GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4))", 1, 2,
94 : 3, 4, "GEOMETRYCOLLECTION"),
95 : std::make_tuple("CIRCULARSTRING(0 10,1 11,2 10)", 0, 10, 2, 11,
96 : "CIRCULARSTRING"),
97 : std::make_tuple("COMPOUNDCURVE((3 4,1 2))", 1, 2, 3, 4,
98 : "COMPOUNDCURVE"),
99 : std::make_tuple("CURVEPOLYGON((0 1,0 2,3 2,0 1))", 0, 1, 3, 2,
100 : "CURVEPOLYGON"),
101 : std::make_tuple("MULTICURVE((3 4,1 2),(5 6,7 8))", 1, 2, 7, 8,
102 : "MULTICURVE"),
103 : std::make_tuple(
104 : "MULTISURFACE(((0 1,0 2,3 2,0 1)),((0 -1,0 -2,-3 -2,0 -1)))",
105 : -3, -2, 3, 2, "MULTISURFACE"),
106 : std::make_tuple("TRIANGLE((0 1,0 2,3 2,0 1))", 0, 1, 3, 2,
107 : "TRIANGLE"),
108 : std::make_tuple("POLYHEDRALSURFACE(((0 1,0 2,3 2,0 1)))", 0, 1, 3,
109 : 2, "POLYHEDRALSURFACE"),
110 : std::make_tuple("TIN(((0 1,0 2,3 2,0 1)))", 0, 1, 3, 2, "TIN"),
111 1 : };
112 : }
113 : };
114 :
115 55 : TEST_P(OGRWKBGetEnvelopeFixture, test)
116 : {
117 27 : const char *pszInput = std::get<0>(GetParam());
118 27 : const double dfExpectedMinX = std::get<1>(GetParam());
119 27 : const double dfExpectedMinY = std::get<2>(GetParam());
120 27 : const double dfExpectedMaxX = std::get<3>(GetParam());
121 27 : const double dfExpectedMaxY = std::get<4>(GetParam());
122 :
123 27 : OGRGeometry *poGeom = nullptr;
124 27 : ASSERT_EQ(OGRGeometryFactory::createFromWkt(pszInput, nullptr, &poGeom),
125 : OGRERR_NONE);
126 27 : ASSERT_TRUE(poGeom != nullptr);
127 54 : std::vector<GByte> abyWkb(poGeom->WkbSize());
128 27 : poGeom->exportToWkb(wkbNDR, abyWkb.data(), wkbVariantIso);
129 27 : delete poGeom;
130 27 : OGREnvelope sEnvelope;
131 27 : EXPECT_EQ(OGRWKBGetBoundingBox(abyWkb.data(), abyWkb.size(), sEnvelope),
132 : true);
133 27 : EXPECT_EQ(sEnvelope.MinX, dfExpectedMinX);
134 27 : EXPECT_EQ(sEnvelope.MinY, dfExpectedMinY);
135 27 : EXPECT_EQ(sEnvelope.MaxX, dfExpectedMaxX);
136 27 : EXPECT_EQ(sEnvelope.MaxY, dfExpectedMaxY);
137 : }
138 :
139 56 : INSTANTIATE_TEST_SUITE_P(
140 : test_ogr_wkb, OGRWKBGetEnvelopeFixture,
141 : ::testing::ValuesIn(OGRWKBGetEnvelopeFixture::GetTupleValues()),
142 : [](const ::testing::TestParamInfo<OGRWKBGetEnvelopeFixture::ParamType>
143 : &l_info) { return std::get<5>(l_info.param); });
144 :
145 : class OGRWKBGetEnvelope3DFixture
146 : : public test_ogr_wkb,
147 : public ::testing::WithParamInterface<
148 : std::tuple<const char *, double, double, double, double, double,
149 : double, const char *>>
150 : {
151 : static constexpr double INF = std::numeric_limits<double>::infinity();
152 :
153 : public:
154 : static std::vector<std::tuple<const char *, double, double, double, double,
155 : double, double, const char *>>
156 1 : GetTupleValues()
157 : {
158 : return {
159 : std::make_tuple("POINT(1 2)", 1, 2, INF, 1, 2, -INF, "POINT"),
160 : std::make_tuple("POINT EMPTY", INF, INF, INF, -INF, -INF, -INF,
161 : "POINT_EMPTY"),
162 : std::make_tuple("POINT Z (1 2 3)", 1, 2, 3, 1, 2, 3, "POINT_3D"),
163 : std::make_tuple("LINESTRING(3 4,1 2)", 1, 2, INF, 3, 4, -INF,
164 : "LINESTRING"),
165 : std::make_tuple("LINESTRING EMPTY", INF, INF, INF, -INF, -INF, -INF,
166 : "LINESTRING_EMPTY"),
167 : std::make_tuple("LINESTRING Z (3 4 5,1 2 6)", 1, 2, 5, 3, 4, 6,
168 : "LINESTRING_3D"),
169 : std::make_tuple("POLYGON((0 1,0 2,3 2,0 1))", 0, 1, INF, 3, 2, -INF,
170 : "POLYGON"),
171 : std::make_tuple("POLYGON EMPTY", INF, INF, INF, -INF, -INF, -INF,
172 : "POLYGON_EMPTY"),
173 : std::make_tuple("POLYGON Z ((0 1 10,0 2 20,3 2 20,0 1 10))", 0, 1,
174 : 10, 3, 2, 20, "POLYGON_3D"),
175 : std::make_tuple("MULTIPOINT((1 2),(3 4))", 1, 2, INF, 3, 4, -INF,
176 : "MULTIPOINT"),
177 : std::make_tuple("MULTIPOINT EMPTY", INF, INF, INF, -INF, -INF, -INF,
178 : "MULTIPOINT_EMPTY"),
179 : std::make_tuple("MULTIPOINT Z ((1 2 10),(3 4 20))", 1, 2, 10, 3, 4,
180 : 20, "MULTIPOINT_3D"),
181 : std::make_tuple("MULTILINESTRING((3 4,1 2),(5 6,7 8))", 1, 2, INF,
182 : 7, 8, -INF, "MULTILINESTRING"),
183 : std::make_tuple("MULTILINESTRING EMPTY", INF, INF, INF, -INF, -INF,
184 : -INF, "MULTILINESTRING_EMPTY"),
185 : std::make_tuple(
186 : "MULTILINESTRING Z ((3 4 10,1 2 20),(5 6 10,7 8 20))", 1, 2, 10,
187 : 7, 8, 20, "MULTILINESTRING_3D"),
188 : std::make_tuple(
189 : "MULTIPOLYGON(((0 1,0 2,3 2,0 1)),((0 -1,0 -2,-3 -2,0 -1)))",
190 : -3, -2, INF, 3, 2, -INF, "MULTIPOLYGON"),
191 : std::make_tuple("MULTIPOLYGON EMPTY", INF, INF, INF, -INF, -INF,
192 : -INF, "MULTIPOLYGON_EMPTY"),
193 : std::make_tuple("MULTIPOLYGON Z (((0 1 10,0 2 20,3 2 20,0 1 "
194 : "10)),((0 -1 -10,0 -2 -20,-3 -2 -20,0 -1 -10)))",
195 : -3, -2, -20, 3, 2, 20, "MULTIPOLYGON_3D"),
196 1 : };
197 : }
198 : };
199 :
200 37 : TEST_P(OGRWKBGetEnvelope3DFixture, test)
201 : {
202 18 : const char *pszInput = std::get<0>(GetParam());
203 18 : const double dfExpectedMinX = std::get<1>(GetParam());
204 18 : const double dfExpectedMinY = std::get<2>(GetParam());
205 18 : const double dfExpectedMinZ = std::get<3>(GetParam());
206 18 : const double dfExpectedMaxX = std::get<4>(GetParam());
207 18 : const double dfExpectedMaxY = std::get<5>(GetParam());
208 18 : const double dfExpectedMaxZ = std::get<6>(GetParam());
209 :
210 18 : OGRGeometry *poGeom = nullptr;
211 18 : ASSERT_EQ(OGRGeometryFactory::createFromWkt(pszInput, nullptr, &poGeom),
212 : OGRERR_NONE);
213 18 : ASSERT_TRUE(poGeom != nullptr);
214 36 : std::vector<GByte> abyWkb(poGeom->WkbSize());
215 18 : poGeom->exportToWkb(wkbNDR, abyWkb.data(), wkbVariantIso);
216 18 : delete poGeom;
217 18 : OGREnvelope3D sEnvelope;
218 18 : EXPECT_EQ(OGRWKBGetBoundingBox(abyWkb.data(), abyWkb.size(), sEnvelope),
219 : true);
220 18 : EXPECT_EQ(sEnvelope.MinX, dfExpectedMinX);
221 18 : EXPECT_EQ(sEnvelope.MinY, dfExpectedMinY);
222 18 : EXPECT_EQ(sEnvelope.MinZ, dfExpectedMinZ);
223 18 : EXPECT_EQ(sEnvelope.MaxX, dfExpectedMaxX);
224 18 : EXPECT_EQ(sEnvelope.MaxY, dfExpectedMaxY);
225 18 : EXPECT_EQ(sEnvelope.MaxZ, dfExpectedMaxZ);
226 : }
227 :
228 38 : INSTANTIATE_TEST_SUITE_P(
229 : test_ogr_wkb, OGRWKBGetEnvelope3DFixture,
230 : ::testing::ValuesIn(OGRWKBGetEnvelope3DFixture::GetTupleValues()),
231 : [](const ::testing::TestParamInfo<OGRWKBGetEnvelope3DFixture::ParamType>
232 : &l_info) { return std::get<7>(l_info.param); });
233 :
234 : class OGRWKBFixupCounterClockWiseExternalRingFixture
235 : : public test_ogr_wkb,
236 : public ::testing::WithParamInterface<
237 : std::tuple<const char *, const char *, const char *>>
238 : {
239 : public:
240 : static std::vector<std::tuple<const char *, const char *, const char *>>
241 1 : GetTupleValues()
242 : {
243 : return {
244 : std::make_tuple("MULTIPOLYGON (((0 1,0 0,1 1,0 1),(0.2 0.3,0.2 "
245 : "0.8,0.7 0.8,0.2 0.3)))",
246 : "MULTIPOLYGON (((0 1,0 0,1 1,0 1),(0.2 0.3,0.2 "
247 : "0.8,0.7 0.8,0.2 0.3)))",
248 : "MULTIPOLYGON_CCW"),
249 : std::make_tuple("MULTIPOLYGON (((1 1,0 0,0 1,1 1),(0.2 0.3,0.7 "
250 : "0.8,0.2 0.8,0.2 0.3)))",
251 : "MULTIPOLYGON (((1 1,0 1,0 0,1 1),(0.2 0.3,0.2 "
252 : "0.8,0.7 0.8,0.2 0.3)))",
253 : "MULTIPOLYGON_CW"),
254 : std::make_tuple(
255 : "MULTIPOLYGON Z (((0 0 10,0 1 10,1 1 10,0 0 10),(0.2 0.3 "
256 : "10,0.7 0.8 10,0.2 0.8 10,0.2 0.3 10)))",
257 : "MULTIPOLYGON Z (((0 0 10,1 1 10,0 1 10,0 0 10),(0.2 0.3 "
258 : "10,0.2 0.8 10,0.7 0.8 10,0.2 0.3 10)))",
259 : "MULTIPOLYGON_CW_3D"),
260 : std::make_tuple("MULTIPOLYGON (((0 0,0 0,1 1,1 1,0 1,0 1,0 0)))",
261 : "MULTIPOLYGON (((0 0,0 0,1 1,1 1,0 1,0 1,0 0)))",
262 : "MULTIPOLYGON_CCW_REPEATED_POINTS"),
263 : std::make_tuple("MULTIPOLYGON (((0 0,0 0,0 1,0 1,1 1,1 1,0 0)))",
264 : "MULTIPOLYGON (((0 0,1 1,1 1,0 1,0 1,0 0,0 0)))",
265 : "MULTIPOLYGON_CW_REPEATED_POINTS"),
266 : std::make_tuple("MULTIPOLYGON EMPTY", "MULTIPOLYGON EMPTY",
267 : "MULTIPOLYGON_EMPTY"),
268 : std::make_tuple("POINT (1 2)", "POINT (1 2)", "POINT"),
269 1 : };
270 : }
271 : };
272 :
273 15 : TEST_P(OGRWKBFixupCounterClockWiseExternalRingFixture, test)
274 : {
275 7 : const char *pszInput = std::get<0>(GetParam());
276 7 : const char *pszExpected = std::get<1>(GetParam());
277 :
278 7 : OGRGeometry *poGeom = nullptr;
279 7 : ASSERT_EQ(OGRGeometryFactory::createFromWkt(pszInput, nullptr, &poGeom),
280 : OGRERR_NONE);
281 7 : ASSERT_TRUE(poGeom != nullptr);
282 7 : std::vector<GByte> abyWkb(poGeom->WkbSize());
283 7 : poGeom->exportToWkb(wkbNDR, abyWkb.data());
284 7 : OGRWKBFixupCounterClockWiseExternalRing(abyWkb.data(), abyWkb.size());
285 7 : delete poGeom;
286 7 : poGeom = nullptr;
287 7 : OGRGeometryFactory::createFromWkb(abyWkb.data(), nullptr, &poGeom);
288 7 : ASSERT_TRUE(poGeom != nullptr);
289 7 : char *pszWKT = nullptr;
290 7 : poGeom->exportToWkt(&pszWKT, wkbVariantIso);
291 7 : EXPECT_STREQ(pszWKT, pszExpected);
292 7 : CPLFree(pszWKT);
293 7 : delete poGeom;
294 : }
295 :
296 16 : INSTANTIATE_TEST_SUITE_P(
297 : test_ogr_wkb, OGRWKBFixupCounterClockWiseExternalRingFixture,
298 : ::testing::ValuesIn(
299 : OGRWKBFixupCounterClockWiseExternalRingFixture::GetTupleValues()),
300 : [](const ::testing::TestParamInfo<
301 : OGRWKBFixupCounterClockWiseExternalRingFixture::ParamType> &l_info)
302 : { return std::get<2>(l_info.param); });
303 :
304 : class OGRWKBIntersectsPessimisticFixture
305 : : public test_ogr_wkb,
306 : public ::testing::WithParamInterface<std::tuple<
307 : const char *, double, double, double, double, bool, const char *>>
308 : {
309 : public:
310 : static std::vector<std::tuple<const char *, double, double, double, double,
311 : bool, const char *>>
312 1 : GetTupleValues()
313 : {
314 : return {
315 : std::make_tuple("POINT(1 2)", 0.9, 1.9, 1.1, 2.1, true, "POINT_IN"),
316 : std::make_tuple("POINT(1 2)", 1.05, 1.9, 1.1, 2.1, false,
317 : "POINT_OUT1"),
318 : std::make_tuple("POINT(1 2)", 0.9, 2.05, 1.1, 2.1, false,
319 : "POINT_OUT2"),
320 : std::make_tuple("POINT(1 2)", 0.9, 1.9, 0.95, 2.1, false,
321 : "POINT_OUT3"),
322 : std::make_tuple("POINT(1 2)", 0.9, 1.9, 1.1, 1.95, false,
323 : "POINT_OUT4"),
324 : std::make_tuple("POINT Z (1 2 3)", 0.9, 1.9, 1.1, 2.1, true,
325 : "POINTZ_IN"),
326 : std::make_tuple("POINT Z (1 2 3)", 1.05, 1.9, 1.1, 2.1, false,
327 : "POINTZ_OUT"),
328 : std::make_tuple("POINT EMPTY", 0.9, 1.9, 1.1, 2.1, false,
329 : "POINT_EMPTY"),
330 : std::make_tuple("LINESTRING(1 2, 3 4)", 0.9, 1.9, 1.1, 2.1, true,
331 : "LINESTRING_IN"),
332 : std::make_tuple("LINESTRING(1 2, 3 4)", 0.9, 1.9, 0.95, 2.1, false,
333 : "LINESTRING_OUT"),
334 : std::make_tuple("LINESTRING EMPTY", 0.9, 1.9, 1.1, 2.1, false,
335 : "LINESTRING_EMPTY"),
336 : std::make_tuple("LINESTRING Z (1 2 10, 3 4 10)", 0.9, 1.9, 1.1, 2.1,
337 : true, "LINESTRINGZ_IN"),
338 : std::make_tuple("LINESTRING Z (1 2 10, 3 4 10)", 0.9, 1.9, 0.95,
339 : 2.1, false, "LINESTRINGZ_OUT"),
340 : std::make_tuple("POLYGON((1 2,1 3,10 3,1 2))", 0.9, 1.9, 1.1, 2.1,
341 : true, "POLYGON_IN"),
342 : std::make_tuple("POLYGON((1 2,1 3,10 3,1 2))", 0.9, 1.9, 0.95, 2.1,
343 : false, "POLYGON_OUT"),
344 : std::make_tuple("POLYGON EMPTY", 0.9, 1.9, 1.1, 2.1, false,
345 : "POLYGON_EMPTY"),
346 : std::make_tuple("POLYGON Z ((1 2 -10,1 3 -10,10 3 -10,1 2 -10))",
347 : 0.9, 1.9, 1.1, 2.1, true, "POLYGONZ_IN"),
348 : std::make_tuple("POLYGON Z ((1 2 -10,1 3 -10,10 3 -10,1 2 -10))",
349 : 0.9, 1.9, 0.95, 2.1, false, "POLYGONZ_OUT"),
350 : std::make_tuple("MULTIPOINT((1 2))", 0.9, 1.9, 1.1, 2.1, true,
351 : "MULTIPOINT_IN"),
352 : std::make_tuple("MULTIPOINT((1 2))", 1.05, 1.9, 1.1, 2.1, false,
353 : "MULTIPOINT_OUT1"),
354 : std::make_tuple("MULTIPOINT((1 2))", 0.9, 2.05, 1.1, 2.1, false,
355 : "MULTIPOINT_OUT2"),
356 : std::make_tuple("MULTIPOINT((1 2))", 0.9, 1.9, 0.95, 2.1, false,
357 : "MULTIPOINT_OUT3"),
358 : std::make_tuple("MULTIPOINT((1 2))", 0.9, 1.9, 1.1, 1.95, false,
359 : "MULTIPOINT_OUT4"),
360 : std::make_tuple("MULTIPOINT Z ((1 2 3))", 0.9, 1.9, 1.1, 2.1, true,
361 : "MULTIPOINTZ_IN"),
362 : std::make_tuple("MULTIPOINT Z ((1 2 3))", 1.05, 1.9, 1.1, 2.1,
363 : false, "MULTIPOINTZ_OUT"),
364 : std::make_tuple("MULTIPOINT EMPTY", 0.9, 1.9, 1.1, 2.1, false,
365 : "MULTIPOINT_EMPTY"),
366 : std::make_tuple("MULTILINESTRING((1 2, 3 4))", 0.9, 1.9, 1.1, 2.1,
367 : true, "MULTILINESTRING_IN"),
368 : std::make_tuple("MULTILINESTRING((1 2, 3 4))", 0.9, 1.9, 0.95, 2.1,
369 : false, "MULTILINESTRING_OUT"),
370 : std::make_tuple("MULTILINESTRING EMPTY", 0.9, 1.9, 1.1, 2.1, false,
371 : "MULTILINESTRING_EMPTY"),
372 : std::make_tuple("MULTILINESTRING Z ((1 2 10, 3 4 10))", 0.9, 1.9,
373 : 1.1, 2.1, true, "MULTILINESTRINGZ_IN"),
374 : std::make_tuple("MULTILINESTRING Z ((1 2 10, 3 4 10))", 0.9, 1.9,
375 : 0.95, 2.1, false, "MULTILINESTRINGZ_OUT"),
376 : std::make_tuple("MULTIPOLYGON(((1 2,1 3,10 3,1 2)))", 0.9, 1.9, 1.1,
377 : 2.1, true, "MULTIPOLYGON_IN"),
378 : std::make_tuple("MULTIPOLYGON(((1 2,1 3,10 3,1 2)))", 0.9, 1.9,
379 : 0.95, 2.1, false, "MULTIPOLYGON_OUT"),
380 : std::make_tuple("MULTIPOLYGON EMPTY", 0.9, 1.9, 1.1, 2.1, false,
381 : "MULTIPOLYGON_EMPTY"),
382 : std::make_tuple(
383 : "MULTIPOLYGON Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))", 0.9,
384 : 1.9, 1.1, 2.1, true, "MULTIPOLYGONZ_IN"),
385 : std::make_tuple(
386 : "MULTIPOLYGON Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))", 0.9,
387 : 1.9, 0.95, 2.1, false, "MULTIPOLYGONZ_OUT"),
388 : std::make_tuple("GEOMETRYCOLLECTION(POINT(1 2))", 0.9, 1.9, 1.1,
389 : 2.1, true, "GEOMETRYCOLLECTION_POINT_IN"),
390 : std::make_tuple("CIRCULARSTRING(0 10,1 11,2 10)", -0.1, 9.9, 0.1,
391 : 10.1, true, "CIRCULARSTRING_IN"),
392 : std::make_tuple("CIRCULARSTRING(0 10,1 11,2 10)", -0.1, 9.9, -0.05,
393 : 10.1, false, "CIRCULARSTRING_OUT"),
394 : std::make_tuple("CIRCULARSTRING EMPTY", -0.1, 9.9, 0.1, 10.1, false,
395 : "CIRCULARSTRING_EMPTY"),
396 : std::make_tuple("TRIANGLE((1 2,1 3,10 3,1 2))", 0.9, 1.9, 1.1, 2.1,
397 : true, "TRIANGLE_IN"),
398 : std::make_tuple("TRIANGLE((1 2,1 3,10 3,1 2))", 0.9, 1.9, 0.95, 2.1,
399 : false, "TRIANGLE_OUT"),
400 : std::make_tuple("TRIANGLE EMPTY", 0.9, 1.9, 1.1, 2.1, false,
401 : "TRIANGLE_EMPTY"),
402 : std::make_tuple("TRIANGLE Z ((1 2 -10,1 3 -10,10 3 -10,1 2 -10))",
403 : 0.9, 1.9, 1.1, 2.1, true, "TRIANGLEZ_IN"),
404 : std::make_tuple("TRIANGLE Z ((1 2 -10,1 3 -10,10 3 -10,1 2 -10))",
405 : 0.9, 1.9, 0.95, 2.1, false, "TRIANGLEZ_OUT"),
406 : std::make_tuple("COMPOUNDCURVE((1 2, 3 4))", 0.9, 1.9, 1.1, 2.1,
407 : true, "COMPOUNDCURVE_IN"),
408 : std::make_tuple("COMPOUNDCURVE((1 2, 3 4))", 0.9, 1.9, 0.95, 2.1,
409 : false, "COMPOUNDCURVE_OUT"),
410 : std::make_tuple("COMPOUNDCURVE EMPTY", 0.9, 1.9, 1.1, 2.1, false,
411 : "COMPOUNDCURVE_EMPTY"),
412 : std::make_tuple("COMPOUNDCURVE Z ((1 2 10, 3 4 10))", 0.9, 1.9, 1.1,
413 : 2.1, true, "COMPOUNDCURVEZ_IN"),
414 : std::make_tuple("COMPOUNDCURVE Z ((1 2 10, 3 4 10))", 0.9, 1.9,
415 : 0.95, 2.1, false, "COMPOUNDCURVEZ_OUT"),
416 : std::make_tuple("CURVEPOLYGON((1 2,1 3,10 3,1 2))", 0.9, 1.9, 1.1,
417 : 2.1, true, "CURVEPOLYGON_IN"),
418 : std::make_tuple("CURVEPOLYGON((1 2,1 3,10 3,1 2))", 0.9, 1.9, 0.95,
419 : 2.1, false, "CURVEPOLYGON_OUT"),
420 : std::make_tuple("CURVEPOLYGON EMPTY", 0.9, 1.9, 1.1, 2.1, false,
421 : "CURVEPOLYGON_EMPTY"),
422 : std::make_tuple(
423 : "CURVEPOLYGON Z ((1 2 -10,1 3 -10,10 3 -10,1 2 -10))", 0.9, 1.9,
424 : 1.1, 2.1, true, "CURVEPOLYGONZ_IN"),
425 : std::make_tuple(
426 : "CURVEPOLYGON Z ((1 2 -10,1 3 -10,10 3 -10,1 2 -10))", 0.9, 1.9,
427 : 0.95, 2.1, false, "CURVEPOLYGONZ_OUT"),
428 : std::make_tuple("MULTICURVE((1 2, 3 4))", 0.9, 1.9, 1.1, 2.1, true,
429 : "MULTICURVE_IN"),
430 : std::make_tuple("MULTICURVE((1 2, 3 4))", 0.9, 1.9, 0.95, 2.1,
431 : false, "MULTICURVE_OUT"),
432 : std::make_tuple("MULTICURVE EMPTY", 0.9, 1.9, 1.1, 2.1, false,
433 : "MULTICURVE_EMPTY"),
434 : std::make_tuple("MULTICURVE Z ((1 2 10, 3 4 10))", 0.9, 1.9, 1.1,
435 : 2.1, true, "MULTICURVEZ_IN"),
436 : std::make_tuple("MULTICURVE Z ((1 2 10, 3 4 10))", 0.9, 1.9, 0.95,
437 : 2.1, false, "MULTICURVEZ_OUT"),
438 : std::make_tuple("MULTISURFACE(((1 2,1 3,10 3,1 2)))", 0.9, 1.9, 1.1,
439 : 2.1, true, "MULTISURFACE_IN"),
440 : std::make_tuple("MULTISURFACE(((1 2,1 3,10 3,1 2)))", 0.9, 1.9,
441 : 0.95, 2.1, false, "MULTISURFACE_OUT"),
442 : std::make_tuple("MULTISURFACE EMPTY", 0.9, 1.9, 1.1, 2.1, false,
443 : "MULTISURFACE_EMPTY"),
444 : std::make_tuple(
445 : "MULTISURFACE Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))", 0.9,
446 : 1.9, 1.1, 2.1, true, "MULTISURFACEZ_IN"),
447 : std::make_tuple(
448 : "MULTISURFACE Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))", 0.9,
449 : 1.9, 0.95, 2.1, false, "MULTISURFACEZ_OUT"),
450 : std::make_tuple("POLYHEDRALSURFACE(((1 2,1 3,10 3,1 2)))", 0.9, 1.9,
451 : 1.1, 2.1, true, "POLYHEDRALSURFACE_IN"),
452 : std::make_tuple("POLYHEDRALSURFACE(((1 2,1 3,10 3,1 2)))", 0.9, 1.9,
453 : 0.95, 2.1, false, "POLYHEDRALSURFACE_OUT"),
454 : std::make_tuple("POLYHEDRALSURFACE EMPTY", 0.9, 1.9, 1.1, 2.1,
455 : false, "POLYHEDRALSURFACE_EMPTY"),
456 : std::make_tuple(
457 : "POLYHEDRALSURFACE Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))",
458 : 0.9, 1.9, 1.1, 2.1, true, "POLYHEDRALSURFACEZ_IN"),
459 : std::make_tuple(
460 : "POLYHEDRALSURFACE Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))",
461 : 0.9, 1.9, 0.95, 2.1, false, "POLYHEDRALSURFACEZ_OUT"),
462 : std::make_tuple("TIN(((1 2,1 3,10 3,1 2)))", 0.9, 1.9, 1.1, 2.1,
463 : true, "TIN_IN"),
464 : std::make_tuple("TIN(((1 2,1 3,10 3,1 2)))", 0.9, 1.9, 0.95, 2.1,
465 : false, "TIN_OUT"),
466 : std::make_tuple("TIN EMPTY", 0.9, 1.9, 1.1, 2.1, false,
467 : "TIN_EMPTY"),
468 : std::make_tuple("TIN Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))", 0.9,
469 : 1.9, 1.1, 2.1, true, "TINZ_IN"),
470 : std::make_tuple("TIN Z (((1 2 -10,1 3 -10,10 3 -10,1 2 -10)))", 0.9,
471 : 1.9, 0.95, 2.1, false, "TINZ_OUT"),
472 1 : };
473 : }
474 : };
475 :
476 151 : TEST_P(OGRWKBIntersectsPessimisticFixture, test)
477 : {
478 75 : const char *pszInput = std::get<0>(GetParam());
479 75 : const double dfMinX = std::get<1>(GetParam());
480 75 : const double dfMinY = std::get<2>(GetParam());
481 75 : const double dfMaxX = std::get<3>(GetParam());
482 75 : const double dfMaxY = std::get<4>(GetParam());
483 75 : const bool bIntersects = std::get<5>(GetParam());
484 :
485 75 : OGRGeometry *poGeom = nullptr;
486 75 : EXPECT_EQ(OGRGeometryFactory::createFromWkt(pszInput, nullptr, &poGeom),
487 : OGRERR_NONE);
488 75 : ASSERT_TRUE(poGeom != nullptr);
489 150 : std::vector<GByte> abyWkb(poGeom->WkbSize());
490 75 : poGeom->exportToWkb(wkbNDR, abyWkb.data(), wkbVariantIso);
491 75 : delete poGeom;
492 75 : OGREnvelope sEnvelope;
493 75 : sEnvelope.MinX = dfMinX;
494 75 : sEnvelope.MinY = dfMinY;
495 75 : sEnvelope.MaxX = dfMaxX;
496 75 : sEnvelope.MaxY = dfMaxY;
497 75 : EXPECT_EQ(
498 : OGRWKBIntersectsPessimistic(abyWkb.data(), abyWkb.size(), sEnvelope),
499 : bIntersects);
500 :
501 75 : if (abyWkb.size() > 9)
502 : {
503 62 : EXPECT_EQ(OGRWKBIntersectsPessimistic(abyWkb.data(), 9, sEnvelope),
504 : false);
505 :
506 62 : if (!STARTS_WITH(pszInput, "POINT"))
507 : {
508 : // Corrupt number of sub-geometries
509 54 : abyWkb[5] = 0xff;
510 54 : abyWkb[6] = 0xff;
511 54 : abyWkb[7] = 0xff;
512 54 : abyWkb[8] = 0xff;
513 54 : EXPECT_EQ(OGRWKBIntersectsPessimistic(abyWkb.data(), abyWkb.size(),
514 : sEnvelope),
515 : false);
516 : }
517 : }
518 : }
519 :
520 152 : INSTANTIATE_TEST_SUITE_P(
521 : test_ogr_wkb, OGRWKBIntersectsPessimisticFixture,
522 : ::testing::ValuesIn(OGRWKBIntersectsPessimisticFixture::GetTupleValues()),
523 : [](const ::testing::TestParamInfo<
524 : OGRWKBIntersectsPessimisticFixture::ParamType> &l_info)
525 : { return std::get<6>(l_info.param); });
526 :
527 : } // namespace
|