geos/tests/unit/simplify/DouglasPeuckerSimplifierTest.cpp

377 строки
9.7 KiB
C++

//
// Test Suite for geos::simplify::DouglasPeuckerSimplifierTest
#include <tut/tut.hpp>
// geos
#include <geos/io/WKTReader.h>
#include <geos/io/WKTWriter.h>
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/Geometry.h>
#include <geos/geom/Coordinate.h>
#include <geos/geom/CoordinateSequenceFilter.h>
#include <geos/simplify/DouglasPeuckerSimplifier.h>
#include <geos/util.h>
// std
#include <string>
#include <memory>
namespace tut {
using namespace geos::simplify;
//
// Test Group
//
// Common data used by tests
struct test_dpsimp_data {
geos::io::WKTReader wktreader;
geos::io::WKTWriter wktwriter;
typedef geos::geom::Geometry::Ptr GeomPtr;
test_dpsimp_data()
:
wktreader()
{}
};
typedef test_group<test_dpsimp_data> group;
typedef group::object object;
group test_dpsimp_group("geos::simplify::DouglasPeuckerSimplifier");
//
// Test Cases
//
// 1 - PolygonNoReduction
template<>
template<>
void object::test<1>
()
{
std::string wkt("POLYGON((20 220, 40 220, 60 220, 80 220, 100 220, \
120 220, 140 220, 140 180, 100 180, 60 180, 20 180, 20 220))");
GeomPtr g(wktreader.read(wkt));
GeomPtr simplified = DouglasPeuckerSimplifier::simplify(
g.get(), 10.0);
ensure(simplified->isValid());
// topology is unchanged
ensure(simplified->equals(g.get()));
}
// 2 - PolygonReductionWithSplit
template<>
template<>
void object::test<2>
()
{
std::string wkt_in("POLYGON ((40 240, 160 241, 280 240, 280 160, \
160 240, 40 140, 40 240))");
std::string wkt_ex("MULTIPOLYGON (((40.0 240.0, 160.0 240.0, 40.0 140.0, 40.0 240.0)), \
((160.0 240.0, 280.0 240.0, 280.0 160.0, 160.0 240.0)))");
GeomPtr g(wktreader.read(wkt_in));
GeomPtr expected(wktreader.read(wkt_ex));
// TODO: This test blows because if instability of geos.index.strtree::yComparator() predicate
GeomPtr simplified = DouglasPeuckerSimplifier::simplify(
g.get(), 10.0);
ensure(simplified->isValid());
ensure(simplified->equalsExact(expected.get()));
}
// 3 - PolygonReduction
template<>
template<>
void object::test<3>
()
{
std::string wkt_in("POLYGON ((120 120, 121 121, 122 122, 220 120, \
180 199, 160 200, 140 199, 120 120))");
std::string wkt_ex("POLYGON ((120 120, 140 199, 160 200, 180 199, 220 120, 120 120))");
GeomPtr g(wktreader.read(wkt_in));
GeomPtr expected(wktreader.read(wkt_ex));
GeomPtr simplified = DouglasPeuckerSimplifier::simplify(
g.get(), 10.0);
ensure(simplified->isValid());
ensure(simplified->equalsExact(expected.get()));
}
// 4 - PolygonWithTouchingHole
template<>
template<>
void object::test<4>
()
{
std::string wkt_in("POLYGON ((80 200, 240 200, 240 60, 80 60, 80 200), \
(120 120, 220 120, 180 199, 160 200, 140 199, 120 120))");
std::string wkt_ex("POLYGON ((80 200, 160 200, 240 200, 240 60, 80 60, 80 200), \
(160 200, 140 199, 120 120, 220 120, 180 199, 160 200)))");
GeomPtr g(wktreader.read(wkt_in));
GeomPtr expected(wktreader.read(wkt_ex));
GeomPtr simplified = DouglasPeuckerSimplifier::simplify(
g.get(), 10.0);
ensure(simplified->isValid());
ensure(simplified->isValid());
ensure(simplified->equalsExact(expected.get()));
}
// 5 - FlattishPolygon
template<>
template<>
void object::test<5>
()
{
std::string wkt_in("POLYGON ((0 0, 50 0, 53 0, 55 0, 100 0, 70 1, 60 1, 50 1, 40 1, 0 0))");
std::string wkt_ex("POLYGON EMPTY");
GeomPtr g(wktreader.read(wkt_in));
GeomPtr expected(wktreader.read(wkt_ex));
GeomPtr simplified = DouglasPeuckerSimplifier::simplify(
g.get(), 10.0);
ensure(simplified->isValid());
ensure(simplified->equalsExact(expected.get()));
//ensure_equals( *simplified, *expected );
}
// 6 - TinySquare
template<>
template<>
void object::test<6>
()
{
std::string wkt_in("POLYGON ((0 5, 5 5, 5 0, 0 0, 0 1, 0 5))");
std::string wkt_ex("POLYGON EMPTY");
GeomPtr g(wktreader.read(wkt_in));
GeomPtr expected(wktreader.read(wkt_ex));
GeomPtr simplified = DouglasPeuckerSimplifier::simplify(
g.get(), 10.0);
ensure(simplified->isValid());
ensure(simplified->equalsExact(expected.get()));
}
// 7 - TinyLineString
template<>
template<>
void object::test<7>
()
{
std::string wkt_in("LINESTRING (0 5, 1 5, 2 5, 5 5)");
std::string wkt_ex("LINESTRING (0 5, 5 5)");
GeomPtr g(wktreader.read(wkt_in));
GeomPtr expected(wktreader.read(wkt_ex));
GeomPtr simplified = DouglasPeuckerSimplifier::simplify(
g.get(), 10.0);
ensure(simplified->isValid());
ensure(simplified->equalsExact(expected.get()));
}
// 8 - MultiPoint
template<>
template<>
void object::test<8>
()
{
std::string wkt_in("MULTIPOINT(80 200, 240 200, 240 60, 80 60, 80 200, 140 199, 120 120)");
GeomPtr g(wktreader.read(wkt_in));
GeomPtr simplified = DouglasPeuckerSimplifier::simplify(
g.get(), 10.0);
// MultiPoint is *not* simplified
ensure(simplified->equalsExact(g.get()));
}
// 9 - MultiLineString
template<>
template<>
void object::test<9>
()
{
std::string wkt_in("MULTILINESTRING( (0 0, 50 0, 70 0, 80 0, 100 0), \
(0 0, 50 1, 60 1, 100 0) )");
std::string wkt_ex("MULTILINESTRING( (0 0, 100 0), (0 0, 100 0) )");
GeomPtr g(wktreader.read(wkt_in));
GeomPtr expected(wktreader.read(wkt_ex));
GeomPtr simplified = DouglasPeuckerSimplifier::simplify(
g.get(), 10.0);
ensure(simplified->isValid());
ensure(simplified->equalsExact(expected.get()));
}
// 10 - GeometryCollection
template<>
template<>
void object::test<10>
()
{
std::string wkt_in("GEOMETRYCOLLECTION ( \
MULTIPOINT (80 200, 240 200, 240 60, 80 60, 80 200, 140 199, 120 120), \
POLYGON ((80 200, 240 200, 240 60, 80 60, 80 200)), \
LINESTRING (80 200, 240 200, 240 60, 80 60, 80 200, 140 199, 120 120) )");
std::string wkt_ex("MULTILINESTRING( (0 0, 100 0), (0 0, 100 0) )");
GeomPtr g(wktreader.read(wkt_in));
GeomPtr expected(wktreader.read(wkt_ex));
GeomPtr simplified = DouglasPeuckerSimplifier::simplify(
g.get(), 10.0);
ensure(simplified->isValid());
// Non simplification occurs
ensure(simplified->equalsExact(g.get()));
}
// 11 - A kind of reversed simplification
template<>
template<>
void object::test<11>
()
{
using namespace geos::geom;
std::string
wkt("MULTIPOLYGON(((0.561648 1,1 1,1 0,0.468083 0,0.52758 0.00800554,0.599683 0.0280924, 0.601611 0.265374, \
0.622693 0.316765,0.69507 0.357497,0.695623 0.429711,0.655111 0.502298, 0.696467 0.543147,0.840712 0.593546, \
0.882583 0.66546,0.852357 0.748213,0.84264 0.789567,0 .832667 0.841202,0.832667 0.841202,0.740538 0.873004, \
0.617349 0.905045,0.566576 0.977697,0.561648 1)),((0 0.801979,0.0308575 0.786234,0.0705513 0.631135, \
0.141616 0.527248,0.233985 0.505872,0.264777 0.526263,0.336631 0.505009,0.356603 0.422321,0.355803 0.350038, \
0.375252 0.205364,0.415206 0.0709182,0.45479 0,0 0,0 0,0 0.801979)))");
GeomPtr g(wktreader.read(wkt));
std::size_t const gN = g->getNumPoints();
ensure_equals(gN, std::size_t(37));
// 1) Simplify with 1/2048
double const d1 = 1 / 2048.0;
GeomPtr simplified1 = DouglasPeuckerSimplifier::simplify(g.get(), d1);
ensure(simplified1->isValid());
ensure(simplified1->equals(g.get()));
std::size_t const simplifiedN1 = simplified1->getNumPoints();
ensure_equals(simplifiedN1, std::size_t(36));
//std::string const simplifiedWkd = wktwriter.write(simplified1.get());
// 2) Multiply points by 2047
struct Multiplier : public CoordinateSequenceFilter {
double f;
Multiplier(double p_f) : f(p_f) {}
void
filter_rw(CoordinateSequence& seq, std::size_t i) override
{
seq.setOrdinate(i, CoordinateSequence::X, seq[i].x * f);
seq.setOrdinate(i, CoordinateSequence::Y, seq[i].y * f);
}
void
filter_ro(const CoordinateSequence& seq, std::size_t i) override
{
::geos::ignore_unused_variable_warning(seq);
::geos::ignore_unused_variable_warning(i);
}
bool
isDone() const override
{
return false;
}
bool
isGeometryChanged() const override
{
return true;
}
};
Multiplier m(2047);
g->apply_rw(m);
std::size_t const multipliedN = g->getNumPoints();
ensure_equals(multipliedN, std::size_t(37));
//std::string const multipliedWkt = wktwriter.write(g.get());
// 3) Simplify with 1.0
double const d2 = 1.0;
GeomPtr simplified2 = DouglasPeuckerSimplifier::simplify(g.get(), d2);
ensure(simplified2->isValid());
ensure(simplified2->equals(g.get()));
std::size_t const simplifiedN2 = simplified2->getNumPoints();
ensure_equals(simplifiedN2, std::size_t(36));
//std::string const simplifiedWkt2 = wktwriter.write(simplified2.get());
}
// 13 - Polygon with inner ring whose extent is less than the simplify distance (#741)
template<>
template<>
void object::test<13>
()
{
std::string wkt_in("POLYGON ((0 0,0 1,1 1,0 0),(0.1 0.1,0.2 0.1,0.2 0.2,0.1 0.1))");
std::string wkt_ex("POLYGON ((0 0,0 1,1 1,0 0))");
GeomPtr g(wktreader.read(wkt_in));
GeomPtr expected(wktreader.read(wkt_ex));
GeomPtr simplified = DouglasPeuckerSimplifier::simplify(
g.get(), 0.5);
ensure(simplified->isValid());
ensure(simplified->equalsExact(expected.get()));
}
} // namespace tut