File: GEOSPreparedGeometryTest.cpp

package info (click to toggle)
geos 3.14.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 31,212 kB
  • sloc: cpp: 199,103; xml: 56,065; ansic: 6,162; sh: 287; makefile: 26
file content (486 lines) | stat: -rw-r--r-- 18,328 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
//
// Test Suite for C-API GEOSPreparedGeometry

#include <tut/tut.hpp>
// geos
#include <geos_c.h>
#include <geos/io/WKBReader.h>
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/GeometryFactory.h>
// std
#include <memory>

#include "capi_test_utils.h"

namespace tut {
//
// Test Group
//

// Common data used in test cases.
struct test_capigeospreparedgeometry_data : public capitest::utility {
    const GEOSPreparedGeometry* prepGeom1_;
    const GEOSPreparedGeometry* prepGeom2_;

    test_capigeospreparedgeometry_data()
        : prepGeom1_(nullptr), prepGeom2_(nullptr)
    {}

    ~test_capigeospreparedgeometry_data()
    {
        GEOSPreparedGeom_destroy(prepGeom1_);
        GEOSPreparedGeom_destroy(prepGeom2_);
        prepGeom1_ = nullptr;
        prepGeom2_ = nullptr;
    }

};

typedef test_group<test_capigeospreparedgeometry_data> group;
typedef group::object object;

group test_capigeospreparedgeometry_group("capi::GEOSPreparedGeometry");

//
// Test Cases
//

// Test geometry preparation
template<>
template<>
void object::test<1>
()
{
    geom1_ = GEOSGeomFromWKT("POLYGON EMPTY");
    prepGeom1_ = GEOSPrepare(geom1_);

    ensure(nullptr != prepGeom1_);

}

// Test PreparedContainsProperly
// Taken from regress/regress_ogc_prep.sql of postgis
// as of revno 3936
// ref: containsproperly200 (a)
template<>
template<>
void object::test<2>
()
{
    geom1_ = GEOSGeomFromWKT("POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
    geom2_ = GEOSGeomFromWKT("POLYGON((2 2, 2 3, 3 3, 3 2, 2 2))");
    prepGeom1_ = GEOSPrepare(geom1_);

    ensure(nullptr != prepGeom1_);

    int ret = GEOSPreparedContainsProperly(prepGeom1_, geom2_);
    ensure_equals(ret, 1);

}

// Test PreparedContainsProperly
// Taken from regress/regress_ogc_prep.sql of postgis
// as of revno 3936
// ref: containsproperly200 (b)
template<>
template<>
void object::test<3>
()
{
    geom1_ = GEOSGeomFromWKT("POLYGON((2 2, 2 3, 3 3, 3 2, 2 2))");
    geom2_ = GEOSGeomFromWKT("POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))");
    prepGeom1_ = GEOSPrepare(geom1_);

    ensure(nullptr != prepGeom1_);

    int ret = GEOSPreparedContainsProperly(prepGeom1_, geom2_);
    ensure_equals(ret, 0);

}

// Test PreparedIntersects
// Also used as a linestring leakage reported
// by http://trac.osgeo.org/geos/ticket/305
//
template<>
template<>
void object::test<4>
()
{
    geom1_ = GEOSGeomFromWKT("LINESTRING(0 0, 10 10)");
    geom2_ = GEOSGeomFromWKT("LINESTRING(0 10, 10 0)");
    prepGeom1_ = GEOSPrepare(geom1_);

    ensure(nullptr != prepGeom1_);

    int ret = GEOSPreparedIntersects(prepGeom1_, geom2_);
    ensure_equals(ret, 1);

}

// Test PreparedCovers
template<>
template<>
void object::test<5>
()
{
    geom1_ = GEOSGeomFromWKT("POLYGON((0 0, 0 10, 10 11, 10 0, 0 0))");
    geom2_ = GEOSGeomFromWKT("POLYGON((0 0, 2 0, 2 2, 0 2, 0 0))");
    prepGeom1_ = GEOSPrepare(geom1_);

    ensure(nullptr != prepGeom1_);

    int ret = GEOSPreparedCovers(prepGeom1_, geom2_);
    ensure_equals(ret, 1);

}

// Test PreparedContains
template<>
template<>
void object::test<6>
()
{
    geom1_ = GEOSGeomFromWKT("POLYGON((0 0, 0 10, 10 11, 10 0, 0 0))");
    geom2_ = GEOSGeomFromWKT("POLYGON((0 0, 2 0, 2 2, 0 2, 0 0))");
    prepGeom1_ = GEOSPrepare(geom1_);

    ensure(nullptr != prepGeom1_);

    int ret = GEOSPreparedContains(prepGeom1_, geom2_);
    ensure_equals(ret, 1);

}

// Test PreparedIntersects: point on segment with FLOAT PM
// X coordinate of 3rd and 4th vertices of the line are not
// float-point exact with X coordinate of the point.
// The X values differ after 14th decimal place:
// POINT (-23.1094689600055080 50.5195368635957180)
// --------------------^^^^^^^------------^^^^^^^^
// LINESTRING 3rd and 4th points
//        -23.1094689600055150 50.5223376452201340,
//        -23.1094689600055010 50.5169177629559480,
// --------------------^^^^^^^------------^^^^^^^^
// So, in float-point precision model, the point does DOES NOT intersect the segment.
// See RobustLineIntersectorTest.cpp for similar test cases.
template<>
template<>
void object::test<7>
()
{
    // POINT located between 3rd and 4th vertex of LINESTRING
    // POINT(-23.1094689600055080 50.5195368635957180)
    std::string point("01010000009a266328061c37c0e21a172f80424940");
    // LINESTRING(-23.122057005539 50.5201976774794,-23.1153476966995 50.5133404815199,-23.1094689600055150 50.5223376452201340,-23.1094689600055010 50.5169177629559480,-23.0961967920942 50.5330464848094,-23.0887991006034 50.5258515213185,-23.0852302622362 50.5264582238409)
    std::string
    line("0102000000070000009909bf203f1f37c05c1d66d6954249404afe386d871d37c0a7eb1124b54149409c266328061c37c056d8bff5db42494098266328061c37c0034f7b5c2a42494060065c5aa01837c08ac001de3a4449408401b189bb1637c0b04e471a4f43494014ef84a6d11537c0b20dabfb62434940");
    geom1_ = GEOSGeomFromHEX_buf(reinterpret_cast<const unsigned char*>(line.data()), line.size());
    geom2_ = GEOSGeomFromHEX_buf(reinterpret_cast<const unsigned char*>(point.data()), point.size());

    prepGeom1_ = GEOSPrepare(geom1_);
    ensure(nullptr != prepGeom1_);
    int ret = GEOSPreparedIntersects(prepGeom1_, geom2_);
    ensure_equals(ret, 0);
}

// Test PreparedIntersects: point on segment with FIXED PM
// X coordinate of 3rd and 4th vertices of the line are not
// float-point exact with X coordinate of the point.
// The X values differ after 14th decimal place:
// POINT (-23.1094689600055080 50.5195368635957180)
// --------------------^^^^^^^------------^^^^^^^^
// LINESTRING 3rd and 4th points
//        -23.1094689600055150 50.5223376452201340,
//        -23.1094689600055010 50.5169177629559480,
// --------------------^^^^^^^------------^^^^^^^^
// So, if float-point values are trimmed up to 14 decimal digits, the point DOES intersect the segment.
// See RobustLineIntersectorTest.cpp for similar test cases.
template<>
template<>
void object::test<8>
()
{
    geos::geom::PrecisionModel pm(1e+13);
    geos::geom::GeometryFactory::Ptr factory = geos::geom::GeometryFactory::create(&pm);
    geos::io::WKBReader reader(*factory);

    // POINT located between 3rd and 4th vertex of LINESTRING
    // POINT(-23.1094689600055080 50.5195368635957180)
    std::string point("01010000009a266328061c37c0e21a172f80424940");
    // LINESTRING(-23.122057005539 50.5201976774794,-23.1153476966995 50.5133404815199,-23.1094689600055150 50.5223376452201340,-23.1094689600055010 50.5169177629559480,-23.0961967920942 50.5330464848094,-23.0887991006034 50.5258515213185,-23.0852302622362 50.5264582238409)
    std::string
    line("0102000000070000009909bf203f1f37c05c1d66d6954249404afe386d871d37c0a7eb1124b54149409c266328061c37c056d8bff5db42494098266328061c37c0034f7b5c2a42494060065c5aa01837c08ac001de3a4449408401b189bb1637c0b04e471a4f43494014ef84a6d11537c0b20dabfb62434940");
    std::stringstream sPoint(point);
    geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sPoint).release());
    std::stringstream sLine(line);
    geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sLine).release());

    prepGeom1_ = GEOSPrepare(geom1_);
    ensure(nullptr != prepGeom1_);
    int ret = GEOSPreparedIntersects(prepGeom1_, geom2_);
    ensure_equals(ret, 1);
}

