Handle nested holes in convex decomposition (#8442)

Fixes #8379
This commit is contained in:
Sebastien Loriot 2024-09-03 17:23:28 +02:00 committed by GitHub
commit 7425bc4654
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 764 additions and 8 deletions

View File

@ -0,0 +1,53 @@
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Nef_polyhedron_3.h>
#include <CGAL/IO/Nef_polyhedron_iostream_3.h>
#include <CGAL/Nef_3/SNC_indexed_items.h>
#include <CGAL/convex_decomposition_3.h>
#include <list>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron_3;
typedef CGAL::Nef_polyhedron_3<Kernel, CGAL::SNC_indexed_items> Nef_polyhedron_3;
typedef Nef_polyhedron_3::Volume_const_iterator Volume_const_iterator;
std::size_t run(std::string path)
{
Polyhedron_3 input;
std::ifstream(path) >> input;
Nef_polyhedron_3 N(input);
CGAL::convex_decomposition_3(N);
std::list<Polyhedron_3> convex_parts;
Volume_const_iterator ci = ++N.volumes_begin();
for( ; ci != N.volumes_end(); ++ci) {
if(ci->mark()) {
Polyhedron_3 P;
N.convert_inner_shell_to_polyhedron(ci->shells_begin(), P);
convex_parts.push_back(P);
}
}
// int i=0;
for (const Polyhedron_3& P : convex_parts)
{
// std::ofstream("out_"+std::to_string(i++)+".off") << std::setprecision(17) << P;
assert(P.size_of_vertices()!=0);
}
return convex_parts.size();
}
int main()
{
std::size_t val = run("data/in1.off");
assert(val==9);
val = run("data/in2.off");
assert(val==10);
val = run("data/in3.off");
assert(val==13);
val = run("data/in4.off");
assert(val==17);
}

View File

@ -0,0 +1,117 @@
OFF 40 76 0
5 -5 4
5 -5 2
5 5 2
5 5 4
5 -5 -2
5 -5 -4
5 5 -4
5 5 -2
-5 5 4
-5 -5 4
-4 -4 4
-4 4 4
4 4 4
4 -4 4
-5 -5 -4
-5 5 -4
-4 4 -4
-4 -4 -4
4 -4 -4
4 4 -4
-5 5 2
-5 -5 2
-5 -5 -2
-5 5 -2
4 4 2
4 -4 2
4 -4 -2
4 4 -2
-4 4 2
-4 -4 2
-4 4 -2
-4 -4 -2
6 -6 2
6 -6 -2
6 6 -2
6 6 2
-6 6 2
-6 -6 2
-6 -6 -2
-6 6 -2
3 0 2 3
3 2 0 1
3 4 6 7
3 6 4 5
3 3 12 0
3 3 11 12
3 11 8 10
3 8 11 3
3 13 0 12
3 10 0 13
3 10 9 0
3 9 10 8
3 5 18 6
3 5 17 18
3 17 14 16
3 14 17 5
3 19 6 18
3 16 6 19
3 16 15 6
3 15 16 14
3 21 8 20
3 8 21 9
3 14 23 15
3 23 14 22
3 2 8 3
3 8 2 20
3 6 23 7
3 23 6 15
3 21 0 9
3 0 21 1
3 14 4 22
3 4 14 5
3 25 12 24
3 12 25 13
3 18 27 19
3 27 18 26
3 10 28 11
3 28 10 29
3 31 16 30
3 16 31 17
3 28 12 11
3 12 28 24
3 16 27 30
3 27 16 19
3 25 10 13
3 10 25 29
3 18 31 26
3 31 18 17
3 32 34 35
3 34 32 33
3 35 2 32
3 35 20 2
3 20 36 21
3 36 20 35
3 1 32 2
3 21 32 1
3 21 37 32
3 37 21 36
3 28 25 24
3 25 28 29
3 33 4 34
3 33 22 4
3 22 38 23
3 38 22 33
3 7 34 4
3 23 34 7
3 23 39 34
3 39 23 38
3 31 27 26
3 27 31 30
3 38 36 39
3 36 38 37
3 34 36 35
3 36 34 39
3 38 32 37
3 32 38 33

View File

@ -0,0 +1,144 @@
OFF
48 92 0
2 2 2
2 -2 2
-2 2 2
-2 -2 2
-2 2 4
2 2 4
-2 -2 4
2 -2 4
5 -5 4
-4 4 4
5 5 4
4 -4 4
-5 -5 4
-4 -4 -4
5 -5 -4
4 4 -4
-5 5 -4
-5 5 4
5 5 -4
-5 -5 -4
4 4 4
4 -4 -2
-4 -4 4
-4 4 -2
-4 4 -4
4 4 -2
4 -4 -4
6 -6 2
5 5 2
-5 5 2
6 6 2
5 -5 2
-5 -5 2
-6 -6 2
5 -5 -2
-5 -5 -2
6 -6 -2
5 5 -2
-5 5 -2
-6 6 -2
-4 -4 -2
-6 6 2
6 6 -2
-6 -6 -2
-4 -4 2
-4 4 2
4 4 2
4 -4 2
3 2 4 5
3 7 6 3
3 5 7 1
3 6 7 5
3 3 6 4
3 5 0 2
3 3 1 7
3 1 0 5
3 5 4 6
3 4 2 3
3 8 28 10
3 28 8 31
3 34 18 37
3 18 34 14
3 10 20 8
3 10 9 20
3 9 17 22
3 17 9 10
3 11 8 20
3 22 8 11
3 22 12 8
3 12 22 17
3 14 26 18
3 14 13 26
3 13 19 24
3 19 13 14
3 15 18 26
3 24 18 15
3 24 16 18
3 16 24 19
3 32 17 29
3 17 32 12
3 19 38 16
3 38 19 35
3 28 17 10
3 17 28 29
3 18 38 37
3 38 18 16
3 32 8 12
3 8 32 31
3 19 34 35
3 34 19 14
3 47 20 46
3 20 47 11
3 26 25 15
3 25 26 21
3 22 45 9
3 45 22 44
3 40 24 23
3 24 40 13
3 45 20 9
3 20 45 46
3 24 25 23
3 25 24 15
3 47 22 11
3 22 47 44
3 26 40 21
3 40 26 13
3 27 42 30
3 42 27 36
3 30 28 27
3 30 29 28
3 29 41 32
3 41 29 30
3 31 27 28
3 32 27 31
3 32 33 27
3 33 32 41
3 2 0 45
3 1 44 47
3 36 34 42
3 36 35 34
3 35 43 38
3 43 35 36
3 37 42 34
3 38 42 37
3 38 39 42
3 39 38 43
3 40 25 21
3 25 40 23
3 43 41 39
3 41 43 33
3 42 41 30
3 41 42 39
3 43 27 33
3 27 43 36
3 44 1 3
3 44 3 45
3 45 3 2
3 46 45 0
3 46 0 47
3 47 0 1

View File

@ -0,0 +1,180 @@
OFF
60 116 0
1 1 4
1 0.33333333333333337 4
1 -1 4
0.33333333333333337 -1 4
-1 -1 4
-1 0.33333333333333337 4
-1 1 4
0.33333333333333337 1 4
-2 2 2
5 -5 4
-4 4 4
5 5 4
4 -4 4
-5 -5 4
-4 -4 -4
5 -5 -4
4 4 -4
-5 5 -4
-5 5 4
5 5 -4
-5 -5 -4
4 4 4
4 -4 -2
-4 -4 4
-4 4 -2
-4 4 -4
4 4 -2
4 -4 -4
6 -6 2
5 5 2
-5 5 2
6 6 2
5 -5 2
-5 -5 2
-6 -6 2
5 -5 -2
-5 -5 -2
6 -6 -2
5 5 -2
-5 5 -2
-6 6 -2
-4 -4 -2
-6 6 2
6 6 -2
-6 -6 -2
-2 -2 2
-4 -4 2
-4 4 2
4 4 2
4 -4 2
2 -2 2
2 2 2
-2 2 4
2 2 4
2 -2 4
-2 -2 4
1 1 2
1 -1 2
-1 -1 2
-1 1 2
3 8 52 53
3 54 55 45
3 53 54 50
3 0 1 53
3 45 55 52
3 53 51 8
3 45 50 54
3 50 51 53
3 4 5 55
3 52 8 45
3 9 29 11
3 29 9 32
3 35 19 38
3 19 35 15
3 11 21 9
3 11 10 21
3 10 18 23
3 18 10 11
3 12 9 21
3 23 9 12
3 23 13 9
3 13 23 18
3 15 27 19
3 15 14 27
3 14 20 25
3 20 14 15
3 16 19 27
3 25 19 16
3 25 17 19
3 17 25 20
3 33 18 30
3 18 33 13
3 20 39 17
3 39 20 36
3 29 18 11
3 18 29 30
3 19 39 38
3 39 19 17
3 33 9 13
3 9 33 32
3 20 35 36
3 35 20 15
3 49 21 48
3 21 49 12
3 27 26 16
3 26 27 22
3 23 47 10
3 47 23 46
3 41 25 24
3 25 41 14
3 47 21 10
3 21 47 48
3 25 26 24
3 26 25 16
3 49 23 12
3 23 49 46
3 27 41 22
3 41 27 14
3 28 43 31
3 43 28 37
3 31 29 28
3 31 30 29
3 30 42 33
3 42 30 31
3 32 28 29
3 33 28 32
3 33 34 28
3 34 33 42
3 8 51 47
3 50 46 49
3 37 35 43
3 37 36 35
3 36 44 39
3 44 36 37
3 38 43 35
3 39 43 38
3 39 40 43
3 40 39 44
3 41 26 22
3 26 41 24
3 44 42 40
3 42 44 34
3 43 42 31
3 42 43 40
3 44 28 34
3 28 44 37
3 46 50 45
3 46 45 47
3 47 45 8
3 48 47 51
3 48 51 49
3 49 51 50
3 52 55 5
3 52 7 53
3 52 5 6
3 53 7 0
3 52 6 7
3 54 53 1
3 54 2 3
3 54 1 2
3 55 54 3
3 55 3 4
3 58 57 56
3 59 56 7
3 2 57 3
3 0 56 1
3 5 59 6
3 56 59 58
3 57 1 56
3 57 2 1
3 58 5 4
3 7 56 0
3 58 3 57
3 4 3 58
3 59 5 58
3 7 6 59

View File

@ -0,0 +1,180 @@
OFF
60 116 0
1 1 4
1 0.5 4
1 -1 4
0.5 -1 4
-1 -1 4
-1 0.5 4
-1 1 4
0.5 1 4
-2 2 2
5 -5 4
-4 4 4
5 5 4
4 -4 4
-5 -5 4
-4 -4 -4
5 -5 -4
4 4 -4
-5 5 -4
-5 5 4
5 5 -4
-5 -5 -4
4 4 4
4 -4 -2
-4 -4 4
-4 4 -2
-4 4 -4
4 4 -2
4 -4 -4
6 -6 2
5 5 2
-5 5 2
6 6 2
5 -5 2
-5 -5 2
-6 -6 2
5 -5 -2
-5 -5 -2
6 -6 -2
5 5 -2
-5 5 -2
-6 6 -2
-4 -4 -2
-6 6 2
6 6 -2
-6 -6 -2
-2 -2 2
-4 -4 2
-4 4 2
4 4 2
4 -4 2
2 -2 2
2 2 2
-2 2 4
2 2 4
2 -2 4
-2 -2 4
1 1 1
1 -1 1
-1 -1 1
-1 1 1
3 8 52 53
3 54 55 45
3 53 54 50
3 0 1 53
3 45 55 52
3 53 51 8
3 45 50 54
3 50 51 53
3 4 5 55
3 52 8 45
3 9 29 11
3 29 9 32
3 35 19 38
3 19 35 15
3 11 21 9
3 11 10 21
3 10 18 23
3 18 10 11
3 12 9 21
3 23 9 12
3 23 13 9
3 13 23 18
3 15 27 19
3 15 14 27
3 14 20 25
3 20 14 15
3 16 19 27
3 25 19 16
3 25 17 19
3 17 25 20
3 33 18 30
3 18 33 13
3 20 39 17
3 39 20 36
3 29 18 11
3 18 29 30
3 19 39 38
3 39 19 17
3 33 9 13
3 9 33 32
3 20 35 36
3 35 20 15
3 49 21 48
3 21 49 12
3 27 26 16
3 26 27 22
3 23 47 10
3 47 23 46
3 41 25 24
3 25 41 14
3 47 21 10
3 21 47 48
3 25 26 24
3 26 25 16
3 49 23 12
3 23 49 46
3 27 41 22
3 41 27 14
3 28 43 31
3 43 28 37
3 31 29 28
3 31 30 29
3 30 42 33
3 42 30 31
3 32 28 29
3 33 28 32
3 33 34 28
3 34 33 42
3 8 51 47
3 50 46 49
3 37 35 43
3 37 36 35
3 36 44 39
3 44 36 37
3 38 43 35
3 39 43 38
3 39 40 43
3 40 39 44
3 41 26 22
3 26 41 24
3 44 42 40
3 42 44 34
3 43 42 31
3 42 43 40
3 44 28 34
3 28 44 37
3 46 50 45
3 46 45 47
3 47 45 8
3 48 47 51
3 48 51 49
3 49 51 50
3 52 55 5
3 52 7 53
3 52 5 6
3 53 7 0
3 52 6 7
3 54 53 1
3 54 2 3
3 54 1 2
3 55 54 3
3 55 3 4
3 58 57 56
3 59 56 7
3 2 57 3
3 0 56 1
3 5 59 6
3 56 59 58
3 57 1 56
3 57 2 1
3 58 5 4
3 7 56 0
3 58 3 57
3 4 3 58
3 59 5 58
3 7 6 59

View File

@ -904,10 +904,11 @@ protected:
Unique_hash_map<Vertex_const_handle, bool>& omit_vertex;
int nov, nof;
bool hh;
public:
Find_holes(Unique_hash_map<Vertex_const_handle, bool>& omit_vertex_)
: omit_vertex(omit_vertex_), nov(0), nof(0) {}
: omit_vertex(omit_vertex_), nov(0), nof(0), hh(false) {}
void visit(Halffacet_const_handle f) {
++nof;
@ -920,10 +921,11 @@ protected:
CGAL_For_all(sfc, send) {
omit_vertex[sfc->source()->source()] = true;
--nov;
hh=true;
}
} else if(fc.is_shalfloop()) {
SHalfloop_const_handle sl(fc);
omit_vertex[sl->incident_sface()->center_vertex()];
omit_vertex[sl->incident_sface()->center_vertex()] = true;
--nov;
} else
CGAL_error_msg( "wrong handle type");
@ -943,6 +945,63 @@ protected:
int number_of_facets() const {
return nof;
}
bool holes_detected() const {
return hh;
}
};
class Nested_holes {
Unique_hash_map<Vertex_const_handle, bool>& omit_vertex;
int norv, nof;
public:
Nested_holes(Unique_hash_map<Vertex_const_handle, bool>& omit_vertex_)
: omit_vertex(omit_vertex_), norv(0), nof(0) {}
void visit(Halffacet_const_handle f) {
Halffacet_cycle_const_iterator fc = f->facet_cycles_begin();
CGAL_assertion(fc.is_shalfedge());
SHalfedge_around_facet_const_circulator sfc(fc), send(sfc);
bool all_in=true;
bool all_out=true;
CGAL_For_all(sfc, send) {
if (omit_vertex[sfc->source()->source()])
all_in=false;
else
all_out=false;
}
if (!all_in && !all_out)
{
SHalfedge_around_facet_const_circulator sfc(fc), send(sfc);
++nof;
CGAL_For_all(sfc, send) {
if (!omit_vertex[sfc->source()->source()])
{
omit_vertex[sfc->source()->source()]=true;
++norv;
}
}
}
if (all_in)
++nof;
}
void visit(Vertex_const_handle) {}
void visit(SFace_const_handle) {}
void visit(Halfedge_const_handle) {}
void visit(SHalfedge_const_handle) {}
void visit(SHalfloop_const_handle) {}
int number_of_removed_vertices() const {
return norv;
}
int number_of_facets() const {
return nof;
}
};
class Add_vertices {
@ -1001,14 +1060,19 @@ protected:
se = SHalfedge_const_handle(fc);
CGAL_assertion(se!=0);
if(omit_vertex[se->source()->source()]) return;
B.begin_facet();
SHalfedge_around_facet_const_circulator hc_start(se);
SHalfedge_around_facet_const_circulator hc_end(hc_start);
std::vector<std::size_t> vids;
CGAL_For_all(hc_start,hc_end) {
CGAL_NEF_TRACEN(" add vertex " << hc_start->source()->center_vertex()->point());
B.add_vertex_to_facet(VI[hc_start->source()->center_vertex()]);
if (omit_vertex[hc_start->source()->center_vertex()])
{
std::cout << "issue with " << se->source()->source()->point() << "\n";
return;
}
vids.push_back(VI[hc_start->source()->center_vertex()]);
}
B.end_facet();
B.add_facet (vids.begin(), vids.end());
}
void visit(SFace_const_handle) {}
@ -1033,11 +1097,29 @@ protected:
Polyhedron_incremental_builder_3<HDS> B(hds, true);
// first mark vertices of holes of each halffacet as omitted.
Find_holes F(omit_vertex);
scd.visit_shell_objects(sf, F);
std::size_t nb_v = F.number_of_vertices();
std::size_t nb_f = F.number_of_facets();
B.begin_surface(F.number_of_vertices(),
F.number_of_facets(),
// then if a halffacet contains a vertex marked as omitted, all its vertices
// must be marked as such
if (F.holes_detected())
{
while(true)
{
Nested_holes F2(omit_vertex);
scd.visit_shell_objects(sf, F2);
if (F2.number_of_removed_vertices()==0) break;
nb_v-=F2.number_of_removed_vertices();
nb_f=F2.number_of_facets();
}
}
B.begin_surface(nb_v,
nb_f,
F.number_of_vertices()+F.number_of_facets()-2);
Add_vertices A(B,omit_vertex, VI);