Trailing whitespace in Spatial searching

This commit is contained in:
Mael Rouxel-Labbé 2017-01-09 17:46:47 +01:00
parent e64f271451
commit fe8f36bcac
9 changed files with 114 additions and 116 deletions

View File

@ -1,7 +1,7 @@
namespace CGAL {
/*!
\ingroup RangeQueryItemClasses
\ingroup RangeQueryItemClasses
The class `Fuzzy_iso_box` implements fuzzy `d`-dimensional iso boxes. A fuzzy iso
box with fuzziness value \f$ \epsilon\f$ has as inner and outer approximations
@ -13,19 +13,19 @@ points may or may not be reported. Subsequently, points on the boundary of the
inner and outer approximations may or may not be reported. Specifically when \f$ \epsilon = 0\f$,
points on the boundary of the box may or may not be reported.
\tparam Traits must be a model of the concept
`SearchTraits`, for example `CGAL::Search_traits_2<CGAL::Simple_cartesian<double> >`.
\tparam Traits must be a model of the concept
`SearchTraits`, for example `CGAL::Search_traits_2<CGAL::Simple_cartesian<double> >`.
\cgalModels `FuzzyQueryItem`
\sa `FuzzyQueryItem`
\sa `FuzzyQueryItem`
*/
template< typename Traits >
class Fuzzy_iso_box {
public:
/// \name Types
/// \name Types
/// @{
/*!
@ -34,18 +34,18 @@ Dimension Tag.
typedef unspecified_type D;
/*!
Point type.
*/
typedef Traits::Point_d Point_d;
Point type.
*/
typedef Traits::Point_d Point_d;
/*!
Number type.
*/
typedef Traits::FT FT;
Number type.
*/
typedef Traits::FT FT;
/// @}
/// @}
/// \name Creation
/// \name Creation
/// @{
/*!
@ -62,13 +62,13 @@ Construct a fuzzy iso box specified by the minimal iso box containing `p` and `q
\attention Only available in case `Traits` is
`Search_traits_adapter<Key,PointPropertyMap,BaseTraits>`.
\pre `p` must be lexicographically smaller than `q`.
*/
Fuzzy_iso_box(Traits::Base::Point_d p, Traits::Base::Point_d q, FT epsilon=FT(0), Traits t=Traits());
\pre `p` must be lexicographically smaller than `q`.
*/
Fuzzy_iso_box(Traits::Base::Point_d p, Traits::Base::Point_d q, FT epsilon=FT(0), Traits t=Traits());
/// @}
/// @}
/// \name Operations
/// \name Operations
/// @{
/*!

View File

@ -22,14 +22,14 @@ of radius \f$ r\f$ may or may not be reported.
\cgalModels `FuzzyQueryItem`
\sa `FuzzyQueryItem`
\sa `FuzzyQueryItem`
*/
template< typename Traits >
class Fuzzy_sphere {
public:
/// \name Types
/// \name Types
/// @{
/*!
@ -38,19 +38,19 @@ Dimension Tag.
typedef unspecified_type D;
/*!
Point type.
*/
typedef Traits::Point_d Point_d;
Point type.
*/
typedef Traits::Point_d Point_d;
/*!
Number type.
*/
typedef Traits::FT FT;
Number type.
*/
typedef Traits::FT FT;
/// @}
/// @}
/// \name Creation
///
/// \name Creation
///
/// @{
/*!
@ -62,12 +62,12 @@ Fuzzy_sphere(Point_d center, FT radius, FT epsilon=FT(0),Traits t=Traits());
/*!
Construct a fuzzy sphere centered at `center` with radius `radius` and fuzziness value `epsilon`.
\attention Only available in case `Traits` is `Search_traits_adapter<Key,PointPropertyMap,BaseTraits>`.
*/
Fuzzy_sphere(Traits::Base::Point_d center, FT radius, FT epsilon=FT(0), Traits t=Traits());
*/
Fuzzy_sphere(Traits::Base::Point_d center, FT radius, FT epsilon=FT(0), Traits t=Traits());
/// @}
/// @}
/// \name Operations
/// \name Operations
/// @{
/*!

View File

@ -2,7 +2,7 @@
namespace CGAL {
/*!
\mainpage User Manual
\mainpage User Manual
\anchor Chapter_dD_Spatial_Searching
\anchor ChapterUserSpatialSearching
\cgalAutoToc
@ -92,14 +92,14 @@ neighbor must not be smaller than \f$ r/(1+\epsilon)\f$. Obviously, for
the less exact the result.
While searching the nearest neighbor the algorithm descends the kd-tree
and has to decide two things for each node : Which child node should be visited
first and could there be possible nearest neighbors in the other child. This
and has to decide two things for each node : Which child node should be visited
first and could there be possible nearest neighbors in the other child. This
basically comes down to computing the distance to the further child, because the
distance to the closer child is the same as the one to the parent. There are
distance to the closer child is the same as the one to the parent. There are
two options now:<br>
-# In general, we compute the distance with the given metric. This is the
<I>k-neighbor search</I> with a <I>general distance</I> class.
-# For point queries we can "update" the distance, because it is only
-# For point queries we can "update" the distance, because it is only
changed in one dimension at a time. This is the <I>orthogonal k-neighbor search</I>
with an <I>orthogonal distance</I> class.
The following example shows the orthogonal distance computation in detail:
@ -110,15 +110,15 @@ Orthogonal distance computation technique
Assume we are searching the nearest neighbor, descending the kd-tree, with \f$ R_{p} \f$
as the parent rectangle and \f$ R_{lo} \f$ and \f$ R_{hi}\f$ as its childs in the current step.
Further assume \f$ R_{lo} \f$ is closer to query point \f$q\f$. Let \f$cd\f$ denote the cutting dimension and let
Further assume \f$ R_{lo} \f$ is closer to query point \f$q\f$. Let \f$cd\f$ denote the cutting dimension and let
\f$cv\f$ denote the cutting value. At this point we already know the distance \f$rd_{p}\f$
to the parent rectangle and need to check if \f$R_{hi}\f$ could contain
to the parent rectangle and need to check if \f$R_{hi}\f$ could contain
nearest neighbors. Because \f$R_{lo}\f$ is the closer rectangle, its distance
to \f$q\f$, \f$rd_{lo}\f$, is the same as \f$rd_{p}\f$.
Notice that for each dimension \f$i \neq cd \f$, \f$ \mathrm{dists}_{lo}[i] = \mathrm{dists}_{hi}[i]\f$,
since these coordinates are not affected by the current cut. So the new distance along the
to \f$q\f$, \f$rd_{lo}\f$, is the same as \f$rd_{p}\f$.
Notice that for each dimension \f$i \neq cd \f$, \f$ \mathrm{dists}_{lo}[i] = \mathrm{dists}_{hi}[i]\f$,
since these coordinates are not affected by the current cut. So the new distance along the
cutting dimension is \f$ \mathrm{dists}_{hi}[cd] = cv - q[cd]\f$. Now we can compute \f$rd_{hi}\f$
in constant time (independent of dimension) with
in constant time (independent of dimension) with
\f$rd_{hi} = rd_{p} - \mathrm{dists}_{lo}[cd]^2 + (cv - q[cd])^2\f$.<br>
This strategy can be used if and only if the distance changes only in one dimension at a time,
which is the case for point queries.
@ -126,25 +126,25 @@ which is the case for point queries.
The following two classes implement the standard
search strategy for orthogonal distances like the weighted Minkowski
distance. The second one is a specialization for incremental neighbor
distance. The second one is a specialization for incremental neighbor
searching and distance browsing. Both require extendes nodes.
`Orthogonal_k_neighbor_search<Traits,
OrthogonalDistance, Splitter, SpatialTree>`
OrthogonalDistance, Splitter, SpatialTree>`
`Orthogonal_incremental_neighbor_search<Traits,
OrthogonalDistance, Splitter, SpatialTree>`
OrthogonalDistance, Splitter, SpatialTree>`
The other two classes implement the standard search strategy for
general distances like the Manhattan distance for iso-rectangle queries.
Again, the second one is a specialization for incremental neighbor
Again, the second one is a specialization for incremental neighbor
searching and distance browsing .
`K_neighbor_search<Traits, GeneralDistance,
Splitter, SpatialTree>`
Splitter, SpatialTree>`
`Incremental_neighbor_search<Traits,
GeneralDistance, Splitter, SpatialTree>`
GeneralDistance, Splitter, SpatialTree>`
\subsection Spatial_searchingRangeSearching Range Searching
@ -165,13 +165,13 @@ For range searching of large data sets, the user may set the parameter `bucket_s
used in building the `kd` tree to a large value (e.g. 100),
because in general the query time will be less than using the default value.
\section Spatial_SearchingSplitting_rule_section Splitting Rules
\section Spatial_SearchingSplitting_rule_section Splitting Rules
Instead of using the default splitting rule `Sliding_midpoint` described below,
a user may, depending upon the data, select
a user may, depending upon the data, select
one from the following splitting rules,
which determine how a separating hyperplane is computed. Every splitter has
degenerated worst cases, which may lead to a linear tree and a stack overflow.
which determine how a separating hyperplane is computed. Every splitter has
degenerated worst cases, which may lead to a linear tree and a stack overflow.
Switching the splitting rule to one of a different kind will solve the problem.
<DL>
@ -219,7 +219,7 @@ along this dimension.
</DL>
The tree can become linear for the median rules, if many points are collinear in a dimension
The tree can become linear for the median rules, if many points are collinear in a dimension
which is not the cutting dimension.
\cgalFigureBegin{Spatial_searchingmedianworstcase, Median_worst_case.jpg}
Median worst case point set in 2d.\n
@ -266,7 +266,7 @@ generate empty cells.
\section Spatial_searchingExample Example Programs
We give seven examples. The first example illustrates k nearest neighbor
searching, and the second example incremental neighbor searching.
searching, and the second example incremental neighbor searching.
The third is an example of approximate furthest neighbor searching
using a `d`-dimensional iso-rectangle as an query object. Approximate
range searching is illustrated by the fourth example. The fifth
@ -280,10 +280,10 @@ scenarios for different splitter types.
The first example illustrates k neighbor searching with an Euclidean
distance and 2-dimensional points. The generated random
data points are inserted in a search tree. We then initialize
the k neighbor search object with the origin as query. Finally, we
the k neighbor search object with the origin as query. Finally, we
obtain the result of the computation in the form of an iterator
range. The value of the iterator is a pair of a point and its square
distance to the query point. We use square distances, or <I>transformed distances</I> for other distance classes, as they are
distance to the query point. We use square distances, or <I>transformed distances</I> for other distance classes, as they are
computationally cheaper.
\cgalExample{Spatial_searching/nearest_neighbor_searching.cpp}
@ -308,7 +308,7 @@ This example program illustrates approximate nearest and furthest
neighbor searching using 4-dimensional %Cartesian coordinates. Five
approximate furthest neighbors of the query rectangle
\f$ [0.1,0.2]^4\f$ are computed. Because the query object is a rectangle
we cannot use the orthogonal neighbor search. As in the previous
we cannot use the orthogonal neighbor search. As in the previous
examples we first initialize a search tree, create the search object
with the query, and obtain the result of the search as iterator range.
@ -327,18 +327,18 @@ The range queries are member functions of the `kd` tree class.
The neighbor searching works with all \cgal kernels, as well as with
user defined points and distance classes.
In this example we assume that the user provides the following 3-dimensional
In this example we assume that the user provides the following 3-dimensional
points class.
\cgalExample{Spatial_searching/Point.h}
We have put the glue layer in this file as well, that is a class that allows to
We have put the glue layer in this file as well, that is a class that allows to
iterate over the %Cartesian coordinates of the point, and a class to construct
such an iterator for a point. We next need a distance class
\cgalExample{Spatial_searching/Distance.h}
We are ready to put the pieces together.
The class `Search_traits<..>` ,which you see in the next file, is a mere
The class `Search_traits<..>` ,which you see in the next file, is a mere
wrapper for all our defined types. The searching itself works exactly as for \cgal kernels.
\cgalExample{Spatial_searching/user_defined_point_and_distance.cpp}
@ -373,7 +373,7 @@ Points are read from a `std::map`. The search tree stores integers of type `std:
\subsubsection Spatial_searchingUsingSurfaceMesh Using a Point Property Map of a Polygonal Mesh
This example programs shows how to search the closest vertices of a `Surface_mesh` or, quite similar, of a
This example programs shows how to search the closest vertices of a `Surface_mesh` or, quite similar, of a
`Polyhedron_3`.
Points are stored in the polygonal mesh. The search tree stores vertex descriptors.
The value type of the iterator of the neighbor searching algorithm is \link BGLSMGT `boost::graph_traits<Surface_mesh>::vertex_descriptor` \endlink.
@ -386,19 +386,19 @@ The value type of the iterator of the neighbor searching algorithm is \link BGL
This example program illustrates selecting a splitting rule and
setting the maximal allowed bucket size. The only differences with
the first example are the declaration of the <I>Fair</I>
the first example are the declaration of the <I>Fair</I>
splitting rule, needed to set the maximal allowed bucket size.
\cgalExample{Spatial_searching/using_fair_splitting_rule.cpp}
\subsection Spatial_searchingExampleforWorstCaseScenarios Example for Worst-Case Scenarios for Different Splitters
This example program has two 2-dimensional data sets: The first one containing
This example program has two 2-dimensional data sets: The first one containing
collinear points with exponential increasing distances and the second
one with collinear points in the firstdimension and one point with a distance
exceeding the spread of the other points in the second dimension. These are
the worst cases for the midpoint/median rules and can also occur in
higher dimensions.
exceeding the spread of the other points in the second dimension. These are
the worst cases for the midpoint/median rules and can also occur in
higher dimensions.
\cgalExample{Spatial_searching/splitter_worst_cases.cpp}
@ -406,11 +406,11 @@ higher dimensions.
\subsection OrthogonalPerfomance Performance of the Orthogonal Search
We took the gargoyle data set (Surface) from aim\@shape, and generated the same number of random points in the bbox of the gargoyle (Random).
We took the gargoyle data set (Surface) from aim\@shape, and generated the same number of random points in the bbox of the gargoyle (Random).
We then consider three scenarios as data/queries.
The data set contains 800K points. For each query point we compute the K=10,20,30 closest points, with the default splitter and for the bucket size 10 (default) and 20.
The data set contains 800K points. For each query point we compute the K=10,20,30 closest points, with the default splitter and for the bucket size 10 (default) and 20.
The results were produced with the release 4.6 of \cgal, on an Intel i7 2.7 Ghz
The results were produced with the release 4.6 of \cgal, on an Intel i7 2.7 Ghz
laptop with 16 GB RAM, compiled with Visual C++ 2012 with the /O2 option.
The values are the average of ten tests each.
@ -419,12 +419,12 @@ The values are the average of ten tests each.
<center>
k | bucket size | Surface/Surface | Surface/Random | Random/Random
--|------------:|-----------------:|---------------:|----------------:
10| 10 | 0.89 | 11.48 | 2.63
10| 20 | 0.89 | 9.80 | 2.25
20| 10 | 1.60 | 13.41 | 4.06
20| 20 | 1.59 | 11.62 | 3.46
30| 10 | 2.35 | 15.52 | 5.42
30| 20 | 2.33 | 13.50 | 4.61
10| 10 | 0.89 | 11.48 | 2.63
10| 20 | 0.89 | 9.80 | 2.25
20| 10 | 1.60 | 13.41 | 4.06
20| 20 | 1.59 | 11.62 | 3.46
30| 10 | 2.35 | 15.52 | 5.42
30| 20 | 2.33 | 13.50 | 4.61
</center>
\cgalFigureBegin{Spatial_searchingfigbenchmark,gargoyle.png}
@ -434,7 +434,7 @@ Blue: Gargoyle surface. Green: Gargoyle bbox random.
\section Spatial_searchingSoftware Software Design
\subsection Kd_tree_subsection The kd Tree
\subsection Kd_tree_subsection The kd Tree
Bentley \cgalCite{b-mbstu-75} introduced the `kd` tree as a
generalization of the binary search tree in higher dimensions. `kd`
@ -504,6 +504,6 @@ The initial implementation of this package was done by Hans Tangelder and
Andreas Fabri. It was optimized in speed and memory consumption by Markus
Overtheil during an internship at GeometryFactory in 2014.
*/
*/
} /* namespace CGAL */

View File

@ -14,7 +14,7 @@
//
// $URL$
// $Id$
//
//
//
// Author(s) : Hans Tangelder (<hanst@cs.uu.nl>)

View File

@ -14,7 +14,7 @@
//
// $URL$
// $Id$
//
//
//
// Author(s) : Hans Tangelder (<hanst@cs.uu.nl>)

View File

@ -1,7 +1,7 @@
// file : test/Spatial_searching/Circular_query.C
// test whether circular queries are computed correctly for random data
//
// 1) generate list of query points using report_all
//
// 1) generate list of query points using report_all
// 2) remove and check reported points from these list
// 3) check if no remaining points should have been reported
@ -26,12 +26,11 @@ typedef Point_with_info_helper<Point>::type
typedef Point_property_map<Point> Ppmap;
typedef CGAL::Search_traits_adapter<Point_with_info,Ppmap,Traits> Traits_with_info;
template <class Traits>
void run(std::list<Point> all_points){
typedef CGAL::Fuzzy_sphere<Traits> Fuzzy_circle;
typedef CGAL::Kd_tree<Traits> Tree;
typedef CGAL::Kd_tree<Traits> Tree;
// Insert also the N points in the tree
Tree tree(
boost::make_transform_iterator(all_points.begin(),Create_point_with_info<typename Traits::Point_d>()),
@ -41,7 +40,7 @@ void run(std::list<Point> all_points){
// define exact circular range query (fuzziness=0)
Point center(0.25, 0.25);
Fuzzy_circle exact_range(typename Traits::Point_d(center), 0.25);
std::list<typename Traits::Point_d> result;
tree.search(std::back_inserter( result ), exact_range);
@ -80,7 +79,7 @@ void run(std::list<Point> all_points){
assert(CGAL::squared_distance(center,get_point(*pt))<=0.140625); // (0.25 + 0.125)²
all_points.remove(get_point(*pt));
}
for (std::list<Point>::iterator pt=all_points.begin(); (pt != all_points.end()); ++pt) {
// all points with a distance d < r - eps must be reported
if(CGAL::squared_distance(center, *pt) < 0.015625){ // (0.25 - 0.125)²
@ -88,23 +87,22 @@ void run(std::list<Point> all_points){
}
assert(CGAL::squared_distance(center,*pt) >= 0.015625);
}
std::cout << "done" << std::endl;
std::cout << "done" << std::endl;
}
int main() {
const int N=1000;
// generator for random data points in the square ( (-1,-1), (1,1) )
Random_points_iterator rpit( 1.0);
// generator for random data points in the square ( (-1,-1), (1,1) )
Random_points_iterator rpit(1.0);
// construct list containing N random points
std::list<Point> all_points(N_Random_points_iterator(rpit,0),
N_Random_points_iterator(N));
N_Random_points_iterator(N));
run<Traits>(all_points);
run<Traits_with_info>(all_points);
return 0;
}

View File

@ -28,13 +28,13 @@ template <class SearchTraits>
void run(std::list<Point> all_points)
{
typedef CGAL::Fuzzy_iso_box<SearchTraits> Fuzzy_box;
// Insert also the N points in the tree
CGAL::Kd_tree<SearchTraits> tree(
boost::make_transform_iterator(all_points.begin(),Create_point_with_info<typename SearchTraits::Point_d>()),
boost::make_transform_iterator(all_points.end(),Create_point_with_info<typename SearchTraits::Point_d>())
);
Point p(0.1, 0.2);
Point q(0.3, 0.5);
typename SearchTraits::Point_d pp(p);
@ -57,7 +57,7 @@ void run(std::list<Point> all_points)
assert(! ic.has_on_unbounded_side(get_point(*pt)) || ic.has_on_boundary(get_point(*pt)));
copy_all_points.remove(get_point(*pt));
}
for (std::list<Point>::iterator pt=copy_all_points.begin(); (pt != copy_all_points.end()); ++pt) {
assert(ic.has_on_unbounded_side(*pt) || ic.has_on_boundary(*pt));
}
@ -76,27 +76,27 @@ void run(std::list<Point> all_points)
assert(! outer_ic.has_on_unbounded_side(get_point(*pt)) || outer_ic.has_on_boundary(get_point(*pt)));
all_points.remove(get_point(*pt));
}
for (std::list<Point>::iterator pt=all_points.begin(); (pt != all_points.end()); ++pt) {
assert(inner_ic.has_on_unbounded_side(*pt) || inner_ic.has_on_boundary(*pt));
}
std::cout << "done" << std::endl;
std::cout << "done" << std::endl;
}
int main() {
const int N=10000;
// generator for random data points in the square ( (-1,-1), (1,1) )
// generator for random data points in the square ( (-1,-1), (1,1) )
Random_points_iterator rpit( 1.0);
// construct list containing N random points
std::list<Point> all_points(N_Random_points_iterator(rpit,0),
N_Random_points_iterator(N));
N_Random_points_iterator(N));
run<Traits>(all_points);
run<Traits_with_info>(all_points);
return 0;
}

View File

@ -28,16 +28,16 @@ template <class SearchTraits>
void run(std::list<Point> all_points)
{
typedef CGAL::Fuzzy_iso_box<SearchTraits> Fuzzy_box;
// Insert also the N points in the tree
CGAL::Kd_tree<SearchTraits> tree(
boost::make_transform_iterator(all_points.begin(),Create_point_with_info<typename SearchTraits::Point_d>()),
boost::make_transform_iterator(all_points.end(),Create_point_with_info<typename SearchTraits::Point_d>())
);
Point p(0.1, 0.2, 0.3);
Point q(0.3, 0.5, 0.4);
typename SearchTraits::Point_d pp(p);
typename SearchTraits::Point_d qq(q);
@ -75,24 +75,24 @@ void run(std::list<Point> all_points)
assert(! outer_ic.has_on_unbounded_side(get_point(*pt)));
all_points.remove(get_point(*pt));
}
for (std::list<Point>::iterator pt=all_points.begin(); (pt != all_points.end()); ++pt) {
assert(inner_ic.has_on_unbounded_side(*pt));
}
std::cout << "done" << std::endl;
std::cout << "done" << std::endl;
}
int main() {
// generator for random data points in the square ( (-1,-1), (1,1) )
// generator for random data points in the square ( (-1,-1), (1,1) )
Random_points_iterator rpit( 1.0);
// construct list containing N random points
std::list<Point> all_points(N_Random_points_iterator(rpit,0),
N_Random_points_iterator(N));
N_Random_points_iterator(N));
run<Traits>(all_points);
run<Traits_with_info>(all_points);
return 0;
}

View File

@ -63,7 +63,7 @@ main() {
Fuzzy_iso_box approximate_range(p, q, 0.1);
tree.search(std::back_inserter( result ), approximate_range);
std::cout << "The points in the fuzzy box [<0.1-0.3>,<0.6-0.9>]x[<0.1-0.3>,<0.6-0.9>] are: "
<< std::endl;
<< std::endl;
std::copy (result.begin(), result.end(), std::ostream_iterator<Point_d>(std::cout,"\n") );
std::cout << std::endl;
return 0;