// Test PreparedIntersects: point on vertex (default FLOAT PM)
template<>
template<>
void object::test<9>
()
{
    // POINT located on the 3rd vertex of LINESTRING
    // POINT(-23.1094689600055 50.5223376452201)
    std::string point("01010000009c266328061c37c056d8bff5db424940");
    // LINESTRING(-23.122057005539 50.5201976774794,-23.1153476966995 50.5133404815199,-23.1094689600055 50.5223376452201,-23.1094689600055 50.5169177629559,-23.0961967920942 50.5330464848094,-23.0887991006034 50.5258515213185,-23.0852302622362 50.5264582238409)
    std::string
    line("0102000000070000009909bf203f1f37c05c1d66d6954249404afe386d871d37c0a7eb1124b54149409c266328061c37c056d8bff5db42494098266328061c37c0034f7b5c2a42494060065c5aa01837c08ac001de3a4449408401b189bb1637c0b04e471a4f43494014ef84a6d11537c0b20dabfb62434940");
    geom1_ = GEOSGeomFromHEX_buf(reinterpret_cast<const unsigned char*>(line.data()), line.size());
    geom2_ = GEOSGeomFromHEX_buf(reinterpret_cast<const unsigned char*>(point.data()), point.size());
    prepGeom1_ = GEOSPrepare(geom1_);
    ensure(nullptr != prepGeom1_);

    int ret = GEOSPreparedIntersects(prepGeom1_, geom2_);
    ensure_equals(ret, 1);
}

