Skip to content

Commit 6c8a889

Browse files
committed
Second patch of suggestion from the review
1 parent 38b4eb9 commit 6c8a889

9 files changed

Lines changed: 168 additions & 27 deletions

File tree

AABB_tree/benchmark/AABB_tree/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ project(AABB_traits_benchmark)
66

77
find_package(CGAL REQUIRED OPTIONAL_COMPONENTS Core)
88

9-
create_single_source_cgal_program("test.cpp")
9+
create_single_source_cgal_program("test_AABB_tree.cpp")
1010
create_single_source_cgal_program("tree_construction.cpp")
11+
create_single_source_cgal_program("knot_generation.cpp")
12+
create_single_source_cgal_program("tree_queries.cpp")
1113

1214
# google benchmark
1315
find_package(benchmark QUIET)
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
2+
#include <cmath>
3+
#include <fstream>
4+
#include <iostream>
5+
#include <vector>
6+
7+
#include <CGAL/Simple_cartesian.h>
8+
#include <CGAL/IO/polygon_soup_io.h>
9+
10+
using Kernel = CGAL::Simple_cartesian<double>;
11+
using Point = Kernel::Point_3;
12+
using Vector = Kernel::Vector_3;
13+
using Triangle = std::array<int, 3>;
14+
15+
int main(int argc, char* argv[])
16+
{
17+
const std::string filename = argc > 1 ? argv[1] : "knot.off";
18+
19+
const int p = argc > 2 ? std::atoi(argv[2]) : 1; // Nb of major turns
20+
const int q = argc > 3 ? std::atoi(argv[3]) : 6; // Nb of knot turns
21+
22+
const double R = argc > 4 ? std::atof(argv[4]) : 2.0; // major radius
23+
const double r = argc > 5 ? std::atof(argv[5]) : 0.9; // knot radius
24+
const double tube_radius = argc > 6 ? std::atof(argv[6]) : 0.4;
25+
26+
const int tubular_segments = argc > 7 ? std::atoi(argv[7]) : 120;
27+
const int radial_segments = argc > 8 ? std::atoi(argv[8]) : 60;
28+
29+
std::vector<Point> vertices;
30+
std::vector<Triangle> faces;
31+
32+
// Generate knot polyline
33+
auto knot = [&](double t){
34+
double cq = std::cos(q * t);
35+
double sq = std::sin(q * t);
36+
double factor = R + r * cq;
37+
return Point(factor * std::cos(p * t),
38+
factor * std::sin(p * t),
39+
r * sq);
40+
};
41+
auto knot_derivative = [&](double t){
42+
double cq = std::cos(q * t);
43+
double sq = std::sin(q * t);
44+
double cp = std::cos(p * t);
45+
double sp = std::sin(p * t);
46+
47+
double factor = R + r*cq;
48+
double dfactor = -r*q*sq;
49+
50+
return Vector(dfactor*cp - factor*p*sp,
51+
dfactor*sp + factor*p*cp,
52+
r*q*cq);
53+
};
54+
55+
const double dt = 2.0 * M_PI / tubular_segments;
56+
const double dr = 2.0 * M_PI / radial_segments;
57+
58+
// A normal to the knot axis
59+
Vector N(1,0,0);
60+
for(int i=0; i<tubular_segments; ++i)
61+
{
62+
double t = i * dt;
63+
64+
// knot point and its tangent
65+
Point C = knot(t);
66+
Vector T = knot_derivative(t);
67+
// Compute bases of the plane on C
68+
Vector B = CGAL::cross_product(N, T);
69+
N = -CGAL::cross_product(B, T);
70+
N /= CGAL::approximate_sqrt(N.squared_length());
71+
B /= CGAL::approximate_sqrt(B.squared_length());
72+
73+
for(int j=0; j<radial_segments; ++j){
74+
double phi = j * dr;
75+
vertices.push_back(C + tube_radius*(std::cos(phi)*N + std::sin(phi)*B));
76+
}
77+
}
78+
79+
auto idx = [&](int i, int j){
80+
i %= tubular_segments;
81+
j %= radial_segments;
82+
return i * radial_segments + j;
83+
};
84+
85+
for(int i=0; i<tubular_segments-1; ++i)
86+
for(int j=0; j<radial_segments; ++j){
87+
int v00 = idx(i , j );
88+
int v10 = idx(i+1, j );
89+
int v01 = idx(i , j+1);
90+
int v11 = idx(i+1, j+1);
91+
92+
faces.push_back({v00,v10,v11});
93+
faces.push_back({v00,v11,v01});
94+
}
95+
96+
// To avoid a twist, we compute the offset that minimize the distance between a point at tubular index N-1 and tubular index 0
97+
int n = tubular_segments-1;
98+
int offset = 0;
99+
double min = CGAL::squared_distance(vertices[idx(n, 0)], vertices[idx(0,0)]);
100+
for(int j=1; j<radial_segments; ++j){
101+
double sq = CGAL::squared_distance(vertices[idx(n, 0)], vertices[idx(0,j)]);
102+
if(min >sq){
103+
min = sq;
104+
offset = j;
105+
}
106+
}
107+
for(int j=0; j<radial_segments; ++j){
108+
int v00 = idx(n, j );
109+
int v10 = idx(0, j+offset);
110+
int v01 = idx(n, j+1);
111+
int v11 = idx(0, j+offset+1);
112+
113+
faces.push_back({v00,v10,v11});
114+
faces.push_back({v00,v11,v01});
115+
}
116+
117+
CGAL::IO::write_polygon_soup(filename, vertices, faces);
118+
119+
return 0;
120+
}

