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
|
/**********************************************************************
*
* GEOS - Geometry Engine Open Source
* http://geos.osgeo.org
*
* Copyright (C) 2009 Sandro Santilli <strk@kbt.io>
*
* This is free software; you can redistribute and/or modify it under
* the terms of the GNU Lesser General Public Licence as published
* by the Free Software Foundation.
* See the COPYING file for more information.
*
**********************************************************************
*
* Last port: jtstest/testrunner/BufferResultMatcher.java rev rev 1.6 (JTS-1.11)
*
**********************************************************************/
#include "BufferResultMatcher.h"
#include <geos/geom/Geometry.h>
#include <geos/geom/HeuristicOverlay.h>
#include <geos/operation/overlay/OverlayOp.h>
#include <geos/algorithm/distance/DiscreteHausdorffDistance.h>
#include <cmath>
namespace geos {
namespace xmltester {
bool
BufferResultMatcher::isBufferResultMatch(const geom::Geometry& actualBuffer,
const geom::Geometry& expectedBuffer,
double distance)
{
if(actualBuffer.isEmpty() && expectedBuffer.isEmpty()) {
return true;
}
/*
* MD - need some more checks here - symDiffArea won't catch
* very small holes ("tears")
* near the edge of computed buffers (which can happen
* in current version of JTS (1.8)).
* This can probably be handled by testing
* that every point of the actual buffer is at least a certain
* distance away from the geometry boundary.
*/
if(! isSymDiffAreaInTolerance(actualBuffer, expectedBuffer)) {
std::cerr << "isSymDiffAreaInTolerance failed" << std::endl;
return false;
}
if(! isBoundaryHausdorffDistanceInTolerance(actualBuffer,
expectedBuffer, distance)) {
std::cerr << "isBoundaryHasudorffDistanceInTolerance failed" << std::endl;
return false;
}
return true;
}
bool
BufferResultMatcher::isSymDiffAreaInTolerance(
const geom::Geometry& actualBuffer,
const geom::Geometry& expectedBuffer)
{
typedef std::unique_ptr<geom::Geometry> GeomPtr;
using namespace operation::overlay;
using geos::geom::HeuristicOverlay;
double area = expectedBuffer.getArea();
GeomPtr diff = HeuristicOverlay(&actualBuffer, &expectedBuffer,
OverlayOp::opSYMDIFFERENCE);
double areaDiff = diff->getArea();
// can't get closer than difference area = 0 !
// This also handles case when symDiff is empty
if(areaDiff <= 0.0) {
return true;
}
if(area <= 0) {
return false;
}
double frac = areaDiff / area;
bool ret = frac < MAX_RELATIVE_AREA_DIFFERENCE;
if(! ret) {
std::cerr << "symDiffArea frac: " << frac << " tolerated " << MAX_RELATIVE_AREA_DIFFERENCE << std::endl;
}
return ret;
}
bool
BufferResultMatcher::isBoundaryHausdorffDistanceInTolerance(
const geom::Geometry& actualBuffer,
const geom::Geometry& expectedBuffer, double distance)
{
typedef std::unique_ptr<geom::Geometry> GeomPtr;
using geos::algorithm::distance::DiscreteHausdorffDistance;
GeomPtr actualBdy(actualBuffer.getBoundary());
GeomPtr expectedBdy(expectedBuffer.getBoundary());
DiscreteHausdorffDistance haus(*actualBdy, *expectedBdy);
haus.setDensifyFraction(0.25);
double maxDistanceFound = haus.orientedDistance();
double expectedDistanceTol = fabs(distance) / MAX_HAUSDORFF_DISTANCE_FACTOR;
if(expectedDistanceTol < MIN_DISTANCE_TOLERANCE) {
expectedDistanceTol = MIN_DISTANCE_TOLERANCE;
}
if(maxDistanceFound > expectedDistanceTol) {
std::cerr << "maxDistanceFound: " << maxDistanceFound << " tolerated " << expectedDistanceTol << std::endl;
return false;
}
return true;
}
} // namespace geos::xmltester
} // namespace geos
|