Move point-specific functionality to traits class

(only Point_3 is currently supported)
This commit is contained in:
JacksonCampolattaro 2023-06-26 16:59:02 +02:00
parent c41faf1274
commit b08eabae93
19 changed files with 325 additions and 142 deletions

View File

@ -73,7 +73,7 @@ split.
\subsection Section_Orthtree_Point_Vector Building an Octree
The `Orthtree` class may be templated with `Orthtree_traits_point_set_3` and thus
The `Orthtree` class may be templated with `Orthtree_traits_point_3` and thus
behave as an %octree. For convenience, the alias `Octree` is provided.
The following example shows how to create an %octree from a vector of

View File

@ -48,7 +48,7 @@
\cgalCRPSection{Traits}
- `CGAL::Orthtree_traits_2<GeomTraits>`
- `CGAL::Orthtree_traits_point_set_3<GeomTraits>`
- `CGAL::Orthtree_traits_point_3<GeomTraits>`
- `CGAL::Orthtree_traits_d<GeomTraits, Dimension>`
\cgalCRPSection{Split Predicates}

View File

@ -16,6 +16,7 @@
#include <CGAL/Orthtree.h>
#include <CGAL/Orthtree_traits_3.h>
#include <CGAL/Orthtree_traits_point_3.h>
namespace CGAL {
@ -43,7 +44,7 @@ template <
#ifdef DOXYGEN_RUNNING
class Octree;
#else
using Octree = Orthtree<Orthtree_traits_3<GeomTraits>, PointRange, PointMap>;
using Octree = Orthtree<Orthtree_traits_point_3<GeomTraits, PointRange, PointMap>>;
#endif
} // namespace CGAL

View File

