176 lines
5.3 KiB
C
176 lines
5.3 KiB
C
|
/**********************************************************************
|
||
|
*
|
||
|
* GEOS - Geometry Engine Open Source
|
||
|
* http://geos.osgeo.org
|
||
|
*
|
||
|
* Copyright (C) 2016 Shinichi SUGIYAMA (shin.sugi@gmail.com)
|
||
|
*
|
||
|
* 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: original work
|
||
|
*
|
||
|
* Developed by Shinichi SUGIYAMA (shin.sugi@gmail.com)
|
||
|
* based on http://www.kr.tuwien.ac.at/staff/eiter/et-archive/cdtr9464.pdf
|
||
|
*
|
||
|
**********************************************************************/
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <geos/export.h>
|
||
|
#include <geos/algorithm/distance/PointPairDistance.h> // for composition
|
||
|
#include <geos/algorithm/distance/DistanceToPoint.h> // for composition
|
||
|
#include <geos/util/IllegalArgumentException.h> // for inlines
|
||
|
#include <geos/geom/Geometry.h> // for inlines
|
||
|
#include <geos/util/math.h> // for inlines
|
||
|
#include <geos/geom/CoordinateFilter.h> // for inheritance
|
||
|
#include <geos/geom/CoordinateSequence.h> // for inheritance
|
||
|
|
||
|
#include <cstddef>
|
||
|
#include <vector>
|
||
|
|
||
|
#ifdef _MSC_VER
|
||
|
#pragma warning(push)
|
||
|
#pragma warning(disable: 4251) // warning C4251: needs to have dll-interface to be used by clients of class
|
||
|
#endif
|
||
|
|
||
|
namespace geos {
|
||
|
namespace algorithm {
|
||
|
//class RayCrossingCounter;
|
||
|
}
|
||
|
namespace geom {
|
||
|
class Geometry;
|
||
|
class Coordinate;
|
||
|
//class CoordinateSequence;
|
||
|
}
|
||
|
namespace index {
|
||
|
namespace intervalrtree {
|
||
|
//class SortedPackedIntervalRTree;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
namespace geos {
|
||
|
namespace algorithm { // geos::algorithm
|
||
|
namespace distance { // geos::algorithm::distance
|
||
|
|
||
|
/** \brief
|
||
|
* An algorithm for computing a distance metric
|
||
|
* which is an approximation to the Frechet Distance
|
||
|
* based on a discretization of the input {@link geom::Geometry}.
|
||
|
*
|
||
|
* The algorithm computes the Frechet distance restricted to discrete points
|
||
|
* for one of the geometries.
|
||
|
* The points can be either the vertices of the geometries (the default),
|
||
|
* or the geometries with line segments densified by a given fraction.
|
||
|
* Also determines two points of the Geometries which are separated by the
|
||
|
* computed distance.
|
||
|
*
|
||
|
* This algorithm is an approximation to the standard Frechet distance.
|
||
|
* Specifically,
|
||
|
* <pre>
|
||
|
* for all geometries a, b: DFD(a, b) >= FD(a, b)
|
||
|
* </pre>
|
||
|
* The approximation can be made as close as needed by densifying the
|
||
|
* input geometries.
|
||
|
* In the limit, this value will approach the true Frechet distance:
|
||
|
* <pre>
|
||
|
* DFD(A, B, densifyFactor) -> FD(A, B) as densifyFactor -> 0.0
|
||
|
* </pre>
|
||
|
* The default approximation is exact or close enough for a large subset of
|
||
|
* useful cases.
|
||
|
*
|
||
|
* The difference between DFD and FD is bounded
|
||
|
* by the length of the longest edge of the polygonal curves.
|
||
|
*
|
||
|
* Fréchet distance sweep continuously along their respective curves
|
||
|
* and the direction of curves is significant.
|
||
|
* This makes a better measure of similarity than Hausdorff distance.
|
||
|
*
|
||
|
* An example showing how different DHD and DFD are:
|
||
|
* <pre>
|
||
|
* A = LINESTRING (0 0, 50 200, 100 0, 150 200, 200 0)
|
||
|
* B = LINESTRING (0 200, 200 150, 0 100, 200 50, 0 0)
|
||
|
* B' = LINESTRING (0 0, 200 50, 0 100, 200 150, 0 200)
|
||
|
*
|
||
|
* DHD(A, B) = DHD(A, B') = 48.5071250072666
|
||
|
* DFD(A, B) = 200
|
||
|
* DFD(A, B') = 282.842712474619
|
||
|
* </pre>
|
||
|
*/
|
||
|
class GEOS_DLL DiscreteFrechetDistance {
|
||
|
public:
|
||
|
|
||
|
static double distance(const geom::Geometry& g0,
|
||
|
const geom::Geometry& g1);
|
||
|
|
||
|
static double distance(const geom::Geometry& g0,
|
||
|
const geom::Geometry& g1, double densifyFrac);
|
||
|
|
||
|
DiscreteFrechetDistance(const geom::Geometry& p_g0,
|
||
|
const geom::Geometry& p_g1)
|
||
|
:
|
||
|
g0(p_g0),
|
||
|
g1(p_g1),
|
||
|
ptDist(),
|
||
|
densifyFrac(0.0)
|
||
|
{}
|
||
|
|
||
|
/**
|
||
|
* Sets the fraction by which to densify each segment.
|
||
|
* Each segment will be (virtually) split into a number of equal-length
|
||
|
* subsegments, whose fraction of the total length is closest
|
||
|
* to the given fraction.
|
||
|
*
|
||
|
* @param dFrac
|
||
|
*/
|
||
|
void setDensifyFraction(double dFrac);
|
||
|
|
||
|
double
|
||
|
distance()
|
||
|
{
|
||
|
compute(g0, g1);
|
||
|
return ptDist.getDistance();
|
||
|
}
|
||
|
|
||
|
const std::array<geom::CoordinateXY, 2>
|
||
|
getCoordinates() const
|
||
|
{
|
||
|
return ptDist.getCoordinates();
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
geom::Coordinate getSegmentAt(const geom::CoordinateSequence& seq, std::size_t index);
|
||
|
|
||
|
PointPairDistance& getFrechetDistance(std::vector< std::vector<PointPairDistance> >& ca, std::size_t i, std::size_t j,
|
||
|
const geom::CoordinateSequence& p, const geom::CoordinateSequence& q);
|
||
|
|
||
|
void compute(const geom::Geometry& discreteGeom, const geom::Geometry& geom);
|
||
|
|
||
|
const geom::Geometry& g0;
|
||
|
|
||
|
const geom::Geometry& g1;
|
||
|
|
||
|
PointPairDistance ptDist;
|
||
|
|
||
|
/// Value of 0.0 indicates that no densification should take place
|
||
|
double densifyFrac; // = 0.0;
|
||
|
|
||
|
// Declare type as noncopyable
|
||
|
DiscreteFrechetDistance(const DiscreteFrechetDistance& other) = delete;
|
||
|
DiscreteFrechetDistance& operator=(const DiscreteFrechetDistance& rhs) = delete;
|
||
|
};
|
||
|
|
||
|
} // geos::algorithm::distance
|
||
|
} // geos::algorithm
|
||
|
} // geos
|
||
|
|
||
|
#ifdef _MSC_VER
|
||
|
#pragma warning(pop)
|
||
|
#endif
|
||
|
|