409 строки
13 KiB
C++
409 строки
13 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Project: C++ Test Suite for GDAL/OGR
|
|
// Purpose: Test GEOS integration in OGR - geometric operations.
|
|
// Ported from ogr/ogr_geos.py.
|
|
// Author: Mateusz Loskot <mateusz@loskot.net>
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Copyright (c) 2006, Mateusz Loskot <mateusz@loskot.net>
|
|
/*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#include "gdal_unit_test.h"
|
|
|
|
#include "ogr_api.h"
|
|
#include "ogrsf_frmts.h"
|
|
|
|
#ifdef HAVE_GEOS
|
|
#include <geos_c.h>
|
|
#endif
|
|
|
|
#include <string>
|
|
|
|
#include "gtest_include.h"
|
|
|
|
namespace
|
|
{
|
|
using namespace tut; // for CheckEqualGeometries
|
|
|
|
// Common fixture with test data
|
|
struct test_ogr_geos : public ::testing::Test
|
|
{
|
|
OGRErr err_ = OGRERR_NONE;
|
|
OGRGeometryH g1_ = nullptr;
|
|
OGRGeometryH g2_ = nullptr;
|
|
OGRGeometryH g3_ = nullptr;
|
|
|
|
void SetUp() override
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
GTEST_SKIP() << "GEOS support is not available";
|
|
#endif
|
|
}
|
|
|
|
void TearDown() override
|
|
{
|
|
OGR_G_DestroyGeometry(g1_);
|
|
g1_ = nullptr;
|
|
OGR_G_DestroyGeometry(g2_);
|
|
g2_ = nullptr;
|
|
OGR_G_DestroyGeometry(g3_);
|
|
g3_ = nullptr;
|
|
}
|
|
};
|
|
|
|
// Test export OGR geometry to GEOS using GDAL C++ API
|
|
TEST_F(test_ogr_geos, exportToGEOS)
|
|
{
|
|
#ifdef HAVE_GEOS
|
|
const char *wkt = "POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))";
|
|
OGRPolygon geom;
|
|
err_ = geom.importFromWkt(&wkt);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
|
|
GEOSContextHandle_t ctxt = OGRGeometry::createGEOSContext();
|
|
GEOSGeom geosGeom = geom.exportToGEOS(ctxt);
|
|
OGRGeometry::freeGEOSContext(ctxt);
|
|
ASSERT_TRUE(nullptr != geosGeom);
|
|
|
|
GEOSGeom_destroy_r(ctxt, geosGeom);
|
|
#endif
|
|
}
|
|
|
|
// Test OGR_G_Contains function
|
|
TEST_F(test_ogr_geos, OGR_G_Contains)
|
|
{
|
|
char *wktOuter =
|
|
const_cast<char *>("POLYGON((-90 -90, -90 90, 190 -90, -90 -90))");
|
|
err_ = OGR_G_CreateFromWkt(&wktOuter, nullptr, &g1_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g1_);
|
|
|
|
char *wktInner = const_cast<char *>("POLYGON((0 0, 10 10, 10 0, 0 0))");
|
|
err_ = OGR_G_CreateFromWkt(&wktInner, nullptr, &g2_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g2_);
|
|
|
|
ASSERT_EQ(OGR_G_Contains(g1_, g2_), TRUE);
|
|
ASSERT_EQ(OGR_G_Contains(g2_, g1_), FALSE);
|
|
}
|
|
|
|
// Test OGR_G_Crosses function
|
|
TEST_F(test_ogr_geos, OGR_G_Crosses)
|
|
{
|
|
char *wkt1 = const_cast<char *>("LINESTRING(0 0, 10 10)");
|
|
err_ = OGR_G_CreateFromWkt(&wkt1, nullptr, &g1_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g1_);
|
|
|
|
char *wkt2 = const_cast<char *>("LINESTRING(10 0, 0 10)");
|
|
err_ = OGR_G_CreateFromWkt(&wkt2, nullptr, &g2_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g2_);
|
|
|
|
ASSERT_EQ(OGR_G_Crosses(g1_, g2_), TRUE);
|
|
|
|
char *wkt3 = const_cast<char *>("LINESTRING(0 0, 0 10)");
|
|
err_ = OGR_G_CreateFromWkt(&wkt3, nullptr, &g3_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g3_);
|
|
|
|
ASSERT_EQ(OGR_G_Crosses(g1_, g3_), FALSE);
|
|
}
|
|
|
|
// Test OGR_G_Disjoint function
|
|
TEST_F(test_ogr_geos, OGR_G_Disjoint)
|
|
{
|
|
char *wkt1 = const_cast<char *>("LINESTRING(0 0, 10 10)");
|
|
err_ = OGR_G_CreateFromWkt(&wkt1, nullptr, &g1_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g1_);
|
|
|
|
char *wkt2 = const_cast<char *>("LINESTRING(10 0, 0 10)");
|
|
err_ = OGR_G_CreateFromWkt(&wkt2, nullptr, &g2_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g2_);
|
|
|
|
ASSERT_EQ(OGR_G_Disjoint(g1_, g2_), FALSE);
|
|
|
|
char *wkt3 = const_cast<char *>("POLYGON((20 20, 20 30, 30 20, 20 20))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt3, nullptr, &g3_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g3_);
|
|
|
|
ASSERT_EQ(OGR_G_Disjoint(g1_, g3_), TRUE);
|
|
}
|
|
|
|
// Test OGR_G_Equals function
|
|
TEST_F(test_ogr_geos, OGR_G_Equals)
|
|
{
|
|
char *wkt1 = const_cast<char *>("LINESTRING(0 0, 10 10)");
|
|
err_ = OGR_G_CreateFromWkt(&wkt1, nullptr, &g1_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g1_);
|
|
|
|
char *wkt2 = const_cast<char *>("LINESTRING(0 0, 10 10)");
|
|
err_ = OGR_G_CreateFromWkt(&wkt2, nullptr, &g2_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g2_);
|
|
|
|
ASSERT_EQ(OGR_G_Equals(g1_, g2_), TRUE);
|
|
|
|
char *wkt3 = const_cast<char *>("POLYGON((20 20, 20 30, 30 20, 20 20))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt3, nullptr, &g3_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g3_);
|
|
|
|
ASSERT_EQ(OGR_G_Equals(g1_, g3_), FALSE);
|
|
}
|
|
|
|
// Test OGR_G_Intersects function
|
|
TEST_F(test_ogr_geos, OGR_G_Intersects)
|
|
{
|
|
char *wkt1 = const_cast<char *>("POLYGON((0 0, 10 10, 10 0, 0 0))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt1, nullptr, &g1_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g1_);
|
|
|
|
char *wkt2 = const_cast<char *>("POLYGON((0 0, 0 10, 10 0, 0 0))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt2, nullptr, &g2_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g2_);
|
|
|
|
ASSERT_EQ(OGR_G_Intersects(g1_, g2_), TRUE);
|
|
|
|
char *wkt3 = const_cast<char *>("POLYGON((20 20, 40 20, 40 40, 20 20))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt3, nullptr, &g3_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g3_);
|
|
|
|
ASSERT_EQ(OGR_G_Intersects(g1_, g3_), FALSE);
|
|
}
|
|
|
|
// Test OGR_G_Overlaps function
|
|
TEST_F(test_ogr_geos, OGR_G_Overlaps)
|
|
{
|
|
char *wkt1 = const_cast<char *>("POLYGON((0 0, 10 10, 10 0, 0 0))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt1, nullptr, &g1_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g1_);
|
|
|
|
char *wkt2 =
|
|
const_cast<char *>("POLYGON((-90 -90, -90 90, 190 -90, -90 -90))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt2, nullptr, &g2_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g2_);
|
|
|
|
ASSERT_EQ(OGR_G_Overlaps(g1_, g2_), FALSE);
|
|
}
|
|
|
|
// Test OGR_G_Touches function
|
|
TEST_F(test_ogr_geos, OGR_G_Touches)
|
|
{
|
|
char *wkt1 = const_cast<char *>("LINESTRING(0 0, 10 10)");
|
|
err_ = OGR_G_CreateFromWkt(&wkt1, nullptr, &g1_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g1_);
|
|
|
|
char *wkt2 = const_cast<char *>("LINESTRING(0 0, 0 10)");
|
|
err_ = OGR_G_CreateFromWkt(&wkt2, nullptr, &g2_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g2_);
|
|
|
|
ASSERT_EQ(OGR_G_Touches(g1_, g2_), TRUE);
|
|
|
|
char *wkt3 = const_cast<char *>("POLYGON((20 20, 20 30, 30 20, 20 20))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt3, nullptr, &g3_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g3_);
|
|
|
|
ASSERT_EQ(OGR_G_Touches(g1_, g3_), FALSE);
|
|
}
|
|
|
|
// Test OGR_G_Within function
|
|
TEST_F(test_ogr_geos, OGR_G_Within)
|
|
{
|
|
char *wkt1 = const_cast<char *>("POLYGON((0 0, 10 10, 10 0, 0 0))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt1, nullptr, &g1_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g1_);
|
|
|
|
char *wkt2 =
|
|
const_cast<char *>("POLYGON((-90 -90, -90 90, 190 -90, -90 -90))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt2, nullptr, &g2_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g2_);
|
|
|
|
ASSERT_EQ(OGR_G_Within(g1_, g2_), TRUE);
|
|
|
|
ASSERT_EQ(OGR_G_Within(g2_, g1_), FALSE);
|
|
}
|
|
|
|
// Test OGR_G_Union function
|
|
TEST_F(test_ogr_geos, OGR_G_Union)
|
|
{
|
|
char *wkt1 = const_cast<char *>("POINT(10 20)");
|
|
err_ = OGR_G_CreateFromWkt(&wkt1, nullptr, &g1_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g1_);
|
|
|
|
char *wkt2 = const_cast<char *>("POINT(30 20)");
|
|
err_ = OGR_G_CreateFromWkt(&wkt2, nullptr, &g2_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g2_);
|
|
|
|
g3_ = OGR_G_Union(g1_, g2_);
|
|
ASSERT_TRUE(nullptr != g3_);
|
|
|
|
OGRGeometryH expect = nullptr;
|
|
char *wktExpect = const_cast<char *>("MULTIPOINT (10 20,30 20)");
|
|
err_ = OGR_G_CreateFromWkt(&wktExpect, nullptr, &expect);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != expect);
|
|
|
|
// Compare operation result against expected geometry
|
|
EXPECT_TRUE(CheckEqualGeometries(g3_, expect, 0.0001));
|
|
|
|
OGR_G_DestroyGeometry(expect);
|
|
}
|
|
|
|
// Test OGR_G_UnaryUnion function
|
|
TEST_F(test_ogr_geos, OGR_G_UnaryUnion)
|
|
{
|
|
char *wkt = const_cast<char *>("GEOMETRYCOLLECTION(POINT(0.5 0.5),"
|
|
"POLYGON((0 0,0 1,1 1,1 0,0 0)),"
|
|
"POLYGON((1 0,1 1,2 1,2 0,1 0)))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt, nullptr, &g1_);
|
|
|
|
g3_ = OGR_G_UnaryUnion(g1_);
|
|
ASSERT_TRUE(nullptr != g3_);
|
|
|
|
OGRGeometryH expect = nullptr;
|
|
char *wktExpect =
|
|
const_cast<char *>("POLYGON ((0 1,1 1,2 1,2 0,1 0,0 0,0 1))");
|
|
err_ = OGR_G_CreateFromWkt(&wktExpect, nullptr, &expect);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != expect);
|
|
|
|
OGREnvelope sEnvelopeIn;
|
|
OGREnvelope sEnvelopeOut;
|
|
OGR_G_GetEnvelope(g1_, &sEnvelopeIn);
|
|
OGR_G_GetEnvelope(g3_, &sEnvelopeOut);
|
|
|
|
// CheckEqualGeometries() doesn't work with GEOS 3.6 with the above
|
|
// expected polygon, because of the order of the nodes, and for some
|
|
// reason OGR_G_Normalize() in CheckEqualGeometries() doesn't fix this,
|
|
// so just fallback to bounding box and area comparison
|
|
EXPECT_EQ(sEnvelopeIn.MinX, sEnvelopeOut.MinX);
|
|
EXPECT_EQ(sEnvelopeIn.MinY, sEnvelopeOut.MinY);
|
|
EXPECT_EQ(sEnvelopeIn.MaxX, sEnvelopeOut.MaxX);
|
|
EXPECT_EQ(sEnvelopeIn.MaxY, sEnvelopeOut.MaxY);
|
|
EXPECT_EQ(OGR_G_Area(g1_), OGR_G_Area(g3_));
|
|
|
|
OGR_G_DestroyGeometry(expect);
|
|
}
|
|
|
|
// Test OGR_G_Intersection function
|
|
TEST_F(test_ogr_geos, OGR_G_Intersection)
|
|
{
|
|
char *wkt1 = const_cast<char *>("POLYGON((0 0, 10 10, 10 0, 0 0))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt1, nullptr, &g1_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g1_);
|
|
|
|
char *wkt2 = const_cast<char *>("POLYGON((0 0, 0 10, 10 0, 0 0))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt2, nullptr, &g2_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g2_);
|
|
|
|
g3_ = OGR_G_Intersection(g1_, g2_);
|
|
ASSERT_TRUE(nullptr != g3_);
|
|
|
|
OGRGeometryH expect = nullptr;
|
|
char *wktExpect = const_cast<char *>("POLYGON ((0 0,5 5,10 0,0 0))");
|
|
err_ = OGR_G_CreateFromWkt(&wktExpect, nullptr, &expect);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != expect);
|
|
|
|
// Compare operation result against expected geometry
|
|
EXPECT_TRUE(CheckEqualGeometries(g3_, expect, 0.0001));
|
|
|
|
OGR_G_DestroyGeometry(expect);
|
|
}
|
|
|
|
// Test OGR_G_Difference function
|
|
TEST_F(test_ogr_geos, OGR_G_Difference)
|
|
{
|
|
char *wkt1 = const_cast<char *>("POLYGON((0 0, 10 10, 10 0, 0 0))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt1, nullptr, &g1_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g1_);
|
|
|
|
char *wkt2 = const_cast<char *>("POLYGON((0 0, 0 10, 10 0, 0 0))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt2, nullptr, &g2_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g2_);
|
|
|
|
g3_ = OGR_G_Difference(g1_, g2_);
|
|
ASSERT_TRUE(nullptr != g3_);
|
|
|
|
OGRGeometryH expect = nullptr;
|
|
char *wktExpect = const_cast<char *>("POLYGON ((5 5,10 10,10 0,5 5))");
|
|
err_ = OGR_G_CreateFromWkt(&wktExpect, nullptr, &expect);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != expect);
|
|
|
|
// Compare operation result against expected geometry
|
|
EXPECT_TRUE(CheckEqualGeometries(g3_, expect, 0.0001));
|
|
|
|
OGR_G_DestroyGeometry(expect);
|
|
}
|
|
|
|
// Test OGR_G_SymDifference function
|
|
TEST_F(test_ogr_geos, OGR_G_SymDifference)
|
|
{
|
|
char *wkt1 = const_cast<char *>("POLYGON((0 0, 10 10, 10 0, 0 0))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt1, nullptr, &g1_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g1_);
|
|
|
|
char *wkt2 = const_cast<char *>("POLYGON((0 0, 0 10, 10 0, 0 0))");
|
|
err_ = OGR_G_CreateFromWkt(&wkt2, nullptr, &g2_);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != g2_);
|
|
|
|
g3_ = OGR_G_SymDifference(g1_, g2_);
|
|
ASSERT_TRUE(nullptr != g3_);
|
|
|
|
OGRGeometryH expect = nullptr;
|
|
char *wktExpect = const_cast<char *>(
|
|
"MULTIPOLYGON (((5 5,0 0,0 10,5 5)),((5 5,10 10,10 0,5 5)))");
|
|
err_ = OGR_G_CreateFromWkt(&wktExpect, nullptr, &expect);
|
|
ASSERT_EQ(OGRERR_NONE, err_);
|
|
ASSERT_TRUE(nullptr != expect);
|
|
|
|
// Compare operation result against expected geometry
|
|
EXPECT_TRUE(CheckEqualGeometries(g3_, expect, 0.0001));
|
|
|
|
OGR_G_DestroyGeometry(expect);
|
|
}
|
|
} // namespace
|