@ -62,11 +62,8 @@ namespace CGAL {
\sa `CGAL::Octree`
\tparam Traits_ must be a model of `OrthtreeTraits`
\tparam PointRange_ must be a model of range whose value type is the key type of `PointMap_`
\tparam PointMap_ must be a model of `ReadablePropertyMap` whose value type is `Traits_::Point_d`
*/
template <typename Traits_, typename PointRange_,
typename PointMap_ = Identity_property_map<typename Traits_::Point_d> >
template <typename Traits_>
class Orthtree {
public:
@ -74,8 +71,6 @@ public:
/// \name Template Types
/// @{
typedef Traits_ Traits; ///< Geometry traits
typedef PointRange_ PointRange; ///< Point range
typedef PointMap_ PointMap; ///< Point map
/// @}
/// \name Traits Types
@ -87,6 +82,9 @@ public:
typedef typename Traits::Sphere_d Sphere; ///< Sphere type.
typedef typename Traits::Adjacency Adjacency; ///< Adjacency type.
typedef typename Traits::Node_data Node_data;
typedef typename Traits::Node_data_element Node_data_element;
/// \cond SKIP_IN_MANUAL
typedef typename Traits::Array Array; ///< Array type.
typedef typename Traits::Construct_point_d_from_array Construct_point_d_from_array;
@ -94,19 +92,13 @@ public:
/// \endcond
/// @}
/// \name Types specific to Point_set_3
/// todo: should be moved to Traits
/// @{
typedef boost::iterator_range<typename PointRange::iterator> Node_point_range;
/// @}
/// \name Public Types
/// @{
/*!
* \brief Self typedef for convenience.
*/
typedef Orthtree<Traits, PointRange, PointMap> Self;
typedef Orthtree<Traits> Self;
/*!
* \brief Degree of the tree (number of children of non-leaf nodes).
@ -168,17 +160,6 @@ public:
#endif
/// \cond SKIP_IN_MANUAL
/*!
* \brief A function that determines the next node in a traversal given the current one.
*/
typedef std::function<const Node*(const Node*)> Node_traversal_method_const;
/// \endcond
/// \cond SKIP_IN_MANUAL
typedef typename PointRange::iterator Range_iterator;
typedef typename std::iterator_traits<Range_iterator>::value_type Range_type;
typedef Orthtrees::internal::Cartesian_ranges<Traits> Cartesian_ranges;
/// \endcond
@ -187,11 +168,9 @@ public:
private: // data members :
Traits m_traits; /* the tree traits */
PointRange& m_range; /* input point range */
PointMap m_point_map; /* property map: `value_type of InputIterator` -> `Point` (Position) */
Node_property_container m_node_properties;
Node_property_container::Array <Node_point_range>& m_node_points;
Node_property_container::Array <Node_data>& m_node_points;
Node_property_container::Array <std::uint8_t>& m_node_depths;
Node_property_container::Array <Global_coordinates>& m_node_coordinates;
Node_property_container::Array <Maybe_node_index>& m_node_parents;
@ -235,12 +214,10 @@ public:
\param enlarge_ratio ratio to which the bounding box should be enlarged.
\param traits the traits object.
*/
Orthtree(PointRange& point_range,
PointMap point_map = PointMap(),
const FT enlarge_ratio = 1.2,
Traits traits = Traits()) :
m_traits(traits), m_range(point_range), m_point_map(point_map),
m_node_points(m_node_properties.add_property<Node_point_range>("points")),
Orthtree(Traits traits,
const FT enlarge_ratio = 1.2) :
m_traits(traits),
m_node_points(m_node_properties.add_property<Node_data>("points")),
m_node_depths(m_node_properties.add_property<std::uint8_t>("depths", 0)),
m_node_coordinates(m_node_properties.add_property<Global_coordinates>("coordinates")),
m_node_parents(m_node_properties.add_property<Maybe_node_index>("parents")),
@ -248,30 +225,11 @@ public:
m_node_properties.emplace();
Array bbox_min;
Array bbox_max;
// init bbox with first values found
{
const Point& p = get(m_point_map, *(point_range.begin()));
std::size_t i = 0;
for (const FT& x: cartesian_range(p)) {
bbox_min[i] = x;
bbox_max[i] = x;
++i;
}
}
for (const Range_type& r: point_range) {
const Point& p = get(m_point_map, r);
std::size_t i = 0;
for (const FT& x: cartesian_range(p)) {
bbox_min[i] = (std::min)(x, bbox_min[i]);
bbox_max[i] = (std::max)(x, bbox_max[i]);
++i;
}
}
auto [bbox_min, bbox_max] = m_traits.root_node_bbox();
// Dilate the bounding box
Array bbox_centroid;
FT max_length = FT(0);
for (std::size_t i = 0; i < Dimension::value; ++i) {
@ -279,7 +237,6 @@ public:
max_length = (std::max)(max_length, bbox_max[i] - bbox_min[i]);
}
max_length *= enlarge_ratio / FT(2);
for (std::size_t i = 0; i < Dimension::value; ++i) {
bbox_min[i] = bbox_centroid[i] - max_length;
bbox_max[i] = bbox_centroid[i] + max_length;
@ -291,7 +248,7 @@ public:
// save orthtree attributes
m_bbox_min = construct_point_d_from_array(bbox_min);
m_side_per_depth.push_back(bbox_max[0] - bbox_min[0]);
points(root()) = {point_range.begin(), point_range.end()};
points(root()) = m_traits.root_node_contents();
}
/// @}
@ -300,10 +257,10 @@ public:
// copy constructor
Orthtree(const Orthtree& other) :
m_traits(other.m_traits), m_range(other.m_range), m_point_map(other.m_point_map),
m_traits(other.m_traits),
m_bbox_min(other.m_bbox_min), m_side_per_depth(other.m_side_per_depth),
m_node_properties(other.m_node_properties),
m_node_points(m_node_properties.get_property<Node_point_range>("points")),
m_node_points(m_node_properties.get_property<Node_data>("points")),
m_node_depths(m_node_properties.get_property<std::uint8_t>("depths")),
m_node_coordinates(m_node_properties.get_property<Global_coordinates>("coordinates")),
m_node_parents(m_node_properties.get_property<Maybe_node_index>("parents")),
@ -311,10 +268,10 @@ public:
// move constructor
Orthtree(Orthtree&& other) :
m_traits(other.m_traits), m_range(other.m_range), m_point_map(other.m_point_map),
m_traits(other.m_traits),
m_bbox_min(other.m_bbox_min), m_side_per_depth(other.m_side_per_depth),
m_node_properties(std::move(other.m_node_properties)),
m_node_points(m_node_properties.get_property<Node_point_range>("points")),
m_node_points(m_node_properties.get_property<Node_data>("points")),
m_node_depths(m_node_properties.get_property<std::uint8_t>("depths")),
m_node_coordinates(m_node_properties.get_property<Global_coordinates>("coordinates")),
m_node_parents(m_node_properties.get_property<Maybe_node_index>("parents")),
@ -742,11 +699,11 @@ public:
return m_node_depths[n];
}
Node_point_range& points(Node_index n) {
Node_data& points(Node_index n) {
return m_node_points[n];
}
const Node_point_range& points(Node_index n) const {
const Node_data& points(Node_index n) const {
return m_node_points[n];
}
@ -883,7 +840,8 @@ public:
Point center = barycenter(n);
// Add the node's points to its children
reassign_points(n, points(n).begin(), points(n).end(), center);
m_traits.distribute_node_contents(n, *this, center);
//reassign_points(n, points(n).begin(), points(n).end(), center);
}
/*!
@ -1046,37 +1004,6 @@ public:
private: // functions :
void reassign_points(Node_index n, Range_iterator begin, Range_iterator end, const Point& center,
std::bitset<Dimension::value> coord = {},
std::size_t dimension = 0) {
// Root case: reached the last dimension
if (dimension == Dimension::value) {
points(child(n, coord.to_ulong())) = {begin, end};
return;
}
// Split the point collection around the center point on this dimension
Range_iterator split_point = std::partition(
begin, end,
[&](const Range_type& a) -> bool {
// This should be done with cartesian iterator,
// but it seems complicated to do efficiently
return (get(m_point_map, a)[int(dimension)] < center[int(dimension)]);
}
);
// Further subdivide the first side of the split
std::bitset<Dimension::value> coord_left = coord;
coord_left[dimension] = false;
reassign_points(n, begin, split_point, center, coord_left, dimension + 1);
// Further subdivide the second side of the split
std::bitset<Dimension::value> coord_right = coord;
coord_right[dimension] = true;
reassign_points(n, split_point, end, center, coord_right, dimension + 1);
}
bool do_intersect(Node_index n, const Sphere& sphere) const {
// Create a cubic bounding box from the node
@ -1087,8 +1014,8 @@ private: // functions :
}
// TODO: There has to be a better way than using structs like these!
struct Point_with_distance {
Point point;
struct Node_element_with_distance {
Node_data_element point;
FT distance;
};
@ -1102,7 +1029,7 @@ private: // functions :
};
void nearest_k_neighbors_recursive(Sphere& search_bounds, Node_index node,
std::vector<Point_with_distance>& results, FT epsilon = 0) const {
std::vector<Node_element_with_distance>& results, FT epsilon = 0) const {
// Check whether the node has children
if (is_leaf(node)) {
@ -1111,14 +1038,11 @@ private: // functions :
// Loop through each of the points contained by the node
// Note: there might be none, and that should be fine!
for (auto point_index: points(node)) {
// Retrieve each point from the orthtree's point map
auto point = get(m_point_map, point_index);
for (auto p: points(node)) {
// Pair that point with its distance from the search point
Point_with_distance current_point_with_distance =
{point, squared_distance(point, search_bounds.center())};
Node_element_with_distance current_point_with_distance =
{p, squared_distance(m_traits.get_element(p), search_bounds.center())};
// Check if the new point is within the bounds
if (current_point_with_distance.distance < search_bounds.squared_radius()) {
@ -1226,7 +1150,7 @@ private: // functions :
OutputIterator nearest_k_neighbors_in_radius(Sphere& query_sphere, std::size_t k, OutputIterator output) const {
// Create an empty list of points
std::vector<Point_with_distance> points_list;
std::vector<Node_element_with_distance> points_list;
if (k != (std::numeric_limits<std::size_t>::max)())
points_list.reserve(k);

View File

@ -25,7 +25,7 @@ namespace CGAL {
/// \cond SKIP_IN_MANUAL
// todo: is this necessary?
// Forward declaration
template <typename T, typename PR, typename PM>
template <typename T>
class Orthtree;
/// \endcond

View File

@ -0,0 +1,258 @@
// Copyright (c) 2023 INRIA (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Jackson Campolattaro
#ifndef ORTHTREE_TESTS_ORTHTREE_TRAITS_POINT_3_H
#define ORTHTREE_TESTS_ORTHTREE_TRAITS_POINT_3_H
#include <CGAL/license/Orthtree.h>
#include <CGAL/Dimension.h>
#include <CGAL/Bbox_3.h>
#include <CGAL/Point_set_3.h>
#include <CGAL/Orthtree/Cartesian_ranges.h>
namespace CGAL {
/*!
\ingroup PkgOrthtreeTraits
The class `Orthtree_traits_point_3` can be used as a template parameter of
the `Orthtree` class.
\tparam GeomTraits model of `Kernel`.
\tparam Point_set must be a model of range whose value type is the key type of `Point_map`
\tparam Point_map must be a model of `ReadablePropertyMap` whose value type is `GeomTraits::Traits::Point_d`
\cgalModels `OrthtreeTraits`
\sa `CGAL::Octree`
\sa `CGAL::Orthtree_traits_2`
\sa `CGAL::Orthtree_traits_d`
*/
template <
typename GeomTraits,
typename Point_set,
typename Point_map = Identity_property_map<typename GeomTraits::Point_3>
>
struct Orthtree_traits_point_3 {
public:
/// \name Types
/// @{
using Self = Orthtree_traits_point_3<GeomTraits, Point_set, Point_map>;
using Dimension = Dimension_tag<3>;
using Bbox_d = Bbox_3;
using FT = typename GeomTraits::FT;
using Point_d = typename GeomTraits::Point_3;
using Sphere_d = typename GeomTraits::Sphere_3;
using Cartesian_const_iterator_d = typename GeomTraits::Cartesian_const_iterator_3;
using Array = std::array<FT, Dimension::value>; // todo: This should have a more descriptive name
// todo: looking for better names
using Node_data = boost::iterator_range<typename Point_set::iterator>;
using Node_data_element = typename std::iterator_traits<typename Point_set::iterator>::value_type;
/*!
* \brief Two directions along each axis in Cartesian space, relative to a node.
*
* Directions are mapped to numbers as 3-bit integers,
* though the numbers 6 and 7 are not used because there are only 6 different directions.
*
* The first two bits indicate the axis (00 = x, 01 = y, 10 = z),
* the third bit indicates the direction along that axis (0 = -, 1 = +).
*
* The following diagram may be a useful reference:
*
* 3 *
* | * 5
* | / y+
* |/ * z+
* 0 *------+------* 1 | *
* /| |/
* / | +-----* x+
* 4 * |
* * 2
*
* This lookup table may also be helpful:
*
* | Direction | bitset | number | Enum |
* | --------- | ------ | ------ | ----- |
* | `-x` | 000 | 0 | LEFT |
* | `+x` | 001 | 1 | RIGHT |
* | `-y` | 010 | 2 | DOWN |
* | `+y` | 011 | 3 | UP |
* | `-z` | 100 | 4 | BACK |
* | `+z` | 101 | 5 | FRONT |
*/
enum Adjacency {
LEFT,
RIGHT,
DOWN,
UP,
BACK,
FRONT
};
/// \cond SKIP_IN_MANUAL
enum Child {
LEFT_BOTTOM_BACK,
RIGHT_BOTTOM_BACK,
LEFT_TOP_BACK,
RIGHT_TOP_BACK,
LEFT_BOTTOM_FRONT,
RIGHT_BOTTOM_FRONT,
LEFT_TOP_FRONT,
RIGHT_TOP_FRONT
};
/// \endcond
#ifdef DOXYGEN_RUNNING
/*!
Functor with an operator to construct a `Point_d` from an `Array` object.
*/
typedef unspecified_type Construct_point_d_from_array;
#else
struct Construct_point_d_from_array {
Point_d operator()(const Array& array) const {
return Point_d(array[0], array[1], array[2]);
}
};
#endif
#ifdef DOXYGEN_RUNNING
/*!
Functor with an operator to construct a `Bbox_d` from two `Array` objects (coordinates of minimum and maximum points).
*/
typedef unspecified_type Construct_bbox_d;
#else
struct Construct_bbox_d {
Bbox_d operator()(const Array& min,
const Array& max) const {
return Bbox_d(min[0], min[1], min[2], max[0], max[1], max[2]);
}
};
#endif
/// @}
Orthtree_traits_point_3(
Point_set& point_set,
Point_map point_map = Point_map()
) : m_point_set(point_set), m_point_map(point_map) {}
/// \name Operations
/// The user shouldn't need to define these themselves
/// @{
/*!
Function used to construct an object of type `Construct_point_d_from_array`.
*/
Construct_point_d_from_array construct_point_d_from_array_object() const { return Construct_point_d_from_array(); }
/*!
Function used to construct an object of type `Construct_bbox_d`.
*/
Construct_bbox_d construct_bbox_d_object() const { return Construct_bbox_d(); }
std::pair<Array, Array> root_node_bbox() const {
Array bbox_min;
Array bbox_max;
Orthtrees::internal::Cartesian_ranges<Self> cartesian_range;
// init bbox with first values found
{
const Point_d& point = get(m_point_map, *(m_point_set.begin()));
std::size_t i = 0;
for (const FT& x: cartesian_range(point)) {
bbox_min[i] = x;
bbox_max[i] = x;
++i;
}
}
// Expand bbox to contain all points
for (const auto& p: m_point_set) {
const Point_d& point = get(m_point_map, p);
std::size_t i = 0;
for (const FT& x: cartesian_range(point)) {
bbox_min[i] = (std::min)(x, bbox_min[i]);
bbox_max[i] = (std::max)(x, bbox_max[i]);
++i;
}
}
return {bbox_min, bbox_max};
}
Node_data root_node_contents() const { return {m_point_set.begin(), m_point_set.end()}; }
template <typename Node_index, typename Tree>
void distribute_node_contents(Node_index n, Tree& tree, const Point_d& center) {
CGAL_precondition(!tree.is_leaf(n));
reassign_points(n, tree, center, tree.points(n));
}
Point_d get_element(const Node_data_element& index) const {
return get(m_point_map, index);
}
/// @}
private:
Point_set& m_point_set;
Point_map m_point_map;
template <typename Node_index, typename Tree>
void reassign_points(Node_index n, Tree& tree,
const Point_d& center, Node_data points,
std::bitset<Dimension::value> coord = {},
std::size_t dimension = 0) {
// Root case: reached the last dimension
if (dimension == Dimension::value) {
tree.points(tree.child(n, coord.to_ulong())) = points;
return;
}
// Split the point collection around the center point on this dimension
auto split_point = std::partition(
points.begin(), points.end(),
[&](const auto& p) -> bool {
// This should be done with cartesian iterator,
// but it seems complicated to do efficiently
return (get(m_point_map, p)[int(dimension)] < center[int(dimension)]);
}
);
// Further subdivide the first side of the split
std::bitset<Dimension::value> coord_left = coord;
coord_left[dimension] = false;
reassign_points(n, tree, center, {points.begin(), split_point}, coord_left, dimension + 1);
// Further subdivide the second side of the split
std::bitset<Dimension::value> coord_right = coord;
coord_right[dimension] = true;
reassign_points(n, tree, center, {split_point, points.end()}, coord_right, dimension + 1);
}
};
}
#endif //ORTHTREE_TESTS_ORTHTREE_TRAITS_POINT_3_H

View File

@ -36,7 +36,7 @@ int main(void) {
points.insert({-1, -1, -1.8});
points.insert({-1, -1, -1.9});
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 1);
std::cout << octree << std::endl;

View File

@ -34,7 +34,7 @@ int main(void) {
points.insert({-1, -1, -1.8});
points.insert({-1, -1, -1.9});
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 1);
std::cout << "root: " << octree.local_coordinates(octree.root()) << std::endl;

View File

@ -20,7 +20,7 @@ void test_1_node() {
points.insert({-1, -1, -1});
// Create the octree
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 1);
// Compare the top (only) node
@ -35,7 +35,7 @@ void test_9_nodes() {
points.insert({1, 1, 1});
// Create the octree
Octree octree(points, points.point_map(), 1.1);
Octree octree({points, points.point_map()}, 1.1);
octree.refine(10, 1);
// Compare the top node
@ -62,7 +62,7 @@ void test_25_nodes() {
points.insert({1, 0.5, 1});
// Create the octree
Octree octree(points, points.point_map(), 1.5);
Octree octree({points, points.point_map()}, 1.5);
octree.refine(10, 1);
// Compare the top node

View File

@ -24,7 +24,7 @@ int main(void)
for (std::size_t i = 0; i < nb_pts; ++i)
points.insert(*(generator++));
Octree base (points, points.point_map());
Octree base ({points, points.point_map()});
assert (base.is_leaf(base.root())); // base is not refined yet
Octree copy1 (base);

View File

@ -23,7 +23,7 @@ int main(void) {
for (std::size_t i = 0; i < nb_pts; ++i)
points.insert(*(generator++));
Octree tree(points, points.point_map());
Octree tree({points, points.point_map()});
// Default value should be respected
auto &node_int_property = tree.add_node_property<int>("int", 5);

View File

@ -26,8 +26,8 @@ void test_identical_trees() {
points.insert({1, 1, 1});
// Create a pair of trees from the same point set
Octree a(points, points.point_map());
Octree b(points, points.point_map());
Octree a({points, points.point_map()});
Octree b({points, points.point_map()});
// Refine both trees using the same criteria
a.refine(10, 1);
@ -52,8 +52,8 @@ void test_identical_contents_different_criteria() {
points.insert({1, 1, 1});
// Create a pair of trees from the same point set
Octree a(points, points.point_map());
Octree b(points, points.point_map());
Octree a({points, points.point_map()});
Octree b({points, points.point_map()});
// Refine both trees using different criteria
a.refine(10, 1);
@ -87,8 +87,8 @@ void test_different_contents_identical_criteria() {
points_b.insert({1, 1, 2});
// Create a pair of trees from the different point sets
Octree a(points_a, points_a.point_map());
Octree b(points_b, points_b.point_map());
Octree a({points_a, points_a.point_map()});
Octree b({points_b, points_b.point_map()});
// Refine both trees using the same criteria
a.refine(10, 1);

View File

@ -48,7 +48,7 @@ void test(std::size_t dataset_size) {
points.insert(*(generator++));
// Build an octree
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
// Refine the octree
octree.refine();

View File

@ -34,7 +34,7 @@ int main(void) {
points.emplace_back(-0.9, -1, -1);
// Create an octree from the vector
Octree octree(points);
Octree octree(Octree::Traits{points});
// Build the octree
octree.refine(10, 2);

View File

@ -18,7 +18,7 @@ void test()
for (std::size_t i = 0; i < 100; ++i)
points.insert(*(generator++));
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine();
octree.grade();
}

View File

@ -22,7 +22,7 @@ void test_1_point() {
points.insert({-1, -1, -1});
// Create the octree
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 1);
// Because there's only the root node, any point should be placed in it
@ -48,7 +48,7 @@ void test_8_points() {
points.insert({1, 1, 1});
// Create the octree
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 1);
// Existing points should end up in the same place
@ -89,7 +89,7 @@ void test_10_points() {
points.insert({-1, -0.75, 1});
// Create the octree
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 1);
// Existing points should end up in the same place

View File

@ -68,13 +68,13 @@ void naive_vs_octree(std::size_t dataset_size) {
// Do the same using the octree
Point octree_nearest = *generator;
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 20);
auto octree_start_time = high_resolution_clock::now();
{
std::vector<Point> k_neighbors;
std::vector<Point_set::Index> k_neighbors;
octree.nearest_neighbors(random_point, 1, std::back_inserter(k_neighbors));
octree_nearest = *k_neighbors.begin();
octree_nearest = get(points.point_map(), *k_neighbors.begin());
}
duration<float> octree_elapsed_time = high_resolution_clock::now() - octree_start_time;
@ -119,8 +119,8 @@ void kdtree_vs_octree(std::size_t dataset_size, std::size_t K) {
<< std::endl;
// Do the same using the octree
std::vector<Point> octree_nearest_neighbors;
Octree octree(points, points.point_map());
std::vector<Point_set::Index> octree_nearest_neighbors;
Octree octree({points, points.point_map()});
octree.refine(10, 20);
auto octree_start_time = high_resolution_clock::now();
octree.nearest_neighbors(random_point, K, std::back_inserter(octree_nearest_neighbors));
@ -136,7 +136,7 @@ void kdtree_vs_octree(std::size_t dataset_size, std::size_t K) {
// Check that they produce the same answer
for (std::size_t j = 0; j < K; ++j)
assert(octree_nearest_neighbors[j] == kd_tree_nearest_neighbors[j]);
assert(get(points.point_map(), octree_nearest_neighbors[j]) == kd_tree_nearest_neighbors[j]);
}

View File

@ -38,7 +38,7 @@ void test_1_point() {
points.insert({-1, -1, -1});
// Create the octree
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 1);
// Check that the root node was never split
@ -54,11 +54,11 @@ void test_2_points() {
points.insert({1, -1, -1});
// Create the octree
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 1);
// The octree should have been split once
Octree other(points, points.point_map());
Octree other({points, points.point_map()});
other.split(other.root());
assert(Octree::is_topology_equal(other, octree));
assert(1 == octree.depth());
@ -73,11 +73,11 @@ void test_4_points() {
points.insert({1, 1, 4});
// Create the octree
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 1);
// The octree should have been split once on the first level, and twice on the second
Octree other(points, points.point_map());
Octree other({points, points.point_map()});
other.split(other.root());
other.split(other.node(3));
other.split(other.node(7));

View File

@ -22,7 +22,7 @@ bool test_preorder_1_node() {
points.insert({-1, -1, -1});
// Create the octree
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 1);
// Create the range
@ -43,7 +43,7 @@ bool test_preorder_9_nodes() {
points.insert({1, -1, -1});
// Create the octree
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 1);
// Create the range
@ -68,7 +68,7 @@ bool test_level_9_nodes() {
points.insert({1, -1, -1});
// Create the octree
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 1);
// Create the range
@ -94,7 +94,7 @@ bool test_preorder_25_nodes() {
points.insert({1, 1, 4});
// Create the octree
Octree octree(points, points.point_map());
Octree octree({points, points.point_map()});
octree.refine(10, 1);
// Create the range