AABB_tree/benchmark/AABB_tree/test_AABB_tree.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <CGAL/Polygon_mesh_processing/transform.h>
99
#include <CGAL/Rigid_triangle_mesh_collision_detection.h>
1010
#include <CGAL/Side_of_triangle_mesh.h>
11+
#include <CGAL/Real_timer.h>
1112

1213
#include <fstream>
1314
#include <sstream>
@@ -157,17 +158,16 @@ int main(int argc, const char** argv)
157158
std::string path = (argc>2)?argv[2]: CGAL::data_file_path("meshes/handle.off");
158159

159160
std::cout<< k<<" steps in "<<path<<std::endl;
161+
CGAL::Real_timer t;
160162
int nb_inter(0), nb_no_inter(0), nb_include(0),
161163
naive_inter(0), naive_no_inter(0), naive_include(0);
162-
auto start = std::chrono::steady_clock::now();
163-
naive_test(k, path, naive_inter, naive_no_inter, naive_include);
164-
auto end = std::chrono::steady_clock::now();
164+
t.start();
165+
naive_test(k, path, naive_inter, naive_no_inter, naive_include);
165166
std::cout<<"Naive test : "<<naive_inter<<" collisions, "<<naive_include<<" inclusions, "<<naive_no_inter<<" no collision, calculated in "
166-
<<std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms." << std::endl;
167-
start = std::chrono::steady_clock::now();
167+
<< t.time() << " ms." << std::endl;
168+
t.stop(); t.reset(); t.start();
168169
test_no_collision(k, path,nb_inter, nb_no_inter, nb_include);
169-
end = std::chrono::steady_clock::now();
170170
std::cout<<"With transform_traits: "<<nb_inter<<" collisions, "<<nb_include<<" inclusions, "<<nb_no_inter<<" no collision, calculated in "
171-
<<std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms." << std::endl;
171+
<< t.time() << " ms." << std::endl;
172172
return 0;
173173
}

AABB_tree/doc/AABB_tree/Doxyfile.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - Fast Intersection and Distance Comput
55
EXTRACT_ALL = false
66
HIDE_UNDOC_MEMBERS = true
77
HIDE_UNDOC_CLASSES = true
8+
9+
INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/AABB_trees/intersection.h

AABB_tree/include/CGAL/AABB_tree.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -691,12 +691,15 @@ namespace CGAL {
691691
return std::addressof(m_nodes[0]);
692692
}
693693

694-
// Still documented but now unused by build() function
695-
Node& new_node()
694+
#ifndef CGAL_NO_DEPRECATED_CODE
695+
// Now unused by build() function
696+
/// @private
697+
CGAL_DEPRECATED Node& new_node()
696698
{
697699
m_nodes.emplace_back();
698700
return m_nodes.back();
699701
}
702+
#endif // CGAL_NO_DEPRECATED_CODE
700703
private:
701704
const Primitive& singleton_data() const {
702705
CGAL_assertion(size() == 1);

AABB_tree/include/CGAL/AABB_tree/internal/AABB_two_trees_traversal_traits.h

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class Two_trees_listing_intersecting_primitives_traits
4949
}
5050
WrapOutputIterator& operator*(){ return *this; }
5151
WrapOutputIterator& operator++(){ ++out; return *this; }
52-
WrapOutputIterator& operator++(int){ auto tmp = *this; ++out; return tmp; }
52+
WrapOutputIterator& operator++(int){ /*auto tmp = *this;*/ ++out; return *this; }
5353
WrapOutputIterator& operator+(int d){ out += d; return *this; }
5454
};
5555

