Skip to content

Commit 6867f9d

Browse files
authored
Merge pull request #66 from sloriot/autoref_news
New for autoref and snap
2 parents 62f92f1 + f28c9c5 commit 6867f9d

8 files changed

Lines changed: 184 additions & 0 deletions
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
---
2+
layout: post
3+
title: "New in CGAL: Fixing Self-Intersections in Triangle Soups using Snap Rounding"
4+
description: ""
5+
category:
6+
tags: [""]
7+
---
8+
{% include JB/setup %}
9+
10+
<h3><a href="https://geometryfactory.com/who-we-are/">Sébastien Loriot</a> & <a href="https://geometryfactory.com/who-we-are/">Léo Valque</a></h3>
11+
<h4><a href="https://geometryfactory.com/">GeometryFactory</a></h4>
12+
13+
<br>
14+
<p><b>The second half of the work described in this post (snap rounding strategies)
15+
will be presented at <a href="https://sgp2025.my.canva.site/">SGP 2025</a> in Bilbao (June 30 - July 4, 2025)</b></p>
16+
17+
<br>
18+
<p>Self-intersections in triangle meshes are a common source of issues in geometry processing, simulation,
19+
and 3D printing. Such defects can arise in various ways: poor design, approximate conversions,
20+
faulty outputs of mesh processing algorithms, and so on.
21+
A particularly interesting case in the latter category is <em>Boolean operations</em>, as these
22+
turn out to be both a source of self-intersections and, as we will see,
23+
a solution to them as well.
24+
</p>
25+
26+
<div style="text-align:center;">
27+
<a href="../../../../images/996816-self-intersections.png"><img src="../../../../images/996816-self-intersections.png" style="max-width:95%"/></a>
28+
<br><small>The model <tt>996816</tt> from the Thingi10k dataset is riddled with thousands of self-intersections</small>
29+
</div>
30+
<br>
31+
32+
<p>
33+
Over the years, CGAL has developed its own algorithms for Boolean operations,
34+
evolving from general and robust methods to more specialized and efficient solutions
35+
(an exhaustive history can be found at the end of this post). To perform robustly,
36+
these methods all rely on exact constructions, meaning the use of arbitrary precision numbers
37+
(see also the page <a href="https://www.cgal.org/exact.html">The Exact Computation Paradigm </a>).
38+
Unfortunately, when results are brought back to the real, double-based world,
39+
self-intersections may appear.</p>
40+
41+
<p>Resolving self-intersections in triangle meshes can be tackled in different ways (vertex
42+
displacement, complete remeshing, etc.), but these solutions have limitations in terms of scope,
43+
computational requirements, or robustness on large datasets.</p>
44+
45+
<p>In CGAL 6.1, we introduce a new method for resolving self-intersections in triangle meshes
46+
and triangle soups, combining a novel Boolean operation function called "autorefinement"
47+
and a new iterative snap rounding strategy. <b>This approach was evaluated on
48+
the <a href="https://ten-thousand-models.appspot.com/">Thingi10k dataset</a>
49+
(nearly 10,000 models including for non-manifold and degenerate inputs) and produced intersection-free
50+
outputs for all cases, thus providing a practical way to address self-intersections in meshes
51+
for a wide range of applications</b>.</p>
52+
53+
<br>
54+
<h3>First half of the Solution: Autorefinement of Triangle Soups</h3>
55+
56+
<p>A question often asked by users was whether CGAL's Boolean operations
57+
(see <a href="https://doc.cgal.org/latest/Polygon_mesh_processing/index.html#title16">Corefinement
58+
and Boolean Operations"</a>) could be used to resolve self-intersections in triangle meshes, especially in solids.
59+
This led us to modify the corefinement code to create an <em>autorefinement</em> version,
60+
which refines triangles from the same mesh that are intersecting along segments not in the input.
61+
Using those intersection edges, it is now possible to apply a self-union to resolve the self-intersections
62+
of the solid.</p>
63+
64+
<br>
65+
<div style="text-align:center;">
66+
<a href="../../../../images/cylinder_autorefine.png"><img src="../../../../images/cylinder_autorefine.png" style="max-width:95%"/></a>
67+
<br><small>Left: A triangle mesh generated by sweeping a circle along a spiral curve;
68+
Right: A triangle mesh free from self-intersection bounding the same volume as in the left picture;
69+
On the bottom, we see the intersection curve of a plane with the triangle meshes.</small>
70+
</div>
71+
<br>
72+
73+
<p>Autorefinement is now available in a new function, <a href="https://doc.cgal.org/6.0/Polygon_mesh_processing/group__PMP__corefinement__grp.html#gaec85370aa0b2acc0919e5f8406cfb74c">CGAL::Polygon_mesh_processing::autorefine_triangle_soup()</a>.
74+
This function takes as input a triangle soup (that is, a range of points and a range of triples of integers representing
75+
triangles using point indices), and resolves all intersections among the triangles by refining the triangles
76+
so that no triangle intersects except along a shared edge or a shared vertex. The function operates on a triangle soup
77+
and not a triangle mesh as to handle arbitrarily complex inputs (including degenerate faces
78+
and non-manifold configurations), and also to represent non-manifold output. Indeed,
79+
even configurations as simple as two triangles whose intersection is a segment will result in
80+
four triangles sharing the same edge after refining them with their intersection.
81+
</p>
82+
83+
<p>
84+
To demonstrate the robustness and runtime efficiency of the function, we ran it over
85+
all 10,000 models from the Thingi10k repository.
86+
The computer used for the benchmark runs x86_64 Debian GNU/Linux 6.1.0-12-amd64 and features
87+
a 2016 Intel(R) Xeon(R) CPU E5-1650 v4 @ 3.60GHz with 6 threads/12 hyperthreads.
88+
The memory values are the maximum resident set size (given using the <tt>/usr/bin/time</tt> command).
89+
</p>
90+
91+
<div style="text-align:center;">
92+
<a href="../../../../images/autoref_runtime.png"><img src="../../../../images/autoref_runtime.png" style="max-width:95%"/></a>
93+
</div>
94+
<div style="text-align:center;">
95+
<a href="../../../../images/autoref_mem.png"><img src="../../../../images/autoref_mem.png" style="max-width:95%"/></a>
96+
</div>
97+
98+
<br>
99+
<h3>Second half of the Solution: A New Snap Rounding Strategy</h3>
100+
101+
<p>Naturally, the new autorefinement function does not suffice by itself to resolve self-intersections
102+
as it suffers from the same issues as other Boolean operations: it must be performed using
103+
exact computations, but once newly created vertices are rounded back to doubles, self-intersections
104+
may appear: out the 9997 valid input files, only 9425 were free from self-intersection
105+
after autorefine and naive rounding to double. Therefore, we are left with 572 files
106+
still featuring self-intersections.</p>
107+
108+
<div style="text-align:center;">
109+
<a href="../../../../images/triangle_snap_error.png"><img src="../../../../images/triangle_snap_error.png" style="max-width:95%"/></a>
110+
<br><small>Illustration of rounding issues in self-intersection resolutions. The red grid represent the grid of floating point numbers.
111+
Points with floating points coordinates must lie on a vertex of the grid. <b>From left to right:</b> input triangles with floating point
112+
numbers coordinates; Resolution of intersections of triangles using arbitrary precision; Rounding new intersection points to the nearest
113+
vertex on the grid: even if the intersection is solved with arbitrary precision, the rounding using floating point coordinates
114+
induces new intersections that cannot be solved by naively iterating the process (in addition to creating new degenerate faces).
115+
</small>
116+
</div>
117+
<br>
118+
119+
<p>The second part of our solution is a novel snap rounding strategy: based on the work of Lazard and Valque [1],
120+
the main idea behind the method is a loop that rounds vertex coordinates of triangles involved
121+
in self-intersections to integers (up to a scaling factor), eliminates degenerate
122+
elements, and resolves self-intersections again, until all self-intersections are resolved
123+
or a user-defined maximum number of iterations is reached. Even if there is no theoretical guarantee
124+
for successful termination, it performs well in practice: using the default values of the parameters for this method,
125+
all the models but one could be rounded with one call. The single remaining model, the infamous model
126+
<tt>996816</tt> (see image at the top of the post) required a few more iterations.</p>
127+
128+
<div style="text-align:center;">
129+
<a href="../../../../images/996816-no-self-intersections.png"><img src="../../../../images/996816-no-self-intersections.png" style="max-width:95%"/></a>
130+
<br><small>The model <tt>996816</tt> no longer intersects and a reasonable number of new vertices was needed: the input has 75k vertices and 170k faces, and the output has 100k vertices and 245k faces.</small>
131+
</div>
132+
<br>
133+
134+
<p>From an API point of view, the function <code>CGAL::Polygon_mesh_processing::autorefine_triangle_soup()</code>
135+
has a parameter <code>apply_iterative_snap_rounding()</code> called to the autorefine
136+
function to activate a snapping strategy in order to avoid self-intersections produced while rounding the coordinates to double.</p>
137+
138+
<br>
139+
<h3>Status</h3>
140+
141+
<p>The new function is already integrated in CGAL's master branch on the
142+
<a href="https://github.com/CGAL/cgal/">CGAL GitHub repository</a> and
143+
will be officially released in the upcoming version of CGAL, CGAL 6.1, scheduled for summer 2025.</p>
144+
145+
<i class="bi bi-book"></i>
146+
<a href="https://doc.cgal.org/6.1/Polygon_mesh_processing/group__PMP__corefinement__grp.html#gaec85370aa0b2acc0919e5f8406cfb74c">Documentation of the function <em>CGAL::Polygon_mesh_processing::autorefine_triangle_soup()</em></a>
147+
<br>
148+
<i class="bi bi-arrow-down-circle"></i>
149+
<a href="https://github.com/CGAL/cgal/tree/master">CGAL master branch on GitHub</a>
150+
<br><br>
151+
152+
<h3>Bibliography</h3>
153+
154+
[1] Sylvain Lazard and Leo Valque. Removing self-intersections in 3D meshes while preserving floating-point coordinates. Computer Graphics Forum. Vol. XX. No. X. 2025.
155+
156+
<br>
157+
<h3>Bonus: History of 3D Boolean Operations in CGAL</h3>
158+
159+
<p>In December 2004, CGAL 3.1 was released with the package <a href="https://doc.cgal.org/latest/Nef_3">3D Boolean Operations on Nef Polyhedra</a>
160+
It provided a robust way to compute Boolean operations on Nef Polyhedra. In particular, it enables users to perform some Boolean operations
161+
on solids bounded by surface meshes, but also on models with non-manifold features and 1D features. Even today, this package is probably
162+
the only solution in the open source world to allow this kind of operations. Unfortunately, all this genericity comes at a price. Indeed, the algorithm
163+
relies on maintaining an arrangement of circles on a sphere at each vertex of the Nef Polyhedra in order to enable those operations.
164+
This representation also requires that intersection points are strictly coplanar with the polygonal faces they describe, implying that
165+
a Kernel providing exact constructions is mandatory.
166+
</p>
167+
168+
<p>As this genericity is not required for all applications, we decided to work on an alternative method which would be restricted to solids
169+
bounded by triangle meshes, and such that the output is manifold. In October 2012, we released an undocumented version of a new code
170+
based on corefinement of triangle meshes. With feedback from early adopters, we officially released with CGAL 4.10 in May 2017
171+
a rewrite of the original 3D Boolean operations through corefinement (see the manual entry <a href="https://doc.cgal.org/latest/Polygon_mesh_processing/index.html#title16">"Corefinement and Boolean Operations"</a>).
172+
One of the key features of this code is the ability to compute several types of Boolean operations in one run (union and intersection,
173+
for example), and the possibility to store the result in a new mesh or directly update one of the input meshes to avoid recopying the entire
174+
mesh if only a small portion is affected. When it comes to robustness, exact constructions are used under the hood to guarantee an output
175+
with the correct topology. To demonstrate the robustness and speed of the method, we posted a <a href="https://www.linkedin.com/pulse/benchmarking-mesh-union-using-cgal-libigl-sebastien-loriot/">benchmark</a>
176+
on the <a href="https://ten-thousand-models.appspot.com/">Thingi10k data set</a> testing the code on thousands of models.
177+
</p>
178+
179+
<p>In CGAL 4.11 (April 2018), we released an undocumented version of the autorefinement code. The code was, however, limited to
180+
meshes where only pairs of triangles were intersecting along the same segment (as an underlying requirement of the code is
181+
a pairwise intersection). In order to officially release that code, we needed to overcome this limitation.
182+
In 2023, we found the time to start a new implementation from-scratch of autorefinement for triangle soups,
183+
which was then peer reviewed in 2024 and officially released with CGAL 6.0 in September 2024.
184+
</p>
168 KB
Loading
349 KB
Loading

images/autoref_mem.png

60.5 KB
Loading

images/autoref_runtime.png

87.5 KB
Loading

images/cylinder_autorefine.png

273 KB
Loading

images/triangle_si.png

41.9 KB
Loading

images/triangle_snap_error.png

103 KB
Loading

0 commit comments

Comments
 (0)