// Test outer polygon contains inner polygon with two coincident vertices
// with results compared depending on precision used with FIXED PMs.
template<>
template<>
void object::test<10>
()
{
    // Coincident vertices of both polygons at
    // -700.67089999181 93743.4218587986, -713.450135807349 93754.1677576647,
    std::string const
    outer("01030000800100000009000000af9dd0005ee585c0f802efbff6e2f6400000000000000000955acde0994b86c039a922afa2e3f64000000000000000002af6fb4f5d1887c07adb1c4071e3f6400000000000000000e5962b388d4f87c0bd3aeda7bae2f640000000000000000087c61344030887c07d585e6ff6e1f6400000000000000000fc8a31b5166186c0230588b20ae1f640000000000000000034733daf050186c0ed9f3ac98ae1f6400000000000000000f190aef659b385c0df2876538ce2f6400000000000000000af9dd0005ee585c0f802efbff6e2f6400000000000000000");
    std::string const
    inner("0103000080010000000a000000ac21f88bbaff86c05f45d8c7b4e2f6400000000000000000467f1177ebf386c05de1971187e2f6400000000000000000fcf677888fc886c04e855a544be2f6400000000000000000c61226e540b686c0c0662d1fe7e1f640000000000000000042dc1bece8a486c09b85529f8ae1f6400000000000000000891047cde55e86c038cfa59c4ee1f6400000000000000000ae9dd0005ee585c0fa02efbff6e2f6400000000000000000975acde0994b86c038a922afa2e3f6400000000000000000287e339b09f986c01b1a083a10e3f6400000000000000000ac21f88bbaff86c05f45d8c7b4e2f6400000000000000000");

    // A contains B if precision is limited to 1e+10
    {
        geos::geom::PrecisionModel pm(1e+10); // NOTE: higher precision fails this test case
        geos::geom::GeometryFactory::Ptr factory = geos::geom::GeometryFactory::create(&pm);
        geos::io::WKBReader reader(*factory);

        std::istringstream sOuter(outer);
        geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sOuter).release());
        std::istringstream sInner(inner);
        geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sInner).release());
        ensure(nullptr != geom1_);
        ensure(nullptr != geom2_);
        prepGeom1_ = GEOSPrepare(geom1_);
        ensure(nullptr != prepGeom1_);

        int ret = GEOSPreparedContains(prepGeom1_, geom2_);
        ensure_equals(ret, 1);
        ret = GEOSPreparedContainsProperly(prepGeom1_, geom2_);
        ensure_equals(ret, 0);

        GEOSGeom_destroy(geom1_);
        GEOSGeom_destroy(geom2_);
        GEOSPreparedGeom_destroy(prepGeom1_);
    }

    // A does NOT contain B if precision is extended to 1e+11 or beyond
    {
        geos::geom::PrecisionModel pm(1e+11);
        geos::geom::GeometryFactory::Ptr factory = geos::geom::GeometryFactory::create(&pm);
        geos::io::WKBReader reader(*factory);

        std::istringstream sOuter(outer);
        geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sOuter).release());
        std::istringstream sInner(inner);
        geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sInner).release());
        ensure(nullptr != geom1_);
        ensure(nullptr != geom2_);
        prepGeom1_ = GEOSPrepare(geom1_);
        ensure(nullptr != prepGeom1_);

        int ret = GEOSPreparedContains(prepGeom1_, geom2_);
        ensure_equals(ret, 0);
        ret = GEOSPreparedContainsProperly(prepGeom1_, geom2_);
        ensure_equals(ret, 0);
    }
}

