diff options
Diffstat (limited to 'src/Spatial_searching')
-rw-r--r-- | src/Spatial_searching/doc/Intro_spatial_searching.h | 4 | ||||
-rw-r--r-- | src/Spatial_searching/example/CMakeLists.txt | 14 | ||||
-rw-r--r-- | src/Spatial_searching/example/example_spatial_searching.cpp | 34 | ||||
-rw-r--r-- | src/Spatial_searching/include/gudhi/Kd_tree_search.h | 88 | ||||
-rw-r--r-- | src/Spatial_searching/test/CMakeLists.txt | 15 | ||||
-rw-r--r-- | src/Spatial_searching/test/test_Kd_tree_search.cpp | 56 |
6 files changed, 92 insertions, 119 deletions
diff --git a/src/Spatial_searching/doc/Intro_spatial_searching.h b/src/Spatial_searching/doc/Intro_spatial_searching.h index 2406c931..23705378 100644 --- a/src/Spatial_searching/doc/Intro_spatial_searching.h +++ b/src/Spatial_searching/doc/Intro_spatial_searching.h @@ -39,6 +39,10 @@ namespace spatial_searching { * <a target="_blank" href="http://doc.cgal.org/latest/Spatial_searching/index.html">CGAL dD spatial searching algorithms</a>. * It provides a simplified API to perform (approximate) neighbor searches. Contrary to CGAL default behavior, the tree * does not store the points themselves, but stores indices. + * + * For more details about the data structure or the algorithms, or for more advanced usages, reading + * <a target="_blank" href="http://doc.cgal.org/latest/Spatial_searching/index.html">CGAL documentation</a> + * is highly recommended. * * \section spatial_searching_examples Example * diff --git a/src/Spatial_searching/example/CMakeLists.txt b/src/Spatial_searching/example/CMakeLists.txt index 3c3970d8..e73b201c 100644 --- a/src/Spatial_searching/example/CMakeLists.txt +++ b/src/Spatial_searching/example/CMakeLists.txt @@ -2,18 +2,12 @@ cmake_minimum_required(VERSION 2.6) project(Spatial_searching_examples) if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.8.1) - message(STATUS "CGAL version: ${CGAL_VERSION}.") - + if (NOT CGAL_VERSION VERSION_LESS 4.9.0) if (EIGEN3_FOUND) add_executable( Spatial_searching_example_spatial_searching example_spatial_searching.cpp ) target_link_libraries(Spatial_searching_example_spatial_searching ${CGAL_LIBRARY}) - else() - message(WARNING "Eigen3 not found. Version 3.1.0 is required for the Tangential_complex examples.") + add_test(Spatial_searching_example_spatial_searching + ${CMAKE_CURRENT_BINARY_DIR}/Spatial_searching_example_spatial_searching) endif() - else() - message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Spatial_searching examples. Version 4.8.1 is required.") - endif () -else() - message(WARNING "CGAL not found. It is required for the Spatial_searching examples.") + endif() endif() diff --git a/src/Spatial_searching/example/example_spatial_searching.cpp b/src/Spatial_searching/example/example_spatial_searching.cpp index 7b48d055..14b324ae 100644 --- a/src/Spatial_searching/example/example_spatial_searching.cpp +++ b/src/Spatial_searching/example/example_spatial_searching.cpp @@ -7,12 +7,10 @@ namespace gss = Gudhi::spatial_searching; -int main (void) -{ - typedef CGAL::Epick_d<CGAL::Dimension_tag<4> > K; - typedef typename K::FT FT; - typedef typename K::Point_d Point; - typedef std::vector<Point> Points; +int main(void) { + typedef CGAL::Epick_d<CGAL::Dimension_tag<4> > K; + typedef typename K::Point_d Point; + typedef std::vector<Point> Points; typedef gss::Kd_tree_search<K, Points> Points_ds; @@ -20,35 +18,35 @@ int main (void) Points points; for (int i = 0; i < 500; ++i) - points.push_back(Point(rd.get_double(-1.,1), rd.get_double(-1.,1), rd.get_double(-1.,1), rd.get_double(-1.,1))); + points.push_back(Point(rd.get_double(-1., 1), rd.get_double(-1., 1), rd.get_double(-1., 1), rd.get_double(-1., 1))); Points_ds points_ds(points); // 10-nearest neighbor query std::cout << "10 nearest neighbors from points[20]:\n"; - auto kns_range = points_ds.query_k_nearest_neighbors(points[20], 10, true); - for (auto const& nghb : kns_range) + auto knn_range = points_ds.query_k_nearest_neighbors(points[20], 10, true); + for (auto const& nghb : knn_range) std::cout << nghb.first << " (sq. dist. = " << nghb.second << ")\n"; // Incremental nearest neighbor query std::cout << "Incremental nearest neighbors:\n"; - auto ins_range = points_ds.query_incremental_nearest_neighbors(points[45]); - // Get all the neighbors that are closer than 0.5 - for (auto ins_iterator = ins_range.begin(); ins_iterator->second < 0.5*0.5 ; ++ins_iterator) + auto inn_range = points_ds.query_incremental_nearest_neighbors(points[45]); + // Get the neighbors in distance order until we hit the first point + for (auto ins_iterator = inn_range.begin(); ins_iterator->first != 0; ++ins_iterator) std::cout << ins_iterator->first << " (sq. dist. = " << ins_iterator->second << ")\n"; // 10-farthest neighbor query std::cout << "10 farthest neighbors from points[20]:\n"; - auto kfs_range = points_ds.query_k_farthest_neighbors(points[20], 10, true); - for (auto const& nghb : kfs_range) + auto kfn_range = points_ds.query_k_farthest_neighbors(points[20], 10, true); + for (auto const& nghb : kfn_range) std::cout << nghb.first << " (sq. dist. = " << nghb.second << ")\n"; // Incremental farthest neighbor query std::cout << "Incremental farthest neighbors:\n"; - auto ifs_range = points_ds.query_incremental_farthest_neighbors(points[45]); - // Get all the neighbors that are farthest than 2.3 - for (auto ifs_iterator = ifs_range.begin(); ifs_iterator->second > 2.3*2.3 ; ++ifs_iterator) + auto ifn_range = points_ds.query_incremental_farthest_neighbors(points[45]); + // Get the neighbors in distance reverse order until we hit the first point + for (auto ifs_iterator = ifn_range.begin(); ifs_iterator->first != 0; ++ifs_iterator) std::cout << ifs_iterator->first << " (sq. dist. = " << ifs_iterator->second << ")\n"; - + return 0; } diff --git a/src/Spatial_searching/include/gudhi/Kd_tree_search.h b/src/Spatial_searching/include/gudhi/Kd_tree_search.h index ff630e9d..6728d56e 100644 --- a/src/Spatial_searching/include/gudhi/Kd_tree_search.h +++ b/src/Spatial_searching/include/gudhi/Kd_tree_search.h @@ -20,8 +20,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef GUDHI_SPATIAL_TREE_DS_H_ -#define GUDHI_SPATIAL_TREE_DS_H_ +#ifndef KD_TREE_SEARCH_H_ +#define KD_TREE_SEARCH_H_ #include <CGAL/Orthogonal_k_neighbor_search.h> #include <CGAL/Orthogonal_incremental_neighbor_search.h> @@ -41,22 +41,22 @@ namespace spatial_searching { /** * \class Kd_tree_search Kd_tree_search.h gudhi/Kd_tree_search.h - * \brief Spatial tree data structure to perform (approximate) nearest neighbor search. + * \brief Spatial tree data structure to perform (approximate) nearest and farthest neighbor search. * * \ingroup spatial_searching * * \details * The class Kd_tree_search is a tree-based data structure, based on * <a target="_blank" href="http://doc.cgal.org/latest/Spatial_searching/index.html">CGAL dD spatial searching data structures</a>. - * It provides a simplified API to perform (approximate) nearest neighbor searches. Contrary to CGAL default behavior, the tree + * It provides a simplified API to perform (approximate) nearest and farthest neighbor searches. Contrary to CGAL default behavior, the tree * does not store the points themselves, but stores indices. * - * There are two types of queries: the <i>k-nearest neighbor query</i>, where <i>k</i> is fixed and the <i>k</i> nearest points are - * computed right away, - * and the <i>incremental nearest neighbor query</i>, where no number of neighbors is provided during the call, as the + * There are two types of queries: the <i>k-nearest or k-farthest neighbor query</i>, where <i>k</i> is fixed and the <i>k</i> nearest + * or farthest points are computed right away, + * and the <i>incremental nearest or farthest neighbor query</i>, where no number of neighbors is provided during the call, as the * neighbors will be computed incrementally when the iterator on the range is incremented. * - * \tparam K must be a model of the <a target="_blank" + * \tparam Search_traits must be a model of the <a target="_blank" * href="http://doc.cgal.org/latest/Spatial_searching/classSearchTraits.html">SearchTraits</a> * concept, such as the <a target="_blank" * href="http://doc.cgal.org/latest/Kernel_d/classCGAL_1_1Epick__d.html">CGAL::Epick_d</a> class, which @@ -64,35 +64,34 @@ namespace spatial_searching { * \tparam Point_range is the type of the range that provides the points. * It must be a range whose iterator type is a `RandomAccessIterator`. */ -template <typename K, typename Point_range> -class Kd_tree_search -{ +template <typename Search_traits, typename Point_range> +class Kd_tree_search { typedef boost::iterator_property_map< typename Point_range::const_iterator, CGAL::Identity_property_map<std::ptrdiff_t> > Point_property_map; -public: - /// The kernel. - typedef K Kernel; + public: + /// The Traits. + typedef Search_traits Traits; /// Number type used for distances. - typedef typename Kernel::FT FT; + typedef typename Traits::FT FT; /// The point type. typedef typename Point_range::value_type Point; typedef CGAL::Search_traits< FT, Point, - typename Kernel::Cartesian_const_iterator_d, - typename Kernel::Construct_cartesian_const_iterator_d> Traits_base; - + typename Traits::Cartesian_const_iterator_d, + typename Traits::Construct_cartesian_const_iterator_d> Traits_base; + typedef CGAL::Search_traits_adapter< std::ptrdiff_t, Point_property_map, Traits_base> STraits; - + typedef CGAL::Orthogonal_k_neighbor_search<STraits> K_neighbor_search; typedef typename K_neighbor_search::Tree Tree; typedef typename K_neighbor_search::Distance Distance; - /// \brief The range returned by a k-nearest neighbor search. + /// \brief The range returned by a k-nearest or k-farthest neighbor search. /// Its value type is `std::pair<std::size_t, FT>` where `first` is the index /// of a point P and `second` is the squared distance between P and the query point. typedef K_neighbor_search KNS_range; @@ -100,7 +99,7 @@ public: typedef CGAL::Orthogonal_incremental_neighbor_search< STraits, Distance, CGAL::Sliding_midpoint<STraits>, Tree> Incremental_neighbor_search; - /// \brief The range returned by an incremental nearest neighbor search. + /// \brief The range returned by an incremental nearest or farthest neighbor search. /// Its value type is `std::pair<std::size_t, FT>` where `first` is the index /// of a point P and `second` is the squared distance between P and the query point. typedef Incremental_neighbor_search INS_range; @@ -113,8 +112,7 @@ public: m_tree(boost::counting_iterator<std::ptrdiff_t>(0), boost::counting_iterator<std::ptrdiff_t>(points.size()), typename Tree::Splitter(), - STraits(std::begin(points)) ) - { + STraits(std::begin(points))) { // Build the tree now (we don't want to wait for the first query) m_tree.build(); } @@ -132,8 +130,7 @@ public: m_tree( only_these_points.begin(), only_these_points.end(), typename Tree::Splitter(), - STraits(std::begin(points))) - { + STraits(std::begin(points))) { // Build the tree now (we don't want to wait for the first query) m_tree.build(); } @@ -151,16 +148,14 @@ public: boost::counting_iterator<std::ptrdiff_t>(begin_idx), boost::counting_iterator<std::ptrdiff_t>(past_the_end_idx), typename Tree::Splitter(), - STraits(std::begin(points)) ) - { + STraits(std::begin(points))) { // Build the tree now (we don't want to wait for the first query) m_tree.build(); } // Be careful, this function invalidates the tree, // which will be recomputed at the next query - void insert(std::ptrdiff_t point_idx) - { + void insert(std::ptrdiff_t point_idx) { m_tree.insert(point_idx); } @@ -174,8 +169,7 @@ public: Point &p, unsigned int k, bool sorted = true, - FT eps = FT(0)) const - { + FT eps = FT(0)) const { // Initialize the search structure, and search all N points // Note that we need to pass the Distance explicitly since it needs to // know the property map @@ -185,9 +179,8 @@ public: k, eps, true, - CGAL::Distance_adapter<std::ptrdiff_t,Point_property_map,CGAL::Euclidean_distance<Traits_base> >( - std::begin(m_points)), - sorted); + CGAL::Distance_adapter<std::ptrdiff_t, Point_property_map, CGAL::Euclidean_distance<Traits_base> >( + std::begin(m_points)), sorted); return search; } @@ -195,11 +188,10 @@ public: /// \brief Search incrementally for the nearest neighbors from a query point. /// @param[in] p The query point. /// @param[in] eps Approximation factor. - /// @return A range containing the neighbors sorted by their distance to p. + /// @return A range containing the neighbors sorted by their distance to p. /// All the neighbors are not computed by this function, but they will be /// computed incrementally when the iterator on the range is incremented. - INS_range query_incremental_nearest_neighbors(const Point &p, FT eps = FT(0)) const - { + INS_range query_incremental_nearest_neighbors(const Point &p, FT eps = FT(0)) const { // Initialize the search structure, and search all N points // Note that we need to pass the Distance explicitly since it needs to // know the property map @@ -224,8 +216,7 @@ public: Point &p, unsigned int k, bool sorted = true, - FT eps = FT(0)) const - { + FT eps = FT(0)) const { // Initialize the search structure, and search all N points // Note that we need to pass the Distance explicitly since it needs to // know the property map @@ -235,9 +226,8 @@ public: k, eps, false, - CGAL::Distance_adapter<std::ptrdiff_t,Point_property_map,CGAL::Euclidean_distance<Traits_base> >( - std::begin(m_points)), - sorted); + CGAL::Distance_adapter<std::ptrdiff_t, Point_property_map, CGAL::Euclidean_distance<Traits_base> >( + std::begin(m_points)), sorted); return search; } @@ -245,11 +235,10 @@ public: /// \brief Search incrementally for the farthest neighbors from a query point. /// @param[in] p The query point. /// @param[in] eps Approximation factor. - /// @return A range containing the neighbors sorted by their distance to p. + /// @return A range containing the neighbors sorted by their distance to p. /// All the neighbors are not computed by this function, but they will be /// computed incrementally when the iterator on the range is incremented. - INS_range query_incremental_farthest_neighbors(const Point &p, FT eps = FT(0)) const - { + INS_range query_incremental_farthest_neighbors(const Point &p, FT eps = FT(0)) const { // Initialize the search structure, and search all N points // Note that we need to pass the Distance explicitly since it needs to // know the property map @@ -264,13 +253,12 @@ public: return search; } - -private: + private: Point_range const& m_points; Tree m_tree; }; -} // namespace spatial_searching -} // namespace Gudhi +} // namespace spatial_searching +} // namespace Gudhi -#endif // GUDHI_SPATIAL_TREE_DS_H_ +#endif // KD_TREE_SEARCH_H_ diff --git a/src/Spatial_searching/test/CMakeLists.txt b/src/Spatial_searching/test/CMakeLists.txt index 0f2c5ae4..7f443b79 100644 --- a/src/Spatial_searching/test/CMakeLists.txt +++ b/src/Spatial_searching/test/CMakeLists.txt @@ -11,20 +11,15 @@ if (GPROF_PATH) endif() if(CGAL_FOUND) - if (NOT CGAL_VERSION VERSION_LESS 4.8.1) - message(STATUS "CGAL version: ${CGAL_VERSION}.") - + if (NOT CGAL_VERSION VERSION_LESS 4.9.0) if (EIGEN3_FOUND) - add_executable( Spatial_searching_test_Kd_tree_search test_Kd_tree_search.cpp ) target_link_libraries(Spatial_searching_test_Kd_tree_search ${CGAL_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) - else() - message(WARNING "Eigen3 not found. Version 3.1.0 is required for the Spatial_searching tests.") + + add_test(Spatial_searching_test_Kd_tree_search ${CMAKE_CURRENT_BINARY_DIR}/Spatial_searching_test_Kd_tree_search + # XML format for Jenkins xUnit plugin + --log_format=XML --log_sink=${CMAKE_SOURCE_DIR}/Spatial_searching_UT.xml --log_level=test_suite --report_level=no) endif() - else() - message(WARNING "CGAL version: ${CGAL_VERSION} is too old to compile Subsampling tests. Version 4.8.1 is required.") endif () -else() - message(WARNING "CGAL not found. It is required for the Spatial_searching tests.") endif() diff --git a/src/Spatial_searching/test/test_Kd_tree_search.cpp b/src/Spatial_searching/test/test_Kd_tree_search.cpp index 6f99b288..0ef22023 100644 --- a/src/Spatial_searching/test/test_Kd_tree_search.cpp +++ b/src/Spatial_searching/test/test_Kd_tree_search.cpp @@ -4,7 +4,7 @@ * * Author(s): Clement Jamin * - * Copyright (C) 2016 INRIA Sophia-Antipolis (France) + * Copyright (C) 2016 INRIA * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,38 +29,35 @@ #include <CGAL/Epick_d.h> #include <CGAL/Random.h> -#include <array> #include <vector> -BOOST_AUTO_TEST_CASE(test_Kd_tree_search) -{ - typedef CGAL::Epick_d<CGAL::Dimension_tag<4> > K; - typedef K::FT FT; - typedef K::Point_d Point; - typedef std::vector<Point> Points; +BOOST_AUTO_TEST_CASE(test_Kd_tree_search) { + typedef CGAL::Epick_d<CGAL::Dimension_tag<4> > K; + typedef K::FT FT; + typedef K::Point_d Point; + typedef std::vector<Point> Points; typedef Gudhi::spatial_searching::Kd_tree_search< - K, Points> Points_ds; - + K, Points> Points_ds; + CGAL::Random rd; Points points; - for (int i = 0 ; i < 500 ; ++i) - points.push_back(Point(rd.get_double(-1.,1), rd.get_double(-1.,1), rd.get_double(-1.,1), rd.get_double(-1.,1))); + for (int i = 0; i < 500; ++i) + points.push_back(Point(rd.get_double(-1., 1), rd.get_double(-1., 1), rd.get_double(-1., 1), rd.get_double(-1., 1))); Points_ds points_ds(points); // Test query_k_nearest_neighbors std::size_t closest_pt_index = - points_ds.query_k_nearest_neighbors(points[10], 1, false).begin()->first; + points_ds.query_k_nearest_neighbors(points[10], 1, false).begin()->first; BOOST_CHECK(closest_pt_index == 10); auto kns_range = points_ds.query_k_nearest_neighbors(points[20], 10, true); std::vector<std::size_t> knn_result; FT last_dist = -1.; - for (auto const& nghb : kns_range) - { + for (auto const& nghb : kns_range) { BOOST_CHECK(nghb.second > last_dist); knn_result.push_back(nghb.second); last_dist = nghb.second; @@ -68,17 +65,16 @@ BOOST_AUTO_TEST_CASE(test_Kd_tree_search) // Test query_incremental_nearest_neighbors closest_pt_index = - points_ds.query_incremental_nearest_neighbors(points[10]).begin()->first; + points_ds.query_incremental_nearest_neighbors(points[10]).begin()->first; BOOST_CHECK(closest_pt_index == 10); - auto ins_range = points_ds.query_incremental_nearest_neighbors(points[20]); + auto inn_range = points_ds.query_incremental_nearest_neighbors(points[20]); std::vector<std::size_t> inn_result; last_dist = -1.; - auto ins_it = ins_range.begin(); - for (int i = 0 ; i < 10 ; ++ins_it, ++i) - { - auto const& nghb = *ins_it; + auto inn_it = inn_range.begin(); + for (int i = 0; i < 10; ++inn_it, ++i) { + auto const& nghb = *inn_it; BOOST_CHECK(nghb.second > last_dist); inn_result.push_back(nghb.second); last_dist = nghb.second; @@ -88,26 +84,24 @@ BOOST_AUTO_TEST_CASE(test_Kd_tree_search) BOOST_CHECK(knn_result == inn_result); // Test query_k_farthest_neighbors - auto kfs_range = points_ds.query_k_farthest_neighbors(points[20], 10, true); + auto kfn_range = points_ds.query_k_farthest_neighbors(points[20], 10, true); std::vector<std::size_t> kfn_result; - last_dist = kfs_range.begin()->second; - for (auto const& nghb : kfs_range) - { + last_dist = kfn_range.begin()->second; + for (auto const& nghb : kfn_range) { BOOST_CHECK(nghb.second <= last_dist); kfn_result.push_back(nghb.second); last_dist = nghb.second; } // Test query_k_farthest_neighbors - auto ifs_range = points_ds.query_incremental_farthest_neighbors(points[20]); + auto ifn_range = points_ds.query_incremental_farthest_neighbors(points[20]); std::vector<std::size_t> ifn_result; - last_dist = ifs_range.begin()->second; - auto ifs_it = ifs_range.begin(); - for (int i = 0; i < 10; ++ifs_it, ++i) - { - auto const& nghb = *ifs_it; + last_dist = ifn_range.begin()->second; + auto ifn_it = ifn_range.begin(); + for (int i = 0; i < 10; ++ifn_it, ++i) { + auto const& nghb = *ifn_it; BOOST_CHECK(nghb.second <= last_dist); ifn_result.push_back(nghb.second); last_dist = nghb.second; |