Adress Mael's review and partially the one of Pierre

This commit is contained in:
Andreas Fabri 2025-02-05 11:51:11 +00:00
parent e34868cea3
commit 295ed81e91
10 changed files with 89 additions and 40 deletions

View File

@ -4,7 +4,7 @@
The concept `FrechetDistanceTraits` defines the requirements of the The concept `FrechetDistanceTraits` defines the requirements of the
first template parameter of the functions `CGAL::is_Frechet_distance_larger()` first template parameter of the functions `CGAL::is_Frechet_distance_larger()`
and `CGAL::approximate_Frechet_distance()`. and `CGAL::bounded_error_Frechet_distance()`.
\cgalHasModelsBegin \cgalHasModelsBegin

View File

@ -14,10 +14,10 @@ namespace CGAL {
This package provides functions for computing the Fréchet distance of polylines in any dimension under the Euclidean metric. This package provides functions for computing the Fréchet distance of polylines in any dimension under the Euclidean metric.
\section secFrechetDistanceIntroduction Introdution \section secFrechetDistanceIntroduction Introduction
The Fréchet distance is a classical dissimilarity measure between polylines. The Fréchet distance is a classical dissimilarity measure between polylines.
Its advantages over other measures is that it both considers the polylines as continuous objects and takes into account the ordering of the points. Its advantages over other measures are that it both considers the polylines as continuous objects and takes into account the ordering of the points.
Intuitively, the Fréchet distance is commonly explained as follows: Imagine a human walking on one polyline while a dog walks on the other polyline, Intuitively, the Fréchet distance is commonly explained as follows: Imagine a human walking on one polyline while a dog walks on the other polyline,
they are connected by a leash, and they are only allowed to walk forward. The Fréchet distance is the shortest leash length that allows the human they are connected by a leash, and they are only allowed to walk forward. The Fréchet distance is the shortest leash length that allows the human
and the dog to jointly walk from start to end on their respective trajectories. and the dog to jointly walk from start to end on their respective trajectories.
@ -45,11 +45,10 @@ The traits classes have as template parameter a kernel, model of the concept `Ke
In case the static constant `Has_filtered_predicates` of the kernel is `true`, the functions In case the static constant `Has_filtered_predicates` of the kernel is `true`, the functions
combine interval arithmetic with a fallback to exact computing in case comparisons of intervals combine interval arithmetic with a fallback to exact computing in case comparisons of intervals
are uncertain. This means for `Simple_cartesian<double>` that there are no guarantees, for are uncertain. This means for `Simple_cartesian<double>` that there are no guarantees, for
`Simple_cartesian<Exact_rational>` that all computation is done with exact rationals, `Simple_cartesian<Exact_rational>` that all computations are performed with exact rationals,
and for kernels such as `Exact_predicates_inexact_constructions_kernel`, `Exact_predicates_exact_constructions_kernel`, and for kernels such as `Exact_predicates_inexact_constructions_kernel`, `Exact_predicates_exact_constructions_kernel`,
`Exact_predicates_exact_constructions_kernel_with_sqrt`, `Exact_predicates_exact_constructions_kernel_with_sqrt`,
as well as `Epick_d` and `Epeck_d`, the computation is filtered and hence fast and at as well as `Epick_d` and `Epeck_d`, the computation is filtered and hence both fast and guaranteed to be correct.
the same time guaranteed to be correct.
\section secFrechetDistanceImplementation Implementation \section secFrechetDistanceImplementation Implementation
@ -92,6 +91,14 @@ polylines in 4-dimensional Euclidean space using `bounded_error_Frechet_distance
\cgalExample{Frechet_distance/Frechet_distance_d.cpp} \cgalExample{Frechet_distance/Frechet_distance_d.cpp}
\subsection subsecFrechetDistanceDSExample Searching Close Curves
The following example shows how to store many curves in a data structure and to find all curves
closed than a distance bound for a query curve.
\cgalExample{Frechet_distance/Frechet_DS_3.cpp}
\subsection subsecFrechetDistanceImageCredits Image Credits \subsection subsecFrechetDistanceImageCredits Image Credits
The teaser image is a visualization of two data points from the <a href="https://archive.ics.uci.edu/dataset/175/character+trajectories">Character Trajectories</a> data set. The teaser image is a visualization of two data points from the <a href="https://archive.ics.uci.edu/dataset/175/character+trajectories">Character Trajectories</a> data set.

View File

@ -2,4 +2,5 @@
\example Frechet_distance/Frechet_distance_2.cpp \example Frechet_distance/Frechet_distance_2.cpp
\example Frechet_distance/Frechet_distance_3.cpp \example Frechet_distance/Frechet_distance_3.cpp
\example Frechet_distance/Frechet_distance_d.cpp \example Frechet_distance/Frechet_distance_d.cpp
\example Frechet_distance/Frechet_DS_3.cpp
*/ */

View File

@ -87,20 +87,21 @@ namespace internal
* \ingroup PkgFrechetDistanceFunctions * \ingroup PkgFrechetDistanceFunctions
* determines if the Frechet distance between two polylines is larger than a given distance bound. * determines if the Frechet distance between two polylines is larger than a given distance bound.
* *
* \tparam Traits a model of `FrechetDistanceTraits` * \tparam PointRange a model of the concept `RandomAccessContainer` whose value type is a `Point_d`
* \tparam PointRange a model of the concept `RandomAccessContainer` with `Traits::Point_d` as value type
* \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" * \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
* *
* \param polyline1 the first polyline defined by a sequence of consecutive points * \param polyline1 the first polyline, defined by a sequence of consecutive points
* \param polyline2 the second polyline defined by a sequence of consecutive points * \param polyline2 the second polyline, defined by a sequence of consecutive points
* \param distance_bound the distance to compare against * \param distance_bound the distance to compare against
* \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below: * \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" containing the one listed below:
* *
* \cgalNamedParamsBegin * \cgalNamedParamsBegin
* \cgalParamNBegin{geom_traits} * \cgalParamNBegin{geom_traits}
* \cgalParamDescription{an instance of a geometric traits class} * \cgalParamDescription{an instance of a geometric traits class}
* \cgalParamType{a model of `FrechetDistanceTraits`} * \cgalParamType{a model of `FrechetDistanceTraits`}
* \cgalParamDefault{`Frechet_distance_traits_2`, `Frechet_distance_traits_3`, or`Frechet_distance_traits_d`, depending on the dimension of the point type.} * \cgalParamDefault{`Frechet_distance_traits_2`, `Frechet_distance_traits_3`, or `Frechet_distance_traits_d`, depending on the dimension of the point type
* deduced from the point type, using `Kernel_traits`.}
* \cgalParamExtra{The input point type (the range's value type) must be equal to the traits' `Point_d` type.
* \cgalParamNEnd * \cgalParamNEnd
* \cgalNamedParamsEnd * \cgalNamedParamsEnd
* *
@ -144,27 +145,28 @@ bool is_Frechet_distance_larger(const PointRange& polyline1,
* returns an estimate of the Fréchet distance between the two polylines that is at most `error_bound` * returns an estimate of the Fréchet distance between the two polylines that is at most `error_bound`
* away from the actual Fréchet distance between the two polylines. * away from the actual Fréchet distance between the two polylines.
* *
* \tparam Traits a model of `FrechetDistanceTraits` * \tparam PointRange a model of the concept `RandomAccessContainer` whose value type is a `Point_d`.
* \tparam PointRange a model of the concept `RandomAccessContainer` with `Traits::Point_d` as value type.
* \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" * \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
* *
* \param polyline1 the first polyline defined by a sequence of consecutive points * \param polyline1 the first polyline, defined by a sequence of consecutive points
* \param polyline2 the second polyline defined by a sequence of consecutive points * \param polyline2 the second polyline, defined by a sequence of consecutive points
* \param error_bound a maximum bound by which the Fréchet distance estimate is allowed to deviate from the actual Fréchet distance * \param error_bound a maximum bound by which the Fréchet distance estimate is allowed to deviate from the actual Fréchet distance
* \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below: * \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" containing the one listed below:
* *
* \cgalNamedParamsBegin * \cgalNamedParamsBegin
* \cgalParamNBegin{geom_traits} * \cgalParamNBegin{geom_traits}
* \cgalParamDescription{an instance of a geometric traits class} * \cgalParamDescription{an instance of a geometric traits class}
* \cgalParamType{a model of `FrechetDistanceTraits`} * \cgalParamType{a model of `FrechetDistanceTraits`}
* \cgalParamDefault{`Frechet_distance_traits_2`, `Frechet_distance_traits_3`, or`Frechet_distance_traits_d`, depending on the dimension of the point type.} * \cgalParamDefault{`Frechet_distance_traits_2`, `Frechet_distance_traits_3`, or `Frechet_distance_traits_d`, depending on the dimension of the point type
* deduced from the point type, using `Kernel_traits`.}
* \cgalParamExtra{The input point type (the range's value type) must be equal to the traits' `Point_d` type.
* \cgalParamNEnd * \cgalParamNEnd
* \cgalNamedParamsEnd * \cgalNamedParamsEnd
* *
* \pre the polylines must not be empty * \pre the polylines must not be empty
* *
* @return an interval enclosing the exact result, the difference between the upper and * @return an interval enclosing the exact Fréchet distance, the difference between the upper and
* the lower bound being less than `error_bound`. * the lower bound being smaller than `error_bound`.
*/ */
template <class PointRange, class NamedParameters = parameters::Default_named_parameters> template <class PointRange, class NamedParameters = parameters::Default_named_parameters>
std::pair<double,double> bounded_error_Frechet_distance(const PointRange& polyline1, std::pair<double,double> bounded_error_Frechet_distance(const PointRange& polyline1,

View File

@ -28,7 +28,7 @@ namespace CGAL {
namespace Frechet_distance { namespace Frechet_distance {
/*! /*!
* A data structure to store curves with a function that enables to find those curves which are close to a query curve. * A data structure to store curves with a function that enables to find those curves which are closer than a distance bound to a query curve.
* *
* \tparam Traits a model of `FrechetDistanceTraits` * \tparam Traits a model of `FrechetDistanceTraits`
* \tparam PointRange a model of the concept `RandomAccessContainer` with `Traits::Point_d` as value type. * \tparam PointRange a model of the concept `RandomAccessContainer` with `Traits::Point_d` as value type.
@ -45,7 +45,13 @@ class Neighbor_search
using PolylineIDs = std::vector<PolylineID>; using PolylineIDs = std::vector<PolylineID>;
public: public:
#ifndef DOXYGEN_RUNNING
Neighbor_search() = default; Neighbor_search() = default;
#endif
#ifdef DOXYGEN_RUNNING
using Point = Traits::Point_d;
#endif
/*! inserts curves /*! inserts curves
*/ */
@ -72,7 +78,12 @@ void Neighbor_search<PointRange, Traits>::insert(
} }
template <class PointRange, class Traits> template <class PointRange, class Traits>
auto Neighbor_search<PointRange, Traits>::get_close_curves( #ifdef DOXYGEN_RUNNING
std::vector<std::size_t>
#else
auto
#endif
Neighbor_search<PointRange, Traits>::get_close_curves(
const Polyline& curve, double distance) -> PolylineIDs const Polyline& curve, double distance) -> PolylineIDs
{ {
auto result = kd_tree.search(curve, distance); auto result = kd_tree.search(curve, distance);

View File

@ -49,6 +49,10 @@ public:
Construct_cartesian_const_iterator_d construct_cartesian_const_iterator_d_object() const { Construct_cartesian_const_iterator_d construct_cartesian_const_iterator_d_object() const {
return Construct_cartesian_const_iterator_d(); return Construct_cartesian_const_iterator_d();
} }
Compare_squared_distance_d construct_compare_squared_distance_d_object() const {
return Compare_squared_distance_d();
}
}; };
} // end of namespace CGAL } // end of namespace CGAL

View File

@ -49,6 +49,10 @@ public:
Construct_cartesian_const_iterator_d construct_cartesian_const_iterator_d_object() const { Construct_cartesian_const_iterator_d construct_cartesian_const_iterator_d_object() const {
return Construct_cartesian_const_iterator_d(); return Construct_cartesian_const_iterator_d();
} }
Compare_squared_distance_d construct_compare_squared_distance_d_object() const {
return Compare_squared_distance_d();
}
}; };
} // end of namespace CGAL } // end of namespace CGAL

View File

@ -20,7 +20,7 @@ public:
/// @{ /// @{
/*! /*!
introduces an \em empty bounding box with lower left constructs an \em empty bounding box with lower left
corner point at \f$ (\infty, \infty) \f$ corner point at \f$ (\infty, \infty) \f$
and with upper right corner point at and with upper right corner point at
\f$ (-\infty, -\infty) \f$, \f$ \infty \f$ being \f$ (-\infty, -\infty) \f$, \f$ \infty \f$ being
@ -28,7 +28,7 @@ and with upper right corner point at
*/ */
Bbox_2(); Bbox_2();
/*! /*!
introduces a bounding box `b` with lower left corner at constructs a bounding box `b` with lower left corner at
`(xmin, ymin)` and with upper right corner at `(xmin, ymin)` and with upper right corner at
`(xmax, ymax)`. `(xmax, ymax)`.
*/ */

View File

@ -20,7 +20,7 @@ public:
/// @{ /// @{
/*! /*!
introduces an \em empty bounding box with lower left constructs an \em empty bounding box with lower left
corner point at \f$ (\infty, \infty, \infty) \f$ corner point at \f$ (\infty, \infty, \infty) \f$
and with upper right corner point at and with upper right corner point at
\f$ (-\infty, -\infty, -\infty) \f$, \f$ \infty \f$ being \f$ (-\infty, -\infty, -\infty) \f$, \f$ \infty \f$ being
@ -29,7 +29,7 @@ and with upper right corner point at
Bbox_3(); Bbox_3();
/*! /*!
introduces a bounding box `b` with lexicographically constructs a bounding box `b` with lexicographically
smallest corner point at `(xmin, ymin, zmin)` smallest corner point at `(xmin, ymin, zmin)`
and lexicographically largest corner point at and lexicographically largest corner point at
`(xmax, ymax, zmax)`. `(xmax, ymax, zmax)`.

View File

@ -4,8 +4,9 @@ namespace CGAL {
/*! /*!
\ingroup PkgKernelDKernelObjs \ingroup PkgKernelDKernelObjs
An object `b` of the class `Bbox_d` is a bounding An object `b` of the class `Bbox_d` is a bounding box in the d-dimensional Euclidean space \f$ \E^d\f$.
box in the d-dimensional Euclidean plane \f$ \E^d\f$. This class is templated with a dimension tag.
\tparam DimensionTag must be an instance of `CGAL::Dimension_tag`.
\cgalModels{Hashable} \cgalModels{Hashable}
@ -18,11 +19,19 @@ template <typename DimensionTag>
class Bbox_d { class Bbox_d {
public: public:
/// \name Types
/// @{
/// An iterator for enumerating the %Cartesian coordinates of the point with the lexicographically
//// smallest coordinates followed by those of the point with the lexicographically largest coordinates.
typedef unspecified_type Cartesian_const_iterator;
/// @}
/// \name Creation /// \name Creation
/// @{ /// @{
/*! /*!
introduces an \em empty bounding box with lower left constructs an \em empty bounding box with lower left
corner coordinates at \f$ \infty \f$ corner coordinates at \f$ \infty \f$
and with upper right corner coordinates at and with upper right corner coordinates at
\f$ -\infty \f$, \f$ \infty \f$ being \f$ -\infty \f$, \f$ \infty \f$ being
@ -31,21 +40,21 @@ and with upper right corner coordinates at
Bbox_d(); Bbox_d();
/*! /*!
introduces a d-dimensional bounding box from a 2d bounding box. constructs a d-dimensional bounding box from a 2D bounding box.
\pre the dimension must be 2D \pre the dimension must be 2D
*/ */
Bbox_d(const Bbox_2& b); Bbox_d(const Bbox_2& b);
/*! /*!
introduces a d-dimensional bounding box from a range. constructs a d-dimensional bounding box from a range of coordinates
\pre the range must have the size of the dimension. \pre the range must have the size of the dimension.
\tparam I an iterator model of `InputIterator` with value type double \tparam InputIterator an input iterator with value type `double`
*/ */
template <typename I> template <typename InputIterator>
Bbox_d(int d, I b, I e); Bbox_d(int d, InputIterator b, InputIterator e);
/*! /*!
introduces a d-dimensional bounding box from a 3d bounding box. constructs a d-dimensional bounding box from a 3D bounding box.
\pre the dimension must be 3D \pre the dimension must be 3D
*/ */
Bbox_d(const Bbox_3& b); Bbox_d(const Bbox_3& b);
@ -56,7 +65,7 @@ Bbox_d(const Bbox_3& b);
/// @{ /// @{
/*! /*!
ests for equality. tests for equality.
*/ */
bool operator==(const Bbox_d &c) const; bool operator==(const Bbox_d &c) const;
@ -72,15 +81,26 @@ int dimension() const;
/*! /*!
returns an iterator for the %Cartesian coordinates of the lower left and the upper right corner. returns the `i`-th %Cartesian coordinate of the "lower left" corner.
*/
double min(int i) const;
/*!
returns the `i`-th %Cartesian coordinate of the "upper right" corner.
*/
double max(int i) const;
/*!
returns an iterator for the %Cartesian coordinates of the "lower left" and the "upper right" corner.
*/ */
Cartesian_const_iterator cartesian_begin() const; Cartesian_const_iterator cartesian_begin() const;
/*! /*!
returns the past-the-end iterator for the %Cartesian coordinates of the lower left and the upper right corner. returns the past-the-end iterator for the %Cartesian coordinates of the "lower left" and the "upper right" corner.
*/ */
Cartesian_const_iterator cartesian_begin() const; Cartesian_const_iterator cartesian_end() const;
/*! /*!
returns a bounding box of `b` and `c`. returns a bounding box of `b` and `c`.
@ -117,7 +137,7 @@ intersection is non-empty.
\relates Bbox_d \relates Bbox_d
*/ */
template <typename DimensionTag> template <typename DimensionTag>
bool do_overlap(const Bbox_d &bb1, const Bbox_d &bb2); bool do_overlap(const Bbox_d<DimensionTag> &bb1, const Bbox_d<DimensionTag> &bb2);
/// @} /// @}