mirror of https://github.com/CGAL/cgal
Add shims for using functions with indices
This commit is contained in:
parent
9103affe72
commit
4e3fc7edf6
|
|
@ -87,10 +87,8 @@ public:
|
||||||
|
|
||||||
/// \cond SKIP_IN_MANUAL
|
/// \cond SKIP_IN_MANUAL
|
||||||
typedef typename Traits::Array Array; ///< Array type.
|
typedef typename Traits::Array Array; ///< Array type.
|
||||||
typedef typename Traits::Construct_point_d_from_array
|
typedef typename Traits::Construct_point_d_from_array Construct_point_d_from_array;
|
||||||
Construct_point_d_from_array;
|
typedef typename Traits::Construct_bbox_d Construct_bbox_d;
|
||||||
typedef typename Traits::Construct_bbox_d
|
|
||||||
Construct_bbox_d;
|
|
||||||
/// \endcond
|
/// \endcond
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
@ -107,6 +105,11 @@ public:
|
||||||
*/
|
*/
|
||||||
typedef Dimension_tag<(2 << (Dimension::value - 1))> Degree;
|
typedef Dimension_tag<(2 << (Dimension::value - 1))> Degree;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Index of a given node in the tree; the root always has index 0.
|
||||||
|
*/
|
||||||
|
typedef std::size_t Node_index;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief The Sub-tree / Orthant type.
|
* \brief The Sub-tree / Orthant type.
|
||||||
*/
|
*/
|
||||||
|
|
@ -197,8 +200,6 @@ public:
|
||||||
, m_range(point_range)
|
, m_range(point_range)
|
||||||
, m_point_map(point_map) {
|
, m_point_map(point_map) {
|
||||||
|
|
||||||
// fixme: this can be removed once traversal doesn't require pointer stability
|
|
||||||
//m_nodes.reserve(1'000'000);
|
|
||||||
m_nodes.emplace_back();
|
m_nodes.emplace_back();
|
||||||
|
|
||||||
Array bbox_min;
|
Array bbox_min;
|
||||||
|
|
@ -311,7 +312,7 @@ public:
|
||||||
m_side_per_depth.resize(1);
|
m_side_per_depth.resize(1);
|
||||||
|
|
||||||
// Initialize a queue of nodes that need to be refined
|
// Initialize a queue of nodes that need to be refined
|
||||||
std::queue<std::size_t> todo;
|
std::queue<Node_index> todo;
|
||||||
todo.push(0);
|
todo.push(0);
|
||||||
|
|
||||||
// Process items in the queue until it's consumed fully
|
// Process items in the queue until it's consumed fully
|
||||||
|
|
@ -372,28 +373,27 @@ public:
|
||||||
void grade() {
|
void grade() {
|
||||||
|
|
||||||
// Collect all the leaf nodes
|
// Collect all the leaf nodes
|
||||||
std::queue<Node*> leaf_nodes;
|
std::queue<Node_index> leaf_nodes;
|
||||||
for (const Node& leaf: traverse(Orthtrees::Leaves_traversal<Self>(*this))) {
|
for (const Node& leaf: traverse(Orthtrees::Leaves_traversal<Self>(*this))) {
|
||||||
// TODO: I'd like to find a better (safer) way of doing this
|
leaf_nodes.push(index(leaf));
|
||||||
leaf_nodes.push(const_cast<Node*>(&leaf));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over the nodes
|
// Iterate over the nodes
|
||||||
while (!leaf_nodes.empty()) {
|
while (!leaf_nodes.empty()) {
|
||||||
|
|
||||||
// Get the next node
|
// Get the next node
|
||||||
Node* node = leaf_nodes.front();
|
Node_index node = leaf_nodes.front();
|
||||||
leaf_nodes.pop();
|
leaf_nodes.pop();
|
||||||
|
|
||||||
// Skip this node if it isn't a leaf anymore
|
// Skip this node if it isn't a leaf anymore
|
||||||
if (!node->is_leaf())
|
if (!m_nodes[node].is_leaf())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Iterate over each of the neighbors
|
// Iterate over each of the neighbors
|
||||||
for (int direction = 0; direction < 6; ++direction) {
|
for (int direction = 0; direction < 6; ++direction) {
|
||||||
|
|
||||||
// Get the neighbor
|
// Get the neighbor
|
||||||
auto* neighbor = adjacent_node(*node, direction);
|
auto neighbor = index(adjacent_node(node, direction));
|
||||||
|
|
||||||
// If it doesn't exist, skip it
|
// If it doesn't exist, skip it
|
||||||
if (!neighbor)
|
if (!neighbor)
|
||||||
|
|
@ -401,23 +401,23 @@ public:
|
||||||
|
|
||||||
// Skip if this neighbor is a direct sibling (it's guaranteed to be the same depth)
|
// Skip if this neighbor is a direct sibling (it's guaranteed to be the same depth)
|
||||||
// TODO: This check might be redundant, if it doesn't affect performance maybe I could remove it
|
// TODO: This check might be redundant, if it doesn't affect performance maybe I could remove it
|
||||||
if (&parent(*neighbor) == &parent(*node))
|
if (parent(neighbor.get()) == parent(node))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If it's already been split, skip it
|
// If it's already been split, skip it
|
||||||
if (!neighbor->is_leaf())
|
if (!m_nodes[neighbor.get()].is_leaf())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check if the neighbor breaks our grading rule
|
// Check if the neighbor breaks our grading rule
|
||||||
// TODO: could the rule be parametrized?
|
// TODO: could the rule be parametrized?
|
||||||
if ((node->depth() - neighbor->depth()) > 1) {
|
if ((m_nodes[node].depth() - m_nodes[neighbor.get()].depth()) > 1) {
|
||||||
|
|
||||||
// Split the neighbor
|
// Split the neighbor
|
||||||
split(*neighbor);
|
split(neighbor.get());
|
||||||
|
|
||||||
// Add newly created children to the queue
|
// Add newly created children to the queue
|
||||||
for (int i = 0; i < Degree::value; ++i) {
|
for (int i = 0; i < Degree::value; ++i) {
|
||||||
leaf_nodes.push(&children(*neighbor)[i]);
|
leaf_nodes.push(index(children(neighbor.get())[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -445,21 +445,21 @@ public:
|
||||||
*/
|
*/
|
||||||
Node& root() { return m_nodes[0]; }
|
Node& root() { return m_nodes[0]; }
|
||||||
|
|
||||||
std::size_t index(const Node& node) const {
|
Node_index index(const Node& node) const {
|
||||||
return std::distance(m_nodes.data(), &node);
|
return std::distance(m_nodes.data(), &node);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<std::size_t> index(const Node* node) const {
|
boost::optional<Node_index> index(const Node* node) const {
|
||||||
if (node == nullptr) return {};
|
if (node == nullptr) return {};
|
||||||
return index(*node);
|
return index(*node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Node& operator[](std::size_t index) const {
|
const Node& operator[](Node_index index) const {
|
||||||
return m_nodes[index];
|
return m_nodes[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
Node& operator[](std::size_t index) {
|
Node& operator[](Node_index index) {
|
||||||
return m_nodes[index];
|
return m_nodes[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -486,7 +486,7 @@ public:
|
||||||
|
|
||||||
const Node* first = traversal.first();
|
const Node* first = traversal.first();
|
||||||
|
|
||||||
auto next = [=](const Self& tree, std::size_t index) -> boost::optional<std::size_t> {
|
auto next = [=](const Self& tree, Node_index index) -> boost::optional<Node_index> {
|
||||||
auto n = traversal.next(&tree[index]);
|
auto n = traversal.next(&tree[index]);
|
||||||
if (n == nullptr) return {};
|
if (n == nullptr) return {};
|
||||||
return tree.index(*n);
|
return tree.index(*n);
|
||||||
|
|
@ -528,6 +528,10 @@ public:
|
||||||
return construct_bbox(min_corner, max_corner);
|
return construct_bbox(min_corner, max_corner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bbox bbox(Node_index n) const {
|
||||||
|
return bbox(m_nodes[n]);
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
/// \name Queries
|
/// \name Queries
|
||||||
|
|
@ -603,8 +607,7 @@ public:
|
||||||
template <typename OutputIterator>
|
template <typename OutputIterator>
|
||||||
OutputIterator nearest_neighbors(const Sphere& query, OutputIterator output) const {
|
OutputIterator nearest_neighbors(const Sphere& query, OutputIterator output) const {
|
||||||
Sphere query_sphere = query;
|
Sphere query_sphere = query;
|
||||||
return nearest_k_neighbors_in_radius(query_sphere,
|
return nearest_k_neighbors_in_radius(query_sphere, (std::numeric_limits<std::size_t>::max)(), output);
|
||||||
(std::numeric_limits<std::size_t>::max)(), output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -677,6 +680,11 @@ public:
|
||||||
return m_nodes[node.m_parent_index.get()];
|
return m_nodes[node.m_parent_index.get()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node_index parent(Node_index node) const {
|
||||||
|
CGAL_precondition (!m_nodes[node].is_root());
|
||||||
|
return m_nodes[node].m_parent_index.get();
|
||||||
|
}
|
||||||
|
|
||||||
// todo: these types can probably be moved out of Node
|
// todo: these types can probably be moved out of Node
|
||||||
using Children = typename Node::Children;
|
using Children = typename Node::Children;
|
||||||
using Children_const = typename Node::Children_const;
|
using Children_const = typename Node::Children_const;
|
||||||
|
|
@ -686,11 +694,19 @@ public:
|
||||||
return Children{&m_nodes[node.m_children_index.get()], Degree::value};
|
return Children{&m_nodes[node.m_children_index.get()], Degree::value};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Children children(Node_index node) {
|
||||||
|
return children(m_nodes[node]);
|
||||||
|
}
|
||||||
|
|
||||||
Children_const children(const Node& node) const {
|
Children_const children(const Node& node) const {
|
||||||
CGAL_precondition (!node.is_leaf());
|
CGAL_precondition (!node.is_leaf());
|
||||||
return Children_const{&m_nodes[node.m_children_index.get()], Degree::value};
|
return Children_const{&m_nodes[node.m_children_index.get()], Degree::value};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Children_const children(Node_index node) const {
|
||||||
|
return children(m_nodes[node]);
|
||||||
|
}
|
||||||
|
|
||||||
const Node* next_sibling(const Node* n) const {
|
const Node* next_sibling(const Node* n) const {
|
||||||
|
|
||||||
// todo: maybe this should take a reference?
|
// todo: maybe this should take a reference?
|
||||||
|
|
@ -702,16 +718,20 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Find out which child this is
|
// Find out which child this is
|
||||||
std::size_t index = n->local_coordinates().to_ulong();
|
std::size_t local_coordinates = n->local_coordinates().to_ulong();
|
||||||
|
|
||||||
constexpr static int degree = Node::Degree::value;
|
constexpr static int degree = Node::Degree::value;
|
||||||
|
|
||||||
// Return null if this is the last child
|
// Return null if this is the last child
|
||||||
if (int(index) == degree - 1)
|
if (int(local_coordinates) == degree - 1)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Otherwise, return the next child
|
// Otherwise, return the next child
|
||||||
return &(children(parent(*n))[index + 1]);
|
return &(children(parent(*n))[local_coordinates + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Node* next_sibling(Node_index n) const {
|
||||||
|
return next_sibling(&m_nodes[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Node* next_sibling_up(const Node* n) const {
|
const Node* next_sibling_up(const Node* n) const {
|
||||||
|
|
@ -731,6 +751,10 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Node* next_sibling_up(Node_index n) const {
|
||||||
|
return next_sibling_up(&m_nodes[n]);
|
||||||
|
}
|
||||||
|
|
||||||
const Node* deepest_first_child(const Node* n) const {
|
const Node* deepest_first_child(const Node* n) const {
|
||||||
|
|
||||||
if (n == nullptr)
|
if (n == nullptr)
|
||||||
|
|
@ -743,12 +767,16 @@ public:
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Node* deepest_first_child(Node_index n) const {
|
||||||
|
return deepest_first_child(&m_nodes[n]);
|
||||||
|
}
|
||||||
|
|
||||||
const Node* first_child_at_depth(const Node* n, std::size_t depth) const {
|
const Node* first_child_at_depth(const Node* n, std::size_t depth) const {
|
||||||
|
|
||||||
if (!n)
|
if (!n)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
// todo: use Node_index instead of pointer
|
||||||
std::stack<const Node*> todo;
|
std::stack<const Node*> todo;
|
||||||
todo.push(n);
|
todo.push(n);
|
||||||
|
|
||||||
|
|
@ -770,6 +798,10 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Node* first_child_at_depth(Node_index n, std::size_t depth) const {
|
||||||
|
return first_child_at_depth(&m_nodes[n], depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief splits the node into subnodes.
|
\brief splits the node into subnodes.
|
||||||
|
|
@ -782,7 +814,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void split(Node& node) { split(index(node)); }
|
void split(Node& node) { split(index(node)); }
|
||||||
|
|
||||||
void split(std::size_t n) {
|
void split(Node_index n) {
|
||||||
|
|
||||||
// Make sure the node hasn't already been split
|
// Make sure the node hasn't already been split
|
||||||
CGAL_precondition (m_nodes[n].is_leaf());
|
CGAL_precondition (m_nodes[n].is_leaf());
|
||||||
|
|
@ -813,7 +845,7 @@ public:
|
||||||
node.m_children_index.reset();
|
node.m_children_index.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void unsplit(std::size_t n) {
|
void unsplit(Node_index n) {
|
||||||
unsplit(m_nodes[n]);
|
unsplit(m_nodes[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -837,6 +869,9 @@ public:
|
||||||
return construct_point_d_from_array(bary);
|
return construct_point_d_from_array(bary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Point barycenter(Node_index n) const {
|
||||||
|
return barycenter(m_nodes[n]);
|
||||||
|
}
|
||||||
|
|
||||||
// todo: this does what the documentation for operator== claims to do!
|
// todo: this does what the documentation for operator== claims to do!
|
||||||
static bool is_topology_equal(const Node& lhsNode, const Self& lhsTree, const Node& rhsNode, const Self& rhsTree) {
|
static bool is_topology_equal(const Node& lhsNode, const Self& lhsTree, const Node& rhsNode, const Self& rhsTree) {
|
||||||
|
|
@ -959,6 +994,10 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Node* adjacent_node(Node_index n, typename Node::Local_coordinates direction) const {
|
||||||
|
return adjacent_node(m_nodes[n], direction);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief equivalent to `adjacent_node()`, with an adjacency direction rather than a bitset.
|
\brief equivalent to `adjacent_node()`, with an adjacency direction rather than a bitset.
|
||||||
*/
|
*/
|
||||||
|
|
@ -966,6 +1005,10 @@ public:
|
||||||
return adjacent_node(node, std::bitset<Dimension::value>(static_cast<int>(adjacency)));
|
return adjacent_node(node, std::bitset<Dimension::value>(static_cast<int>(adjacency)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Node* adjacent_node(Node_index n, typename Node::Adjacency adjacency) const {
|
||||||
|
return adjacent_node(m_nodes[n], adjacency);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief equivalent to adjacent_node, except non-const
|
* \brief equivalent to adjacent_node, except non-const
|
||||||
*/
|
*/
|
||||||
|
|
@ -1018,15 +1061,25 @@ 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) {
|
||||||
|
reassign_points(m_nodes[n], begin, end, center, coord, dimension);
|
||||||
|
}
|
||||||
|
|
||||||
bool do_intersect(const Node& node, const Sphere& sphere) const {
|
bool do_intersect(const Node& node, const Sphere& sphere) const {
|
||||||
|
|
||||||
// Create a cubic bounding box from the node
|
// Create a cubic bounding box from the node
|
||||||
Bbox node_cube = bbox(node);
|
Bbox node_cube = bbox(node);
|
||||||
|
|
||||||
// Check for overlap between the node's box and the sphere as a box, to quickly catch some cases
|
// Check for intersection between the node and the sphere
|
||||||
// FIXME: Activating this causes slower times
|
return CGAL::do_intersect(node_cube, sphere);
|
||||||
// if (!do_overlap(node_cube, sphere.bbox()))
|
}
|
||||||
// return false;
|
|
||||||
|
bool do_intersect(Node_index n, const Sphere& sphere) const {
|
||||||
|
|
||||||
|
// Create a cubic bounding box from the node
|
||||||
|
Bbox node_cube = bbox(n);
|
||||||
|
|
||||||
// Check for intersection between the node and the sphere
|
// Check for intersection between the node and the sphere
|
||||||
return CGAL::do_intersect(node_cube, sphere);
|
return CGAL::do_intersect(node_cube, sphere);
|
||||||
|
|
@ -1167,9 +1220,7 @@ private: // functions :
|
||||||
\param output the output iterator to add the found points to (in order of increasing distance)
|
\param output the output iterator to add the found points to (in order of increasing distance)
|
||||||
*/
|
*/
|
||||||
template <typename OutputIterator>
|
template <typename OutputIterator>
|
||||||
OutputIterator nearest_k_neighbors_in_radius
|
OutputIterator nearest_k_neighbors_in_radius(Sphere& query_sphere, std::size_t k, OutputIterator output) const {
|
||||||
(Sphere& query_sphere,
|
|
||||||
std::size_t k, OutputIterator output) const {
|
|
||||||
|
|
||||||
// Create an empty list of points
|
// Create an empty list of points
|
||||||
std::vector<Point_with_distance> points_list;
|
std::vector<Point_with_distance> points_list;
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ public:
|
||||||
typedef Orthtree<Traits, PointRange, PointMap> Enclosing; ///< Orthtree type (enclosing class).
|
typedef Orthtree<Traits, PointRange, PointMap> Enclosing; ///< Orthtree type (enclosing class).
|
||||||
typedef typename Enclosing::Dimension Dimension; ///< Dimension type.
|
typedef typename Enclosing::Dimension Dimension; ///< Dimension type.
|
||||||
typedef typename Enclosing::Degree Degree; ///< Degree type.
|
typedef typename Enclosing::Degree Degree; ///< Degree type.
|
||||||
|
typedef typename Enclosing::Node_index Node_index; ///< Index type.
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Self typedef for convenience.
|
\brief Self typedef for convenience.
|
||||||
|
|
@ -106,9 +107,8 @@ private:
|
||||||
std::uint8_t m_depth = 0;
|
std::uint8_t m_depth = 0;
|
||||||
Global_coordinates m_global_coordinates{};
|
Global_coordinates m_global_coordinates{};
|
||||||
|
|
||||||
// todo
|
boost::optional<Node_index> m_parent_index{};
|
||||||
boost::optional<std::size_t> m_parent_index{};
|
boost::optional<Node_index> m_children_index{};
|
||||||
boost::optional<std::size_t> m_children_index{};
|
|
||||||
|
|
||||||
// Only the Orthtree class has access to the non-default
|
// Only the Orthtree class has access to the non-default
|
||||||
// constructor, mutators, etc.
|
// constructor, mutators, etc.
|
||||||
|
|
@ -138,7 +138,7 @@ public:
|
||||||
\param parent the node containing this one
|
\param parent the node containing this one
|
||||||
\param index this node's relationship to its parent
|
\param index this node's relationship to its parent
|
||||||
*/
|
*/
|
||||||
explicit Node(std::size_t parent_index, Global_coordinates parent_coordinates,
|
explicit Node(Node_index parent_index, Global_coordinates parent_coordinates,
|
||||||
std::size_t depth, Local_coordinates local_coordinates) :
|
std::size_t depth, Local_coordinates local_coordinates) :
|
||||||
m_parent_index(parent_index), m_depth(depth) {
|
m_parent_index(parent_index), m_depth(depth) {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue