Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
9db7374
Add API for convex hull do-intersect
sloriot Apr 29, 2022
35622e2
raw import of code from @horasio and plug into CGAL's function
sloriot May 4, 2022
6c2cfda
add missing license include
sloriot May 4, 2022
bc7b057
use later version provided by email
sloriot May 4, 2022
326ce48
remove code not used
sloriot May 4, 2022
7d29e6a
remove hardcoded float
sloriot May 4, 2022
5ea4af6
fix include directives
sloriot May 4, 2022
1e5ea04
fix warning
sloriot May 4, 2022
a131617
fix include directive
sloriot May 5, 2022
8825d4d
Comment on the computation of support points
LeoValque Mar 25, 2025
ada5f5a
Make it compile
LeoValque Mar 25, 2025
d0a7b1e
Remove use of normalized() (and thus sqrt)
LeoValque Mar 25, 2025
d430aa0
Correct previous commit to compile
LeoValque Mar 25, 2025
e8332ca
Replace local Vec3 by Vector_3 of CGAL
LeoValque Mar 25, 2025
456471f
Remove Vec3 and Vec4 since there are now unused
LeoValque Mar 25, 2025
3c24c2f
Replace predicate by exact ones
LeoValque Mar 25, 2025
4974195
correct abs missing in LInf_normalize
LeoValque Mar 25, 2025
73072cf
Add ch3_test_do_intersect.cpp
LeoValque Mar 26, 2025
9258622
add degenerate test and solved a bug of a floating point exception wh…
LeoValque Mar 26, 2025
cb3644c
more test
LeoValque Mar 26, 2025
09b77bd
Traits class and naive filter predicate
LeoValque Mar 28, 2025
ba0c52f
Externalize the extreme_point to the rest of the algorithm for prepar…
LeoValque Mar 28, 2025
28a3d11
Add a random test on tetrahedron
LeoValque Mar 28, 2025
6dc972a
Add benchmark for ch3_do_intersect
LeoValque Mar 28, 2025
7196253
avoid as much normalization as possible for performance
LeoValque Mar 28, 2025
cc4443c
delete differenceCoversZeroInDIr since now unused
LeoValque Mar 28, 2025
73d0b0f
More numeric stabilities and less filter failure
LeoValque Apr 11, 2025
c9bd4ad
add bench do_intersect_ch3
LeoValque Apr 15, 2025
5e6dacb
clean bench ch3_do_intersect
LeoValque Apr 17, 2025
f029c9d
a correctly filtered implementation :-)
LeoValque Apr 17, 2025
23677cf
Convex hull with hierarchy and its bench
LeoValque May 11, 2025
1f58595
Compile and execute with all kind of input
LeoValque May 12, 2025
6119759
Replace goto with break and a boolean variable
LeoValque May 12, 2025
8d7ab64
more test
LeoValque May 12, 2025
afbc76b
even more test
LeoValque May 13, 2025
2a4931d
rename Spherical_disjoint into DO_intersect
LeoValque May 13, 2025
7cccdb8
supress RangeConverter
LeoValque May 13, 2025
68f9945
Automatic deduction of the Kernel
LeoValque May 14, 2025
ab89dda
clearer benchmark
LeoValque May 14, 2025
1d66036
make_do_intersect_traits_with_point_maps to deduce PointMap template
LeoValque May 14, 2025
e28cbe6
construct hierarchy directly from a mesh
LeoValque May 14, 2025
55730ec
Modif after review of Andreas
LeoValque May 21, 2025
f37e10f
solve conflict after merge master
LeoValque May 21, 2025
9f466fd
Range deduction and construct_vector_38object instead of Vector_3
LeoValque May 21, 2025
5c2b851
Documentation of do_intersect and convex_hull_hierarchy (examples are…
LeoValque May 22, 2025
f190342
Apply suggestions from code reviewfff
LeoValque May 22, 2025
6c8086a
User Reference first draft
LeoValque May 22, 2025
1003a75
Apply suggestions from code review
LeoValque May 22, 2025
6440569
typos
afabri May 23, 2025
2a0ef6d
typos
afabri May 23, 2025
5033217
Capitalize file name
afabri May 23, 2025
edb9f09
typos
afabri May 23, 2025
46410f5
move function in another group
afabri May 23, 2025
7a270fc
Capitalize file name
afabri May 23, 2025
f1fd6d7
Merge local with distant
LeoValque May 23, 2025
a5d9b99
Reparation of the tests
LeoValque May 23, 2025
ae71a53
change API according to the new documentation
LeoValque Jun 2, 2025
9847321
more test
LeoValque Jun 2, 2025
f1ffee0
clean do_intersect code
LeoValque Jun 3, 2025
f20ff8e
Small changed in documentation
LeoValque Jun 4, 2025
0e6293e
Add GJK separation_distance
LeoValque Aug 14, 2025
a69db16
benchmark
LeoValque Aug 14, 2025
548c73e
solve conflict
LeoValque Aug 14, 2025
b0739cc
Switch to EPECK for separation_distance for robust execution
LeoValque Aug 14, 2025
2d1f617
separate do_intersect and separation_distance in two distinct files
LeoValque Aug 14, 2025
27dc01f
correct Copyright
LeoValque Aug 14, 2025
5b070de
reorgaise dir_to_origin
LeoValque Aug 18, 2025
d235d7c
Clean code of distance.h
LeoValque Aug 18, 2025
6e38e3b
modify bench_ch3_do_intersevt
LeoValque Aug 18, 2025
70c3e43
Remove warning with point_map in Convex_hull_hierarchy
LeoValque Aug 20, 2025
dc383b4
Remove segfault triggered by using reference after modification of th…
LeoValque Aug 20, 2025
ddd5f20
Fix doc bug
LeoValque Aug 20, 2025
5cbfd7f
Remove unused using
LeoValque Aug 20, 2025
bc0e88d
Add class GetGeomTraitsFromConvex to deduce GT from different input
LeoValque Aug 21, 2025
132bee2
Repair example of do_intersect_ch3
LeoValque Aug 21, 2025
76643c3
Correct compilation error specific to windows
LeoValque Aug 21, 2025
30cc5b3
warnings
sloriot Aug 21, 2025
dc2e6b6
DOUBLE name is reserved in MSVC compiler
LeoValque Aug 22, 2025
b6f9b22
Respect naming conventions in ch3_test_do_intersect
LeoValque Aug 22, 2025
3adfbbe
update dependencies
sloriot Aug 26, 2025
099ac7a
Merge branch 'master' into CH3-do_intersect
LeoValque Dec 9, 2025
fc09b0e
Apply suggestions from code review
LeoValque Dec 9, 2025
588ccbc
First path of suggestions of the review
LeoValque Dec 9, 2025
66847f6
Merge branch 'CH3-do_intersect' of github.com:sloriot/cgal into CH3-d…
LeoValque Dec 9, 2025
a809550
Convex_hull_hierarchy compatible with all MutableFaceGraph
LeoValque Jan 26, 2026
7b04675
Clean Convex_hull_hierarchy
LeoValque Jan 26, 2026
5e73552
Adapt documentation according to the review
LeoValque Jan 27, 2026
c3a7749
Rename intersections.h to do_intersect.h
LeoValque Jan 27, 2026
e4bda07
Move GetGeomTraitsFromConvex in a helpers file
LeoValque Jan 27, 2026
b53594a
Correct error in Doxyfile.in
LeoValque Jan 27, 2026
1723214
Add missing include in helpers.h
LeoValque Jan 27, 2026
934ffbd
Apply Suggestions from the review
LeoValque Jan 27, 2026
ea21881
Add more information on the return of Point_3
LeoValque Jan 27, 2026
6b9b1cc
Update benchmark
LeoValque Jan 29, 2026
504e422
Complete reorganisation of the PR and modification of the API
LeoValque Jan 30, 2026
534997c
Small fix in doc
LeoValque Feb 1, 2026
60fc608
Add extreme_point_3 in DOXYFILE_IN
LeoValque Feb 1, 2026
8086edc
Fix rare error of an empty level coming from unlucky rng
LeoValque Feb 1, 2026
e93e4d0
Fix rare error of an empty level coming from unlucky rng
LeoValque Feb 1, 2026
03d58c3
Merge branch 'CH3-do_intersect' of github.com:sloriot/cgal into CH3-d…
LeoValque Feb 1, 2026
14c8c6f
Apply suggestions from code review
LeoValque Feb 2, 2026
ac669f8
Update Convex_hull_3/doc/Convex_hull_3/Convex_hull_3.txt
LeoValque Feb 2, 2026
c4c0602
implementation history
LeoValque Feb 2, 2026
8cd9c04
Merge branch 'CH3-do_intersect' of github.com:sloriot/cgal into CH3-d…
LeoValque Feb 2, 2026
a279801
Clarify tie case of extreme_point_3
LeoValque Feb 2, 2026
5ab77c0
CHANGES.md
LeoValque Feb 2, 2026
5718854
Apply suggestions from code review
LeoValque Feb 2, 2026
25cfde7
Merge branch 'CH3-do_intersect' of github.com:sloriot/cgal into CH3-d…
LeoValque Feb 2, 2026
cc1bc34
Apply suggestions from the review
LeoValque Feb 5, 2026
4bc7f69
Add test for compare_scalar_product and fix the testsuite
LeoValque Feb 6, 2026
8334059
Apply suggestions from code review
LeoValque Feb 6, 2026
882ccbf
Add suggestions from the review
LeoValque Feb 6, 2026
086cb48
fix name
sloriot Feb 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Convex_hull_3/benchmark/Convex_hull_3/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Created by the script cgal_create_cmake_script
# This is the CMake script for compiling a CGAL application.

cmake_minimum_required(VERSION 3.1...3.22)
project(Bench_convex_hull_3)

find_package(CGAL REQUIRED)

include_directories(BEFORE "include")

# create a target per cppfile
file(
GLOB cppfiles
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
foreach(cppfile ${cppfiles})
create_single_source_cgal_program("${cppfile}")
endforeach()
356 changes: 356 additions & 0 deletions Convex_hull_3/benchmark/Convex_hull_3/bench_ch3_do_intersect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,356 @@
#define CGAL_PROFILE_CONVEX_HULL_DO_INTERSECT

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>

#include <CGAL/Surface_mesh.h>
#include <CGAL/Extreme_points_traits_adapter_3.h>
#include <CGAL/convex_hull_3.h>
#include <CGAL/Convex_hull_hierarchy_3.h>
#include <CGAL/Convex_hull_3/do_intersect.h>
#include <CGAL/Convex_hull_3/distance.h>

#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>
#include <CGAL/IO/polygon_soup_io.h>

#include <CGAL/optimal_bounding_box.h>

#include <CGAL/Random.h>
#include <CGAL/Timer.h>
#include <CGAL/Real_timer.h>

#include <vector>
#include <fstream>

template <typename K>
struct Test
{
typedef typename K::FT FT;
typedef typename K::Point_3 P;
typedef typename K::Segment_3 S;
typedef typename K::Vector_3 V;
typedef typename K::Ray_3 R;
typedef typename K::Line_3 L;
typedef typename K::Triangle_3 T;
typedef typename K::Plane_3 Pl;
typedef typename K::Tetrahedron_3 Tet;
typedef typename K::Iso_cuboid_3 Cub;
typedef typename std::vector<P> PR;

private:
CGAL::Random& r;
double m = 0, M = 1;
const double PI=3.14159265358979323846;

public:
Test(CGAL::Random& r) : r(r) { }

private:
P random_point() const
{
return P(FT(r.get_double(m, M)), FT(r.get_double(m, M)), FT(r.get_double(m, M)));
}

P random_sphere_point() const
{
FT a=r.get_double(0,2*PI);
FT b=r.get_double(-PI/2,PI/2);
return P( std::cos(a)*std::cos(b), std::sin(a)*std::cos(b), std::sin(b));
}

void test_Tet(std::vector< PR > &a, std::vector< PR > &b)
{
std::cout << "Do intersect of package Intersection_3" << std::endl;
CGAL::Real_timer t;
t.start();
for(std::size_t i=0; i<a.size(); ++i)
CGAL::do_intersect(Tet(a[i][0], a[i][1], a[i][2], a[i][3]), Tet(b[i][0], b[i][1], b[i][2], b[i][3]));
t.stop();
std::cout << t.time() << " sec" << std::endl;

std::cout << "Do intersect of Convex_hull" << std::endl;
t.reset();
t.start();
for(std::size_t i=0; i<a.size(); ++i)
CGAL::Convex_hull_3::do_intersect(a[i], b[i]);
t.stop();
std::cout << t.time() << " sec" << std::endl;

std::cout << "Separation distance of Convex_hull" << std::endl;
t.reset();
t.start();
for(std::size_t i=0; i<a.size(); ++i)
CGAL::Convex_hull_3::experimental::separation_distance(a[i], b[i]);
t.stop();
std::cout << t.time() << " sec" << std::endl << std::endl;
}

void Tet_tet(int N)
{
std::cout << "Tetrahedron likely to intersect" << std::endl;
std::vector<PR> a;
std::vector<PR> b;
for(int i=0; i<N; ++i)
a.push_back(PR({random_point(), random_point(), random_point(), random_point()}));
for(int i=0; i<N; ++i)
b.push_back(PR({random_point(), random_point(), random_point(), random_point()}));
test_Tet(a, b);
}

void Tet_mirror(int N)
{
std::cout << "Tetrahedrons closed" << std::endl;
std::vector<PR> a;
std::vector<PR> b;
for(int i=0; i<N; ++i)
{
P p0 = random_point();
if(p0.x() > p0.y())
p0 = P(-p0.x(), -p0.y(), -p0.z());
P p1 = random_point();
if(p1.x() > p1.y())
p1 = P(-p1.x(), -p1.y(), -p1.z());
P p2 = random_point();
if(p2.x() > p2.y())
p2 = P(-p2.x(), -p2.y(), -p2.z());
P p3 = random_point();
if(p3.x() > p3.y())
p3 = P(-p3.x(), -p3.y(), -p3.z());

P q0 = random_point();
if(q0.x() < q0.y())
q0 = P(-q0.x(), -q0.y(), -q0.z());
P q1 = random_point();
if(q1.x() < q1.y())
q1 = P(-q1.x(), -q1.y(), -q1.z());
P q2 = random_point();
if(q2.x() < q2.y())
q2 = P(-q2.x(), -q2.y(), -q2.z());
P q3 = random_point();
if(q3.x() < q3.y())
q3 = P(-q3.x(), -q3.y(), -q3.z());

a.push_back(PR({p0,p1,p2,p3}));
b.push_back(PR({q0,q1,q2,q3}));
}
test_Tet(a, b);
}

void Tet_stretched(int N)
{
std::cout << "Tetrahedrons streched" << std::endl;
std::vector<PR> a;
std::vector<PR> b;
for(int i=0; i<N; ++i)
{
P p0 = random_point()+V(-1,1,0);
P p1 = random_point()+V(-1,1,0);
P p2 = random_point()+V(1,-1,0);
P p3 = random_point()+V(1,-1,0);

P q0 = random_point()+V(-1,-1,0);
P q1 = random_point()+V(-1,-1,0);
P q2 = random_point()+V(1,1,0);
P q3 = random_point()+V(1,1,0);

a.push_back(PR({p0,p1,p2,p3}));
b.push_back(PR({q0,q1,q2,q3}));
}
test_Tet(a, b);
}

void Tet_shift(int N)
{
std::cout << "Tetrahedrons that do not intersect" << std::endl;
std::vector<PR> a;
std::vector<PR> b;
for(int i=0; i<N; ++i)
{
P p0 = random_point();
P p1 = random_point();
P p2 = random_point();
P p3 = random_point();

P q0 = random_point()+V(1,1,1);
P q1 = random_point()+V(1,1,1);
P q2 = random_point()+V(1,1,1);
P q3 = random_point()+V(1,1,1);

a.push_back(PR({p0,p1,p2,p3}));
b.push_back(PR({q0,q1,q2,q3}));
}
test_Tet(a, b);

}

void Test_sphere(int N, int M)
{
std::cout << "Sphere of size " << M << std::endl;
CGAL::Real_timer t;
std::vector< std::vector<P> > points_ranges;
std::vector< CGAL::Surface_mesh<P> > hulls;
std::vector< CGAL::Convex_hull_hierarchy_3< CGAL::Surface_mesh<P> > > hulls_hierarchy;

double nb_tests=double(N*(N-1)/2);

for(int i=0; i<N; ++i)
{
std::vector<P> sp;
V vec( P(0,0,0), random_sphere_point());
vec*=1.2;
for(int i=0; i<M; ++i)
sp.push_back(random_sphere_point()+vec);
points_ranges.push_back(std::move(sp));
}

std::cout << "Compute convex hulls" << std::endl;
t.start();
for(int i=0; i<N; ++i)
{
CGAL::Surface_mesh<P> hull;
CGAL::convex_hull_3(points_ranges[i].begin(), points_ranges[i].end(), hull);
hulls.push_back(std::move(hull));
}
t.stop();
std::cout << " " << t.time()/N << " sec" << std::endl;
t.reset();

std::cout << "Construct hierarchy of convex hulls" << std::endl;
t.start();
for(int i=0; i<N; ++i)
hulls_hierarchy.emplace_back(hulls[i], CGAL::parameters::compute_convex_hull(false));
t.stop();
double time_build = t.time()/N;
std::cout << " " << t.time()/N << " sec" << std::endl;
t.reset();

std::cout << "Do intersect with RangePoints" << std::endl;
nb_visited=0;
t.start();
for(int i=0; i<N; ++i)
for(int j=i+1; j<N; ++j)
CGAL::Convex_hull_3::do_intersect(points_ranges[i], points_ranges[j]);
t.stop();

std::cout << " " << t.time()/nb_tests << " sec per test" << std::endl;
t.reset();

std::cout << "Do intersect with Hulls" << std::endl;
nb_visited=0;
t.start();
for(int i=0; i<N; ++i)
for(int j=i+1; j<N; ++j)
CGAL::Convex_hull_3::do_intersect(hulls[i], hulls[j]);
t.stop();
double time_without_hierarchy = t.time()/nb_tests;
std::cout << " " << t.time()/nb_tests << " sec per test" << std::endl;
t.reset();

std::cout << "Do intersect with Hierarchical Hulls" << std::endl;
nb_visited=0;
t.start();
for(int i=0; i<N; ++i)
for(int j=i+1; j<N; ++j)
CGAL::Convex_hull_3::do_intersect(hulls_hierarchy[i], hulls_hierarchy[j]);
t.stop();

std::cout << " " << t.time()/nb_tests << " sec per test" << std::endl;
std::cout << " " << time_build / (time_without_hierarchy - t.time()/nb_tests) << " ratio tests/build";
t.reset();
std::cout << std::endl;
}

public:
void run()
{
std::cout << "Kernel: " << typeid(K).name() << std::endl;
Tet_tet(1000);
Tet_mirror(1000);
Tet_shift(1000);
Tet_stretched(1000);

Test_sphere(1000, 40);
Test_sphere(1000, 100);
Test_sphere(1000, 350);
Test_sphere(1000, 1000);
Test_sphere(300, 3500);
Test_sphere(50, 10000);
Test_sphere(25, 35000);
Test_sphere(25, 100000);
Test_sphere(10, 350000);
Test_sphere(10, 1000000);
std::cout << std::endl;
}
};

template <typename K>
void bench_on_data(const std::string &f1, const std::string &f2){
typedef typename K::Point_3 Point_3;
typedef CGAL::Surface_mesh<Point_3> Mesh;

std::vector<typename K::Point_3> pts1, pts2;
std::vector<boost::container::small_vector<std::size_t, 3>> trs1, trs2;
if (!CGAL::IO::read_polygon_soup(f1, pts1, trs1))
{
std::cerr << "Cannot read " << f1 << "\n";
}
if (!CGAL::IO::read_polygon_soup(f2, pts2, trs2))
{
std::cerr << "Cannot read " << f2 << "\n";
}

CGAL::Real_timer t;
t.start();
Mesh hull1, hull2;
CGAL::convex_hull_3(pts1.begin(), pts1.end(), hull1);
CGAL::convex_hull_3(pts2.begin(), pts2.end(), hull2);
t.stop();
std::cout << "Computing convex hulls: " << t.time() << " sec" << std::endl;
std::cout << "Convex hull size:" << vertices(hull1).size() << ", " << vertices(hull2).size() << "\n" << std::endl;
t.reset();

t.start();
CGAL::Convex_hull_3::do_intersect(hull1, hull2);
t.stop();
std::cout << "Do intersect: " << t.time() << " sec\n" << std::endl;
t.reset();

t.start();
std::array<Point_3, 8> obb1, obb2;
CGAL::oriented_bounding_box(hull1, obb1, CGAL::parameters::use_convex_hull(false));
CGAL::oriented_bounding_box(hull2, obb2, CGAL::parameters::use_convex_hull(false));
t.stop();
std::cout << "Computing Obbs: " << t.time() << " sec\n" << std::endl;
t.reset();

t.start();
CGAL::Convex_hull_3::do_intersect(obb1, obb2);
t.stop();
std::cout << "Do intersect with Obbs: " << t.time() << " sec\n" << std::endl;
}

int main(int argc, char** argv)
{
// std::cout.precision(17);
// std::cerr.precision(17);

std::cout << "3D Distance tests" << std::endl;

CGAL::Random rp;
CGAL::Random r(argc==1?rp.get_seed():std::stoi(argv[1]));
// std::cout << "random seed = " << r.get_seed() << std::endl;

// Test<CGAL::Simple_cartesian<double> >(r).run();
Test<CGAL::Exact_predicates_inexact_constructions_kernel>(r).run();
// Test<CGAL::Exact_predicates_exact_constructions_kernel>(r).run();

const std::string f1 = (argc>2) ? argv[2] : CGAL::data_file_path("meshes/elephant.off");
const std::string f2 = (argc>3) ? argv[3] : CGAL::data_file_path("meshes/sphere.off");
// bench_on_data<CGAL::Exact_predicates_inexact_constructions_kernel>(f1,f2);

std::cout << "Done!" << std::endl;

return EXIT_SUCCESS;
}
6 changes: 3 additions & 3 deletions Convex_hull_3/doc/Convex_hull_3/CGAL/convex_hull_3.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ then the default traits class used is `Convex_hull_traits_3<R>`, and `R` otherwi
*/
template <class InputRange, class OutputIterator, class Traits>
OutputIterator
extreme_points_3(InputRange range,
OutputIterator out,
const Traits& traits);
extreme_points_3(const InputRange &range,
OutputIterator out,
const Traits& traits);



Expand Down
Loading