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
|
//
// Test Suite for geos::algorithm::distance::DiscreteFrechetDistance
//
#include <tut/tut.hpp>
// geos
#include <geos/constants.h>
#include <geos/io/WKTReader.h>
#include <geos/algorithm/distance/DiscreteFrechetDistance.h>
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/Geometry.h> // required for use in unique_ptr
#include <geos/geom/Coordinate.h>
#include <geos/util.h>
// std
#include <cmath>
#include <string>
#include <memory>
namespace geos {
namespace geom {
class Geometry;
}
}
using namespace geos::geom;
using namespace geos::algorithm::distance; // for Location
namespace tut {
//
// Test Group
//
struct test_frechetdistance_data {
geos::io::WKTReader reader;
static constexpr double TOLERANCE = 0.00001;
void
checkDiscreteFrechet(const std::string& wkt1, const std::string& wkt2,
double expectedDistance)
{
std::unique_ptr<Geometry> g1(reader.read(wkt1));
std::unique_ptr<Geometry> g2(reader.read(wkt2));
double distance = DiscreteFrechetDistance::distance(*g1, *g2);
ensure_equals("checkDiscreteFrechet", distance, expectedDistance, TOLERANCE);
}
void
checkDensifiedFrechet(const std::string& wkt1, const std::string& wkt2,
double densifyFactor, double expectedDistance)
{
std::unique_ptr<Geometry> g1(reader.read(wkt1));
std::unique_ptr<Geometry> g2(reader.read(wkt2));
double distance = DiscreteFrechetDistance::distance(*g1, *g2, densifyFactor);
ensure_equals("checkDensifiedFrechet", distance, expectedDistance, TOLERANCE);
}
};
typedef test_group<test_frechetdistance_data> group;
typedef group::object object;
group test_frechetdistance_group("geos::algorithm::distance::DiscreteFrechetDistance");
// 1 - testLineSegments
template<>
template<>
void object::test<1> ()
{
checkDiscreteFrechet("LINESTRING (0 0, 2 1)", "LINESTRING (0 0, 2 0)", 1.0);
// zero densify factor
try {
checkDensifiedFrechet("LINESTRING (0 0, 2 1)", "LINESTRING EMPTY", 0.0, 0);
}
catch(const geos::util::IllegalArgumentException& e) {
// We do expect an exception
::geos::ignore_unused_variable_warning(e);
}
// too big densify factor
try {
checkDensifiedFrechet("LINESTRING (0 0, 2 1)", "LINESTRING EMPTY", 1 + 1e-10, 0);
}
catch(const geos::util::IllegalArgumentException& e) {
// We do expect an exception
::geos::ignore_unused_variable_warning(e);
}
// too small positive densify factor
try {
checkDensifiedFrechet("LINESTRING (0 0, 2 1)", "LINESTRING EMPTY", 1e-30, 0);
}
catch(const geos::util::IllegalArgumentException& e) {
// We do expect an exception
::geos::ignore_unused_variable_warning(e);
}
}
// 2 - testLineSegments2
template<>
template<>
void object::test<2> ()
{
checkDiscreteFrechet("LINESTRING (0 0, 2 0)", "LINESTRING (0 1, 1 2, 2 1)", 2.23606797749979);
}
// 3 - testLinePoints
template<>
template<>
void object::test<3> ()
{
checkDiscreteFrechet("LINESTRING (0 0, 2 0)", "MULTIPOINT ((0 1), (1 0), (2 1))", 1.0);
}
// 4 - testLinesShowingDiscretenessEffect
//
// Shows effects of limiting FD to vertices
// Answer is not true Frechet distance.
//
template<>
template<>
void object::test<4> ()
{
checkDiscreteFrechet("LINESTRING (0 0, 100 0)", "LINESTRING (0 0, 50 50, 100 0)", 70.7106781186548);
// densifying provides accurate HD
checkDensifiedFrechet("LINESTRING (0 0, 100 0)", "LINESTRING (0 0, 50 50, 100 0)", 0.5, 50.0);
}
// 5 - test Line Segments revealing distance initialization bug
template<>
template<>
void object::test<5> ()
{
checkDiscreteFrechet("LINESTRING (1 1, 2 2)", "LINESTRING (1 4, 2 3)", 3);
}
// Empty arguments should throw error
template<>
template<>
void object::test<6> ()
{
auto g1 = reader.read("LINESTRING EMPTY");
auto g2 = reader.read("POLYGON EMPTY");
try {
DiscreteFrechetDistance::distance(*g1, *g2);
} catch (const geos::util::GEOSException& e) {
::geos::ignore_unused_variable_warning(e);
}
}
// Large test data set caused stack overflow in old
// recursive version of the algorithm
// https://github.com/libgeos/geos/issues/516
#include "DiscreteFrechetDistanceData.h"
template<>
template<>
void object::test<7> ()
{
checkDiscreteFrechet(LS1, LS2, 2.49903e-04);
}
template<>
template<>
void object::test<8> ()
{
checkDensifiedFrechet("LINESTRING(1 0, 2 0)", "LINESTRING(-1 0, 0 0, 7 8)", 0.002, 9.43398);
}
template<>
template<>
void object::test<9> ()
{
checkDensifiedFrechet("POINT(-11.1111111 40)", "POINT(-11.1111111 40)", 0.8, 0);
}
} // namespace tut
|