mirror of https://github.com/CGAL/cgal
Test AABBTree move semantics
This commit is contained in:
parent
587c77774c
commit
2b9c2c1634
|
|
@ -36,14 +36,12 @@ static void BM_Intersections(benchmark::State& state)
|
|||
Point_3 q(-0.5, 0.04, 0.06);
|
||||
|
||||
Tree tree{mesh.faces_begin(), mesh.faces_end(), mesh};
|
||||
tree.build();
|
||||
tree.accelerate_distance_queries();
|
||||
|
||||
Segment segment_query(p, q);
|
||||
|
||||
for (auto _ : state)
|
||||
{
|
||||
benchmark::DoNotOptimize([&]() {
|
||||
tree.accelerate_distance_queries();
|
||||
tree.number_of_intersected_primitives(segment_query);
|
||||
Point_3 point_query(2.0, 2.0, 2.0);
|
||||
Point_3 closest = tree.closest_point(point_query);
|
||||
|
|
|
|||
|
|
@ -632,13 +632,14 @@ public:
|
|||
template <typename Tr>
|
||||
typename AABB_tree<Tr>::Self& AABB_tree<Tr>::operator=(Self&& tree) noexcept
|
||||
{
|
||||
m_traits = std::move(tree.traits);
|
||||
m_traits = std::move(tree.m_traits);
|
||||
m_primitives = std::move(tree.m_primitives);
|
||||
m_p_nodes = std::move(tree.m_p_nodes);
|
||||
m_p_search_tree = std::move(tree.m_p_search_tree);
|
||||
m_search_tree_constructed = std::exchange(tree.m_search_tree_constructed, false);
|
||||
m_default_search_tree_constructed = std::exchange(tree.m_default_search_tree_constructed, true);
|
||||
m_need_build = std::exchange(tree.m_need_build, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Tr>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,193 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <utility>
|
||||
|
||||
#include <CGAL/AABB_face_graph_triangle_primitive.h>
|
||||
#include <CGAL/AABB_halfedge_graph_segment_primitive.h>
|
||||
#include <CGAL/AABB_segment_primitive.h>
|
||||
#include <CGAL/AABB_traits.h>
|
||||
#include <CGAL/AABB_tree.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Polyhedron_3.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Surface_mesh.h>
|
||||
#include <CGAL/assertions.h>
|
||||
#include <fstream>
|
||||
|
||||
template <int test_number> auto create_tree();
|
||||
template <int test_number, typename T> void init_tree(T &tree) {}
|
||||
template <int test_number, typename T> bool test_tree(T &tree);
|
||||
template <int test_number> class TestUtils;
|
||||
|
||||
// test 0 is from "aabb_test_singleton_tree"
|
||||
template <> struct TestUtils<0> {
|
||||
typedef CGAL::Simple_cartesian<double> K;
|
||||
typedef K::FT FT;
|
||||
typedef K::Point_3 Point;
|
||||
typedef K::Plane_3 Plane;
|
||||
typedef K::Segment_3 Segment;
|
||||
typedef K::Triangle_3 Triangle;
|
||||
typedef std::vector<Segment>::iterator Iterator;
|
||||
typedef CGAL::AABB_segment_primitive<K, Iterator> Primitive;
|
||||
typedef CGAL::AABB_traits<K, Primitive> Traits;
|
||||
typedef CGAL::AABB_tree<Traits> Tree;
|
||||
|
||||
Point a = {1.0, 0.0, 0.0};
|
||||
Point b = {0.0, 1.0, 0.0};
|
||||
Point c = {0.0, 0.0, 1.0};
|
||||
Point d = {0.0, 0.0, 0.0};
|
||||
std::vector<Segment> segments = {Segment(Point(0, 0, 0), Point(2, 2, 2))};
|
||||
};
|
||||
|
||||
template <> auto create_tree<0>() {
|
||||
using T = TestUtils<0>;
|
||||
T utils;
|
||||
return T::Tree(utils.segments.begin(), utils.segments.end());
|
||||
}
|
||||
using Test0Param = decltype(create_tree<0>());
|
||||
template <> bool test_tree<0, Test0Param>(Test0Param &tree) {
|
||||
using T = TestUtils<0>;
|
||||
T utils;
|
||||
|
||||
T::Plane plane_query(utils.a, utils.b, utils.d);
|
||||
T::Triangle triangle_query(utils.a, utils.b, utils.c);
|
||||
|
||||
// Test calls to all functions
|
||||
CGAL::Emptyset_iterator devnull;
|
||||
tree.all_intersections(triangle_query, devnull);
|
||||
tree.all_intersected_primitives(triangle_query, devnull);
|
||||
assert(tree.any_intersected_primitive(triangle_query));
|
||||
assert(tree.any_intersection(triangle_query));
|
||||
const CGAL::Bbox_3 bbox = tree.bbox();
|
||||
assert(bbox == CGAL::Bbox_3(0, 0, 0, 2, 2, 2));
|
||||
tree.clear();
|
||||
tree.insert(utils.segments.begin(), utils.segments.end());
|
||||
tree.build();
|
||||
assert(tree.closest_point(T::Point(-0.1, -0.1, -0.1)) == T::Point(0, 0, 0));
|
||||
assert(tree.closest_point(T::Point(-0.1, -0.1, -0.1), T::Point(0, 0, 0)) ==
|
||||
T::Point(0, 0, 0));
|
||||
assert(tree.closest_point_and_primitive(T::Point(-0.1, -0.1, -0.1)).second ==
|
||||
utils.segments.begin());
|
||||
assert(tree.do_intersect(plane_query) == true);
|
||||
assert(tree.do_intersect(triangle_query) == true);
|
||||
assert(!tree.empty());
|
||||
assert(tree.size() == 1);
|
||||
tree.clear();
|
||||
assert(tree.size() == 0);
|
||||
tree.insert(utils.segments.begin(), utils.segments.end());
|
||||
assert(tree.size() == 1);
|
||||
assert(tree.number_of_intersected_primitives(plane_query) == 1);
|
||||
tree.rebuild(utils.segments.begin(), utils.segments.end());
|
||||
assert(tree.size() == 1);
|
||||
assert(tree.number_of_intersected_primitives(triangle_query) == 1);
|
||||
assert(tree.squared_distance(T::Point(0, 0, 0)) == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
// test 1 is from "aabb_test_all_intersected_primitives"
|
||||
template <> struct TestUtils<1> {
|
||||
typedef CGAL::Epick K;
|
||||
typedef K::FT FT;
|
||||
typedef K::Point_3 Point;
|
||||
typedef K::Vector_3 Vector;
|
||||
typedef K::Segment_3 Segment;
|
||||
typedef K::Ray_3 Ray;
|
||||
typedef CGAL::Surface_mesh<CGAL::Point_3<CGAL::Epick>> Mesh;
|
||||
typedef CGAL::AABB_halfedge_graph_segment_primitive<Mesh, CGAL::Default,
|
||||
CGAL::Tag_false>
|
||||
S_Primitive;
|
||||
typedef CGAL::AABB_face_graph_triangle_primitive<Mesh, CGAL::Default,
|
||||
CGAL::Tag_false>
|
||||
T_Primitive;
|
||||
typedef CGAL::AABB_traits<K, T_Primitive> T_Traits;
|
||||
typedef CGAL::AABB_traits<K, S_Primitive> S_Traits;
|
||||
typedef CGAL::AABB_tree<T_Traits> T_Tree;
|
||||
typedef CGAL::AABB_tree<S_Traits> S_Tree;
|
||||
typedef T_Tree::Primitive_id T_Primitive_id;
|
||||
typedef S_Tree::Primitive_id S_Primitive_id;
|
||||
};
|
||||
|
||||
template <> auto create_tree<1>() {
|
||||
using T = TestUtils<1>;
|
||||
|
||||
static CGAL::Surface_mesh<CGAL::Point_3<CGAL::Epick>> m1 = {};
|
||||
static CGAL::Surface_mesh<CGAL::Point_3<CGAL::Epick>> m2 = {};
|
||||
static bool mesh_loaded = false;
|
||||
if (!mesh_loaded) {
|
||||
std::ifstream in("data/cube.off");
|
||||
assert(in);
|
||||
in >> m1;
|
||||
in.close();
|
||||
in.open("data/tetrahedron.off");
|
||||
assert(in);
|
||||
in >> m2;
|
||||
in.close();
|
||||
mesh_loaded = true;
|
||||
}
|
||||
return std::make_pair(T::T_Tree{faces(m1).first, faces(m1).second, m1},
|
||||
T::S_Tree{edges(m2).first, edges(m2).second, m2});
|
||||
}
|
||||
using Test1Param = decltype(create_tree<1>());
|
||||
template <> void init_tree<1, Test1Param>(Test1Param &trees) {
|
||||
trees.first.build();
|
||||
trees.second.build();
|
||||
}
|
||||
template <> bool test_tree<1, Test1Param>(Test1Param &trees) {
|
||||
using T = TestUtils<1>;
|
||||
|
||||
auto &cube_tree = trees.first;
|
||||
auto &tet_tree = trees.second;
|
||||
|
||||
std::list<T::T_Tree::Primitive::Id> t_primitives;
|
||||
std::list<T::S_Tree::Primitive::Id> s_primitives;
|
||||
cube_tree.all_intersected_primitives(tet_tree,
|
||||
std::back_inserter(t_primitives));
|
||||
CGAL_assertion(t_primitives.size() == 6);
|
||||
tet_tree.all_intersected_primitives(cube_tree,
|
||||
std::back_inserter(s_primitives));
|
||||
CGAL_assertion(s_primitives.size() == 6);
|
||||
CGAL_assertion(tet_tree.do_intersect(cube_tree));
|
||||
CGAL_assertion(cube_tree.do_intersect(tet_tree));
|
||||
|
||||
std::vector<T::T_Tree::Primitive::Id> all_primitives;
|
||||
cube_tree.all_intersected_primitives(tet_tree,
|
||||
std::back_inserter(all_primitives));
|
||||
bool found_f5 = false;
|
||||
for (auto prim : all_primitives) {
|
||||
if ((int)prim.first == 5)
|
||||
found_f5 = true;
|
||||
}
|
||||
CGAL_assertion(found_f5);
|
||||
CGAL_USE(found_f5);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <int test_number> bool run_test() {
|
||||
// create_tree should return prvalue for guaranteed copy elision
|
||||
auto tree_1 = create_tree<test_number>();
|
||||
init_tree<test_number>(tree_1);
|
||||
auto tree_2 = create_tree<test_number>();
|
||||
init_tree<test_number>(tree_2);
|
||||
auto tree_3 = create_tree<test_number>();
|
||||
init_tree<test_number>(tree_3);
|
||||
|
||||
decltype(tree_1) tree_ctor{std::move(tree_2)};
|
||||
decltype(tree_1) tree_assig{};
|
||||
tree_assig = std::move(tree_3);
|
||||
|
||||
bool normal = test_tree<test_number>(tree_1);
|
||||
bool move_ctor = test_tree<test_number>(tree_ctor);
|
||||
bool move_ass =
|
||||
test_tree<test_number>(tree_assig); // test move assignment operator
|
||||
|
||||
if (!normal)
|
||||
std::cout << "Test " << test_number << "failed on the original tree\n";
|
||||
if (!move_ctor)
|
||||
std::cout << "Test " << test_number << "failed on move constructed tree\n";
|
||||
if (!move_ass)
|
||||
std::cout << "Test " << test_number << "failed on move assigned tree\n";
|
||||
return normal && move_ctor && move_ass;
|
||||
}
|
||||
|
||||
int main() { return (run_test<0>() && run_test<1>()) ? 0 : 1; }
|
||||
Loading…
Reference in New Issue