@@ -66,10 +66,7 @@ class Two_trees_listing_intersecting_primitives_traits
6666
template<typename Node_A, typename Node_B>
6767
bool prefer_A_for_next_step(const Node_A& node_a, const Node_B& node_b, const std::size_t&, const std::size_t&) const {
6868
#if 1
69-
auto sq_diag = [](const Bbox_3 &b){
70-
return (b.xmax()-b.xmin())*(b.xmax()-b.xmin()) + (b.ymax()-b.ymin())*(b.ymax()-b.ymin()) + (b.zmax()-b.zmin())*(b.zmax()-b.zmin());
71-
};
72-
return sq_diag(node_a.bbox()) > sq_diag(node_b.bbox());
69+
return node_a.bbox().squared_diagonal_length() > node_b.bbox().squared_diagonal_length();
7370
#else
7471
return false;
7572
#endif
@@ -141,15 +138,12 @@ class Listing_self_intersecting_primitives_traits
141138
// If true, the next step of traversal continue on A, if false, the next step of traversal is on B
142139
template<typename Node_A, typename Node_B>
143140
bool prefer_A_for_next_step(const Node_A& node_a, const Node_B& node_b, const std::size_t&, const std::size_t&) const {
144-
auto sq_diag = [](const Bbox_3 &b){
145-
return (b.xmax()-b.xmin())*(b.xmax()-b.xmin()) + (b.ymax()-b.ymin())*(b.ymax()-b.ymin()) + (b.zmax()-b.zmin())*(b.zmax()-b.zmin());
146-
};
147-
return sq_diag(node_a.bbox()) > sq_diag(node_b.bbox());
141+
return node_a.bbox().squared_diagonal_length() > node_b.bbox().squared_diagonal_length();
148142
}
149143

150144
void intersection(const Primitive& primitive1, const Node& node2, std::size_t nb_primitives_2)
151145
{
152-
// TODO Since we are in a symetrical case, maybe we can ignore this call
146+
// TODO Since we are in a symmetric case, maybe we can ignore this call
153147
using WrapIterator = WrapOutputIterator<true, typename Primitive::Id>;
154148
WrapIterator wrap_out(primitive1.id(), out);
155149
Listing_distinct_primitive_traits<AABBTraits, WrapIterator> traits(wrap_out, m_traits);
@@ -191,14 +185,11 @@ class Two_trees_do_intersect_traits
191185
return !m_is_found;
192186
}
193187

194-
// If true, the next step of traversal continue on A, if false, the next step of traversal is on B
188+
// If true, the next step of traversal continues on A, if false, the next step of traversal is on B
195189
template<typename Node_A, typename Node_B>
196190
bool prefer_A_for_next_step(const Node_A& node_a, const Node_B& node_b, const std::size_t&, const std::size_t&) const {
197191
#if 1
198-
auto sq_diag = [](const Bbox_3 &b){
199-
return (b.xmax()-b.xmin())*(b.xmax()-b.xmin()) + (b.ymax()-b.ymin())*(b.ymax()-b.ymin()) + (b.zmax()-b.zmin())*(b.zmax()-b.zmin());
200-
};
201-
return sq_diag(node_a.bbox()) > sq_diag(node_b.bbox());
192+
return node_a.bbox().squared_diagonal_length() > node_b.bbox().squared_diagonal_length();
202193
#else
203194
return false;
204195
#endif

AABB_tree/test/AABB_tree/aabb_intersection_test.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
#include <CGAL/AABB_traits_3.h>
1212
#include <CGAL/AABB_tree.h>
1313

14-
#include <CGAL/Polyhedron_3.h>
15-
1614
using K = CGAL::Exact_predicates_inexact_constructions_kernel;
1715

1816
void test(const std::string fname1, const std::string fname2, std::size_t nb_inter)

Kernel_23/doc/Kernel_23/CGAL/Bbox_3.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,26 @@ double ymax() const;
8787
*/
8888
double zmax() const;
8989

90+
/*!
91+
92+
*/
93+
double x_span() const;
94+
95+
/*!
96+
97+
*/
98+
double y_span() const;
99+
100+
/*!
101+
102+
*/
103+
double z_span() const;
104+
105+
/*!
106+
107+
*/
108+
double squared_diagonal_length() const;
109+
90110
/*!
91111
Returns `xmin()` if `i==0` or `ymin()` if `i==1`
92112
or `zmin()` if `i==2`.

Kernel_23/include/CGAL/Bbox_3.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class Bbox_3
6666
double x_span() const;
6767
double y_span() const;
6868
double z_span() const;
69+
double squared_diagonal_length() const;
6970

7071
inline double min BOOST_PREVENT_MACRO_SUBSTITUTION (int i) const;
7172
inline double max BOOST_PREVENT_MACRO_SUBSTITUTION (int i) const;
@@ -122,6 +123,10 @@ inline double Bbox_3::z_span() const {
122123
return zmax() - zmin();
123124
}
124125

126+
inline double Bbox_3::squared_diagonal_length() const {
127+
return x_span()*x_span() + y_span()*y_span() + z_span()*z_span();
128+
}
129+
125130
inline
126131
bool
127132
Bbox_3::operator==(const Bbox_3 &b) const

0 commit comments

Comments
 (0)