mirror of https://github.com/CGAL/cgal
Move point-specific functionality to traits class
(only Point_3 is currently supported)
This commit is contained in:
parent
c41faf1274
commit
b08eabae93
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue