Skip to content

Commit

Permalink
Orthtree: Doc and traits bugfixes (#8678)
Browse files Browse the repository at this point in the history
## Summary of Changes

Octree doc states requirement of RandomAccessIterator for point range
added missing _object types for functors in traits

## Release Management

* Affected package(s): Orthtree
  • Loading branch information
sloriot authored Jan 9, 2025
2 parents a7afaf8 + e1cc01c commit 17e6644
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 31 deletions.
2 changes: 1 addition & 1 deletion Orthtree/include/CGAL/Octree.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace CGAL {
\brief Alias that specializes the `Orthtree` class to a 3D octree storing 3D points.
\tparam GeomTraits a model of `Kernel`
\tparam PointRange a model of `Range` whose value type is the key type of `PointMap`
\tparam PointRange a model of `Range` whose value type is the key type of `PointMap` and whose iterator type is a model of `RandomAccessIterator`
\tparam PointMap a model of `ReadablePropertyMap` whose value type is `GeomTraits::Point_3`
\tparam cubic_nodes Boolean to enforce cubic nodes
*/
Expand Down
21 changes: 11 additions & 10 deletions Orthtree/include/CGAL/Orthtree.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class Orthtree {
/// @{
#ifndef DOXYGEN_RUNNING
static inline constexpr bool has_data = Orthtree_impl::has_Node_data<GeomTraits>::value;
static inline constexpr bool supports_neighbor_search = true;// Orthtree_impl::has_Squared_distance_of_element<GeomTraits>::value;
static inline constexpr bool supports_neighbor_search = Orthtree_impl::has_Squared_distance_of_element<GeomTraits>::value;
#else
static inline constexpr bool has_data = bool_value; ///< `true` if `GeomTraits` is a model of `OrthtreeTraitsWithData` and `false` otherwise.
static inline constexpr bool supports_neighbor_search = bool_value; ///< `true` if `GeomTraits` is a model of `CollectionPartitioningOrthtreeTraits` and `false` otherwise.
Expand Down Expand Up @@ -385,7 +385,8 @@ class Orthtree {
\param max_depth deepest a tree is allowed to be (nodes at this depth will not be split).
\param bucket_size maximum number of items a node is allowed to contain.
*/
void refine(size_t max_depth = 10, size_t bucket_size = 20) {
template<typename Orthtree = Self>
auto refine(size_t max_depth = 10, size_t bucket_size = 20) -> std::enable_if_t<Orthtree::has_data, void> {
refine(Orthtrees::Maximum_depth_and_maximum_contained_elements(max_depth, bucket_size));
}

Expand Down Expand Up @@ -681,10 +682,10 @@ class Orthtree {
\warning Nearest neighbor searches requires `GeomTraits` to be a model of `CollectionPartitioningOrthtreeTraits`.
*/
template<typename OutputIterator>
template<typename OutputIterator, typename Orthtree = Self>
auto nearest_k_neighbors(const Point& query,
std::size_t k,
OutputIterator output) const -> std::enable_if_t<supports_neighbor_search, OutputIterator> {
OutputIterator output) const -> std::enable_if_t<Orthtree::supports_neighbor_search, OutputIterator> {
Sphere query_sphere(query, (std::numeric_limits<FT>::max)());
CGAL_precondition(k > 0);

Expand All @@ -704,8 +705,8 @@ class Orthtree {
\warning Nearest neighbor searches requires `GeomTraits` to be a model of `CollectionPartitioningOrthtreeTraits`.
*/
template<typename OutputIterator>
auto neighbors_within_radius(const Sphere& query, OutputIterator output) const -> std::enable_if_t<supports_neighbor_search, OutputIterator> {
template<typename OutputIterator, typename Orthtree = Self>
auto neighbors_within_radius(const Sphere& query, OutputIterator output) const -> std::enable_if_t<Orthtree::supports_neighbor_search, OutputIterator> {
return nearest_k_neighbors_within_radius(query, (std::numeric_limits<std::size_t>::max)(), output);
}

Expand All @@ -726,12 +727,12 @@ class Orthtree {
\warning Nearest neighbor searches requires `GeomTraits` to be a model of `CollectionPartitioningOrthtreeTraits`.
*/
template <typename OutputIterator>
template <typename OutputIterator, typename Orthtree = Self>
auto nearest_k_neighbors_within_radius(
const Sphere& query,
std::size_t k,
OutputIterator output
) const -> std::enable_if_t<supports_neighbor_search, OutputIterator> {
) const -> std::enable_if_t<Orthtree::supports_neighbor_search, OutputIterator> {
CGAL_precondition(k > 0);
Sphere query_sphere = query;

Expand Down Expand Up @@ -1298,13 +1299,13 @@ class Orthtree {
return output;
}

template <typename Result>
template <typename Result, typename Orthtree = Self>
auto nearest_k_neighbors_recursive(
Sphere& search_bounds,
Node_index node,
std::vector<Result>& results,
std::size_t k,
FT epsilon = 0) const -> std::enable_if_t<supports_neighbor_search> {
FT epsilon = 0) const -> std::enable_if_t<Orthtree::supports_neighbor_search> {

// Check whether the node has children
if (is_leaf(node)) {
Expand Down
2 changes: 1 addition & 1 deletion Orthtree/include/CGAL/Orthtree/Split_predicates.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class Maximum_depth {
\ingroup PkgOrthtreeSplitPredicates
\brief A class used to choose when a node should be split depending on the depth and the number of contained elements.
This predicate makes a note split if it contains more than a
This predicate makes a node split if it contains more than a
certain number of items and if its depth is lower than a certain
limit.
Expand Down
23 changes: 16 additions & 7 deletions Orthtree/include/CGAL/Orthtree_traits_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,16 @@ struct Orthtree_traits_base {
using Adjacency = int;
/// @}

auto construct_point_d_object() const {
return [](auto... Args) -> Point_d {
std::initializer_list<FT> args_list{Args...};
return Point_d{static_cast<int>(args_list.size()), args_list.begin(), args_list.end()};
};
struct Construct_point_d {
template <typename ...Args, typename T = std::common_type_t<Args...>>
Point_d operator()(Args ...args) {
std::initializer_list<T> args_list{ args... };
return Point_d{ static_cast<int>(args_list.size()), args_list.begin(), args_list.end() };
}
};

Construct_point_d construct_point_d_object() const {
return Construct_point_d();
}
};

Expand All @@ -115,7 +120,9 @@ struct Orthtree_traits_base<GeomTraits, 2> {
UP
};

auto construct_point_d_object() const {
using Construct_point_d = Point_d(*)(const FT&, const FT&);

Construct_point_d construct_point_d_object() const {
return [](const FT& x, const FT& y) -> Point_d {
return {x, y};
};
Expand Down Expand Up @@ -153,7 +160,9 @@ struct Orthtree_traits_base<GeomTraits, 3> {
RIGHT_TOP_FRONT
};

auto construct_point_d_object() const {
using Construct_point_d = Point_d(*)(const FT&, const FT&, const FT&);

Construct_point_d construct_point_d_object() const {
return [](const FT& x, const FT& y, const FT& z) -> Point_d {
return {x, y, z};
};
Expand Down
52 changes: 40 additions & 12 deletions Orthtree/include/CGAL/Orthtree_traits_point.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,15 @@ struct Orthtree_traits_point : public Orthtree_traits_base<GeomTraits, dimension
using Node_index = typename Base::Node_index;
using Node_data_element = typename std::iterator_traits<typename PointRange::iterator>::value_type;

static_assert(std::is_same_v<typename std::iterator_traits<typename PointRange::iterator>::iterator_category, std::random_access_iterator_tag>);

Orthtree_traits_point(
PointRange& points,
PointMap point_map = PointMap()
) : m_points(points), m_point_map(point_map) {}

using Construct_root_node_bbox = typename Self::Bbox_d(*)();

auto construct_root_node_bbox_object() const {
return [&]() -> typename Self::Bbox_d {

Expand Down Expand Up @@ -152,41 +156,65 @@ struct Orthtree_traits_point : public Orthtree_traits_base<GeomTraits, dimension
};
}

auto construct_root_node_contents_object() const {
return [&]() -> typename Self::Node_data {
return {m_points.begin(), m_points.end()};
};
struct Construct_root_node_contents {
PointRange& m_points;
Construct_root_node_contents(PointRange& points) : m_points(points) {}
typename Self::Node_data operator()() {
return { m_points.begin(), m_points.end() };
}
};

Construct_root_node_contents construct_root_node_contents_object() const {
return Construct_root_node_contents(m_points);
}

auto distribute_node_contents_object() const {
return [&](Node_index n, Tree& tree, const typename Self::Point_d& center) {
struct Distribute_node_contents {
const PointMap m_point_map;
Distribute_node_contents(const PointMap& point_map) : m_point_map(point_map) {}
void operator()(Node_index n, Tree& tree, const typename Self::Point_d& center) {
CGAL_precondition(!tree.is_leaf(n));
reassign_points(tree, m_point_map, n, center, tree.data(n));
};
};

Distribute_node_contents distribute_node_contents_object() const {
return Distribute_node_contents(m_point_map);
}

auto construct_sphere_d_object() const {
using Construct_sphere_d = typename Self::Sphere_d(*)(const typename Self::Point_d&, const typename Self::FT&);

Construct_sphere_d construct_sphere_d_object() const {
return [](const typename Self::Point_d& center, const typename Self::FT& squared_radius) -> typename Self::Sphere_d {
return typename Self::Sphere_d(center, squared_radius);
};
}

auto construct_center_d_object() const {
using Construct_center_d = typename Self::Point_d(*)(const typename Self::Sphere_d&);

Construct_center_d construct_center_d_object() const {
return [](const typename Self::Sphere_d& sphere) -> typename Self::Point_d {
return sphere.center();
};
}

auto compute_squared_radius_d_object() const {
using Compute_squared_radius_d = typename Self::FT(*)(const typename Self::Sphere_d&);

Compute_squared_radius_d compute_squared_radius_d_object() const {
return [](const typename Self::Sphere_d& sphere) -> typename Self::FT {
return sphere.squared_radius();
};
}

auto squared_distance_of_element_object() const {
return [&](const Node_data_element& index, const typename Self::Point_d& point) -> typename Self::FT {
struct Squared_distance_of_element {
const PointMap m_point_map;
Squared_distance_of_element(const PointMap& point_map) : m_point_map(point_map) {}
typename Self::FT operator()(const Node_data_element& index, const typename Self::Point_d& point) {
return CGAL::squared_distance(get(m_point_map, index), point);
};
};
};

Squared_distance_of_element squared_distance_of_element_object() const {
return Squared_distance_of_element(m_point_map);
}

PointRange& m_points;
Expand Down

0 comments on commit 17e6644

Please sign in to comment.