// Test outer rectangle contains inner rectangle with one coincident vertex
// and two vertices of the inner rectangle are on the boundary (lay on segments)
// of the outer rectangle.
// Precision model should not affect the containment test result.
template<>
template<>
void object::test<11>
()
{
    // Coincident vertex at -753.167968418005 93709.4279185742
    //POLYGON ((-753.167968418005 93754.0955183194,-816.392328351464 93754.0955183194,-816.392328351464 93709.4279185742,-753.167968418005 93709.4279185742,-753.167968418005 93754.0955183194))
    std::string const
    outer("01030000800100000005000000bd70d3ff578987c09e373e87a1e3f6400000000000000000a9f60b7d238389c09e373e87a1e3f6400000000000000000a9f60b7d238389c09625c1d8d6e0f6400000000000000000bd70d3ff578987c09625c1d8d6e0f6400000000000000000bd70d3ff578987c09e373e87a1e3f6400000000000000000");
    //POLYGON ((-753.167968418005 93747.6909727677,-799.641978447015 93747.6909727677,-799.641978447015 93709.4279185742,-753.167968418005 93709.4279185742,-753.167968418005 93747.6909727677))
    std::string const
    inner("01030000800100000005000000bd70d3ff578987c0f875390e3be3f6400000000000000000579598c522fd88c0f875390e3be3f6400000000000000000579598c522fd88c09625c1d8d6e0f6400000000000000000bd70d3ff578987c09625c1d8d6e0f6400000000000000000bd70d3ff578987c0f875390e3be3f6400000000000000000");

    // A contains B if precision is limited to 1e+10
    {
        geos::geom::PrecisionModel pm(1e+10);
        geos::geom::GeometryFactory::Ptr factory = geos::geom::GeometryFactory::create(&pm);
        geos::io::WKBReader reader(*factory);

        std::istringstream sOuter(outer);
        geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sOuter).release());
        std::istringstream sInner(inner);
        geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sInner).release());
        ensure(nullptr != geom1_);
        ensure(nullptr != geom2_);
        prepGeom1_ = GEOSPrepare(geom1_);
        ensure(nullptr != prepGeom1_);

        int ret = GEOSPreparedContains(prepGeom1_, geom2_);
        ensure_equals(ret, 1);
        ret = GEOSPreparedContainsProperly(prepGeom1_, geom2_);
        ensure_equals(ret, 0);

        GEOSGeom_destroy(geom1_);
        GEOSGeom_destroy(geom2_);
        GEOSPreparedGeom_destroy(prepGeom1_);
    }

    // A contains B if FLOATING PM is used with extended precision
    {
        geos::geom::PrecisionModel pm;
        geos::geom::GeometryFactory::Ptr factory = geos::geom::GeometryFactory::create(&pm);
        geos::io::WKBReader reader(*factory);

        std::istringstream sOuter(outer);
        geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sOuter).release());
        std::istringstream sInner(inner);
        geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sInner).release());
        ensure(nullptr != geom1_);
        ensure(nullptr != geom2_);
        prepGeom1_ = GEOSPrepare(geom1_);
        ensure(nullptr != prepGeom1_);

        int ret = GEOSPreparedContains(prepGeom1_, geom2_);
        ensure_equals(ret, 1);
        ret = GEOSPreparedContainsProperly(prepGeom1_, geom2_);
        ensure_equals(ret, 0);
    }
}

// Test PreparedIntersects with Point EMPTY
template<>
template<>
void object::test<12>
()
{
    geom1_ = GEOSGeomFromWKT("POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))");
    geom2_ = GEOSGeomFromWKT("POINT EMPTY");
    prepGeom1_ = GEOSPrepare(geom1_);

    ensure(nullptr != prepGeom1_);
    ensure(nullptr != geom2_);

    int ret = GEOSPreparedIntersects(prepGeom1_, geom2_);
    ensure_equals(ret, 0);
}

// Test PreparedCovers with Point EMPTY
template<>
template<>
void object::test<13>
()
{
    geom1_ = GEOSGeomFromWKT("POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))");
    geom2_ = GEOSGeomFromWKT("POINT EMPTY");
    prepGeom1_ = GEOSPrepare(geom1_);

    ensure(nullptr != prepGeom1_);
    ensure(nullptr != geom2_);

    int ret = GEOSPreparedCovers(prepGeom1_, geom2_);
    ensure_equals(ret, 0);
}

// Verify no memory leak on exception (https://github.com/libgeos/geos/issues/505)
// RelateNG does not throw for this case
template<>
template<>
void object::test<14>
()
{
    geom1_ = GEOSGeomFromWKT("LINESTRING(0 0, 1 NaN)");
    geom2_ = GEOSGeomFromWKT("POINT(0 0)");
    prepGeom1_ = GEOSPrepare(geom1_);

    ensure(nullptr != prepGeom1_);
    ensure(nullptr != geom2_);

    int ret = GEOSPreparedTouches(prepGeom1_, geom2_);
    ensure_equals(ret, 1);
}

// Test XY variants
template<>
template<>
void object::test<15>
()
{
    geom1_ = GEOSGeomFromWKT("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))")    ;
    prepGeom1_ = GEOSPrepare(geom1_);

    ensure_equals(GEOSPreparedContainsXY(prepGeom1_, 0.5, 0.5), 1);
    ensure_equals(GEOSPreparedContainsXY(prepGeom1_, 1.5, 0.5), 0);
    ensure_equals(GEOSPreparedContainsXY(prepGeom1_, 0.75, 0.5), 1);

    ensure_equals(GEOSPreparedIntersectsXY(prepGeom1_, 0.5, 0.5), 1);
    ensure_equals(GEOSPreparedIntersectsXY(prepGeom1_, 1.5, 0.5), 0);
    ensure_equals(GEOSPreparedIntersectsXY(prepGeom1_, 0.75, 0.5), 1);
}


template<>
template<>
void object::test<16>()
{
    geom1_ = fromWKT("CIRCULARSTRING (0 0, 1 1, 2 0)");

    ensure(geom1_);

    prepGeom1_ = GEOSPrepare(geom1_);
    ensure("curved geometries not supporteds", prepGeom1_ == nullptr);
}


template<>
template<>
void object::test<17>()
{
    geom1_ = fromWKT("POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))");
    geom2_ = fromWKT("POLYGON((0.5 0.5, 1.5 0.5, 1.5 1.5, 0.5 1.5, 0.5 0.5))");

    ensure(geom1_);
    ensure(geom2_);

    prepGeom1_ = GEOSPrepare(geom1_);

    // Run each test twice to make sure the "accelerated" second call
    // is the same as the first one.
    ensure_equals("prepTouches1", GEOSPreparedTouches(prepGeom1_, geom2_), GEOSTouches(geom1_, geom2_));
    ensure_equals("prepTouches2", GEOSPreparedTouches(prepGeom1_, geom2_), GEOSTouches(geom1_, geom2_));
    ensure_equals("prepOverlaps1", GEOSPreparedOverlaps(prepGeom1_, geom2_), GEOSOverlaps(geom1_, geom2_));
    ensure_equals("prepOverlaps2", GEOSPreparedOverlaps(prepGeom1_, geom2_), GEOSOverlaps(geom1_, geom2_));
    ensure_equals("prepCrosses1", GEOSPreparedCrosses(prepGeom1_, geom2_), GEOSCrosses(geom1_, geom2_));
    ensure_equals("prepCrosses2", GEOSPreparedCrosses(prepGeom1_, geom2_), GEOSCrosses(geom1_, geom2_));
    ensure_equals("prepDisjoint1", GEOSPreparedDisjoint(prepGeom1_, geom2_), GEOSDisjoint(geom1_, geom2_));
    ensure_equals("prepDisjoint2", GEOSPreparedDisjoint(prepGeom1_, geom2_), GEOSDisjoint(geom1_, geom2_));

    char* r1 = GEOSPreparedRelate(prepGeom1_, geom2_);
    char* r2 = GEOSRelate(geom1_, geom2_);
    ensure_equals("prepRelate1", std::string(r1), std::string(r2));
    GEOSFree(r1);
    GEOSFree(r2);
}

} // namespace tut