Merge branch 'master' into CGAL-Prepare_CHANGES.md_6.1-GF

This commit is contained in:
Mael 2025-05-09 14:18:57 +02:00 committed by GitHub
commit 6efa5d932a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 900 additions and 251 deletions

2
.gitattributes vendored
View File

@ -16,7 +16,7 @@
*.py text *.py text
*.xml text *.xml text
*.js text *.js text
*.hmtl text *.html text
*.bib text *.bib text
*.css text *.css text
*.ui text *.ui text

View File

@ -106,7 +106,7 @@ it is used only for distance computations.
\warning Having degenerate primitives in the AABB-tree is not recommended as the underlying \warning Having degenerate primitives in the AABB-tree is not recommended as the underlying
predicates and constructions of the traits class might not be able to handle them. predicates and constructions of the traits class might not be able to handle them.
For example if one is using `CGAL::AABB_traits` with a Kernel from \cgal, For example if one is using `CGAL::AABB_traits` with a Kernel from \cgal,
having degenerate triangles or segments in the AABB-tree will results in an undefined having degenerate triangles or segments in the AABB-tree will result in an undefined
behavior or a crash. behavior or a crash.
\section aabb_tree_examples Examples \section aabb_tree_examples Examples
@ -197,9 +197,9 @@ The AABB tree example folder contains three examples of trees
constructed with custom primitives. In \ref AABB_tree/AABB_custom_example.cpp "AABB_custom_example.cpp" constructed with custom primitives. In \ref AABB_tree/AABB_custom_example.cpp "AABB_custom_example.cpp"
the primitive contains triangles which are defined by three pointers the primitive contains triangles which are defined by three pointers
to custom points. In \ref AABB_tree/AABB_custom_triangle_soup_example.cpp "AABB_custom_triangle_soup_example.cpp" all input to custom points. In \ref AABB_tree/AABB_custom_triangle_soup_example.cpp "AABB_custom_triangle_soup_example.cpp" all input
triangles are stored into a single array so as to form a triangle triangles are stored into a single array as to form a triangle
soup. The primitive internally uses a `boost::iterator_adaptor` so as soup. The primitive internally uses a `boost::iterator_adaptor`
to provide the three functions `AABBPrimitive::id()`, `AABBPrimitive::datum()`, as to provide the three functions `AABBPrimitive::id()`, `AABBPrimitive::datum()`,
and `AABBPrimitive::reference_point()`) required by the primitive concept. In and `AABBPrimitive::reference_point()`) required by the primitive concept. In
\ref AABB_tree/AABB_custom_indexed_triangle_set_example.cpp "AABB_custom_indexed_triangle_set_example.cpp" the input is an indexed \ref AABB_tree/AABB_custom_indexed_triangle_set_example.cpp "AABB_custom_indexed_triangle_set_example.cpp" the input is an indexed
triangle set stored through two arrays: one array of points and one triangle set stored through two arrays: one array of points and one
@ -213,7 +213,7 @@ contains a set of polyhedron triangle facets. We measure the tree
construction time, the memory occupancy and the number of queries per construction time, the memory occupancy and the number of queries per
second for a variety of intersection and distance queries. The machine second for a variety of intersection and distance queries. The machine
used is a PC running Windows XP64 with an Intel CPU Core2 Extreme used is a PC running Windows XP64 with an Intel CPU Core2 Extreme
clocked at 3.06 GHz with 4GB of RAM. By default the kernel used is clocked at 3.06 GHz with 4GB of RAM. By default, the kernel used is
`Simple_cartesian<double>` (the fastest in our experiments). The `Simple_cartesian<double>` (the fastest in our experiments). The
program has been compiled with Visual C++ 2005 compiler with the O2 program has been compiled with Visual C++ 2005 compiler with the O2
option which maximizes speed. option which maximizes speed.
@ -244,7 +244,7 @@ internal KD-tree). It increases to approximately 150 bytes per
primitive when constructing the internal KD-tree with one reference primitive when constructing the internal KD-tree with one reference
point per primitive (the default mode when calling the function point per primitive (the default mode when calling the function
`AABB_tree::accelerate_distance_queries()`). Note that the polyhedron `AABB_tree::accelerate_distance_queries()`). Note that the polyhedron
facet primitive primitive stores only one facet handle as primitive id facet primitive stores only one facet handle as primitive id
and computes on the fly a 3D triangle from the facet handle stored and computes on the fly a 3D triangle from the facet handle stored
internally. When explicitly storing a 3D triangle in the primitive the internally. When explicitly storing a 3D triangle in the primitive the
tree occupies approximately 140 bytes per primitive instead of 60 tree occupies approximately 140 bytes per primitive instead of 60
@ -340,7 +340,7 @@ inside the bounding box.
The experiments described above are neither exhaustive nor conclusive The experiments described above are neither exhaustive nor conclusive
as we have chosen one specific case where the input primitives are the as we have chosen one specific case where the input primitives are the
facets of a triangle surface polyhedron. Nevertheless we now provide facets of a triangle surface polyhedron. Nevertheless, we now provide
some general observations and advises about how to put the AABB tree some general observations and advises about how to put the AABB tree
to use with satisfactory performances. While the tree construction to use with satisfactory performances. While the tree construction
times and memory occupancy do not fluctuate much in our experiments times and memory occupancy do not fluctuate much in our experiments

View File

@ -15,7 +15,7 @@ As a consequence types representing polynomials, algebraic extensions and
finite fields play a more important role in related implementations. finite fields play a more important role in related implementations.
This package has been introduced to stay abreast of these changes. This package has been introduced to stay abreast of these changes.
Since in particular polynomials must be supported by the introduced framework Since in particular polynomials must be supported by the introduced framework
the package avoids the term <I>number type</I>. Instead the package distinguishes the package avoids the term <I>number type</I>. Instead, the package distinguishes
between the <I>algebraic structure</I> of a type and whether a type is embeddable on between the <I>algebraic structure</I> of a type and whether a type is embeddable on
the real axis, or <I>real embeddable</I> for short. the real axis, or <I>real embeddable</I> for short.
Moreover, the package introduces the notion of <I>interoperable</I> types which Moreover, the package introduces the notion of <I>interoperable</I> types which
@ -45,11 +45,11 @@ the operations 'sqrt', 'k-th root' and 'real root of a polynomial',
respectively. The concept `IntegralDomainWithoutDivision` also respectively. The concept `IntegralDomainWithoutDivision` also
corresponds to integral domains in the algebraic sense, the corresponds to integral domains in the algebraic sense, the
distinction results from the fact that some implementations of distinction results from the fact that some implementations of
integral domains lack the (algebraically always well defined) integral integral domains lack the (algebraically always well-defined) integral
division. division.
Note that `Field` refines `IntegralDomain`. This is because Note that `Field` refines `IntegralDomain`. This is because
most ring-theoretic notions like greatest common divisors become trivial for most ring-theoretic notions like greatest common divisors become trivial for
`Field`s. Hence we see `Field` as a refinement of `Field`s. Hence, we see `Field` as a refinement of
`IntegralDomain` and not as a `IntegralDomain` and not as a
refinement of one of the more advanced ring concepts. refinement of one of the more advanced ring concepts.
If an algorithm wants to rely on gcd or remainder computation, it is trying If an algorithm wants to rely on gcd or remainder computation, it is trying
@ -119,7 +119,7 @@ Conversely, types as `leda_real` or `CORE::Expr` are exact but sensitive
to numerical issues due to the internal use of multi precision floating point to numerical issues due to the internal use of multi precision floating point
arithmetic. We expect that `Is_numerical_sensitive` is used for dispatching arithmetic. We expect that `Is_numerical_sensitive` is used for dispatching
of algorithms, while `Is_exact` is useful to enable assertions that can be of algorithms, while `Is_exact` is useful to enable assertions that can be
check for exact types only. checked for exact types only.
Tags are very useful to dispatch between alternative implementations. Tags are very useful to dispatch between alternative implementations.
The following example illustrates a dispatch for `Field`s using overloaded The following example illustrates a dispatch for `Field`s using overloaded
@ -134,7 +134,7 @@ category tags reflect the algebraic structure hierarchy.
Most number types represent some subset of the real numbers. From those types Most number types represent some subset of the real numbers. From those types
we expect functionality to compute the sign, absolute value or double we expect functionality to compute the sign, absolute value or double
approximations. In particular we can expect an order on such a type that approximations. In particular, we can expect an order on such a type that
reflects the order along the real axis. reflects the order along the real axis.
All these properties are gathered in the concept `::RealEmbeddable`. All these properties are gathered in the concept `::RealEmbeddable`.
The concept is orthogonal to the algebraic structure concepts, The concept is orthogonal to the algebraic structure concepts,
@ -190,12 +190,12 @@ In general mixed operations are provided by overloaded operators and
functions or just via implicit constructor calls. functions or just via implicit constructor calls.
This level of interoperability is reflected by the concept This level of interoperability is reflected by the concept
`ImplicitInteroperable`. However, within template code the result type, `ImplicitInteroperable`. However, within template code the result type,
or so called coercion type, of a mixed arithmetic operation may be unclear. or so-called coercion type, of a mixed arithmetic operation may be unclear.
Therefore, the package introduces `Coercion_traits` Therefore, the package introduces `Coercion_traits`
giving access to the coercion type via \link Coercion_traits::Type `Coercion_traits<A,B>::Type` \endlink giving access to the coercion type via \link Coercion_traits::Type `Coercion_traits<A,B>::Type` \endlink
for two interoperable types `A` and `B`. for two interoperable types `A` and `B`.
Some trivial example are `int` and `double` with coercion type double Some trivial examples are `int` and `double` with coercion type double
or `Gmpz` and `Gmpq` with coercion type `Gmpq`. or `Gmpz` and `Gmpq` with coercion type `Gmpq`.
However, the coercion type is not necessarily one of the input types, However, the coercion type is not necessarily one of the input types,
e.g. the coercion type of a polynomial e.g. the coercion type of a polynomial
@ -269,7 +269,7 @@ The package is part of \cgal since release 3.3. Of course the package is based
on the former Number type support of CGAL. This goes back to Stefan Schirra and Andreas Fabri. But on the other hand the package is to a large extend influenced on the former Number type support of CGAL. This goes back to Stefan Schirra and Andreas Fabri. But on the other hand the package is to a large extend influenced
by the experience with the number type support in \exacus \cgalCite{beh-eeeafcs-05}, by the experience with the number type support in \exacus \cgalCite{beh-eeeafcs-05},
which in the main goes back to which in the main goes back to
Lutz Kettner, Susan Hert, Arno Eigenwillig and Michael Hemmer. Lutz Kettner, Susan Hert, Arno Eigenwillig, and Michael Hemmer.
However, the package abstracts from the pure support for However, the package abstracts from the pure support for
number types that are embedded on the real axis which allows the support of number types that are embedded on the real axis which allows the support of
polynomials, finite fields, and algebraic extensions as well. See also related polynomials, finite fields, and algebraic extensions as well. See also related

View File

@ -146,8 +146,8 @@ polynomial is not computed yet.
This is in particular relevant in relation to the `AlgebraicKernel_d_2`, This is in particular relevant in relation to the `AlgebraicKernel_d_2`,
where `AlgebraicKernel_d_1::Algebraic_real_1` is used to represent coordinates of solutions of bivariate systems. where `AlgebraicKernel_d_1::Algebraic_real_1` is used to represent coordinates of solutions of bivariate systems.
Hence, the design does Hence, the design does
not allow a direct access to any, seemingly obvious, members of an not allow direct access to any, seemingly obvious, members of an
`AlgebraicKernel_d_1::Algebraic_real_1`. Instead there is, e.g., `AlgebraicKernel_d_1::Algebraic_real_1`. Instead, there is, e.g.,
`AlgebraicKernel_d_1::Compute_polynomial_1` which emphasizes `AlgebraicKernel_d_1::Compute_polynomial_1` which emphasizes
that the requested polynomial may not be computed yet. Similarly, that the requested polynomial may not be computed yet. Similarly,
there is no way to directly ask for the refinement of the current there is no way to directly ask for the refinement of the current

View File

@ -35,8 +35,8 @@ of this process in 2D (where our ice-cream spoon is simply a circle).
Alpha shapes depend on a parameter \f$ \alpha\f$ after which they are named. Alpha shapes depend on a parameter \f$ \alpha\f$ after which they are named.
In the ice-cream analogy above, \f$ \alpha\f$ is the squared radius of the In the ice-cream analogy above, \f$ \alpha\f$ is the squared radius of the
carving spoon. A very small value will allow us to eat up all of the carving spoon. A very small value will allow us to eat up all the
ice-cream except the chocolate points themselves. Thus we already see ice-cream except the chocolate points themselves. Thus, we already see
that the \f$ \alpha\f$-shape degenerates to the point-set \f$ S\f$ for that the \f$ \alpha\f$-shape degenerates to the point-set \f$ S\f$ for
\f$ \alpha \rightarrow 0\f$. On the other hand, a huge value of \f$ \alpha\f$ \f$ \alpha \rightarrow 0\f$. On the other hand, a huge value of \f$ \alpha\f$
will prevent us even from moving the spoon between two points since will prevent us even from moving the spoon between two points since
@ -53,7 +53,7 @@ We distinguish two versions of alpha shapes. <I>Basic alpha shapes</I>
are based on the Delaunay triangulation. <I>Weighted alpha shapes</I> are based on the Delaunay triangulation. <I>Weighted alpha shapes</I>
are based on its generalization, the regular triangulation are based on its generalization, the regular triangulation
(cf. Section \ref Section_2D_Triangulations_Regular "Regular Triangulations"), (cf. Section \ref Section_2D_Triangulations_Regular "Regular Triangulations"),
replacing the euclidean distance by the power to weighted points. replacing the Euclidean distance by the power to weighted points.
There is a close connection between alpha shapes and the underlying There is a close connection between alpha shapes and the underlying
triangulations. More precisely, the \f$ \alpha\f$-complex of \f$ S\f$ is a triangulations. More precisely, the \f$ \alpha\f$-complex of \f$ S\f$ is a
@ -100,7 +100,7 @@ It provides iterators to enumerate the vertices and edges that are in
the \f$ \alpha\f$-shape, and functions that allow to classify vertices, the \f$ \alpha\f$-shape, and functions that allow to classify vertices,
edges and faces with respect to the \f$ \alpha\f$-shape. They can be in edges and faces with respect to the \f$ \alpha\f$-shape. They can be in
the interior of a face that belongs or does not belong to the \f$ \alpha\f$-shape. the interior of a face that belongs or does not belong to the \f$ \alpha\f$-shape.
They can be singular/regular, that is be on the boundary of the \f$ \alpha\f$-shape, They can be singular/regular, that is, they can be on the boundary of the \f$ \alpha\f$-shape,
but not incident/incident to a triangle of the \f$ \alpha\f$-complex. but not incident/incident to a triangle of the \f$ \alpha\f$-complex.
Finally, it provides a function to determine the \f$ \alpha\f$-value Finally, it provides a function to determine the \f$ \alpha\f$-value
@ -213,7 +213,7 @@ cube will be chosen and no optimizations will be used.
It is also recommended to switch the triangulation to 1-sheeted It is also recommended to switch the triangulation to 1-sheeted
covering if possible. Note that a periodic triangulation in 9-sheeted covering if possible. Note that a periodic triangulation in 9-sheeted
covering space is degenerate. In this case, an exact constructions covering space is degenerate. In this case, an exact constructions
kernel needs to be used to compute the alpha shapes. Otherwise the kernel needs to be used to compute the alpha shapes. Otherwise, the
results will suffer from round-off problems. results will suffer from round-off problems.
\cgalExample{Alpha_shapes_2/ex_periodic_alpha_shapes_2.cpp} \cgalExample{Alpha_shapes_2/ex_periodic_alpha_shapes_2.cpp}

View File

@ -34,8 +34,8 @@ of this process in 2D (where our ice-cream spoon is simply a circle).
Alpha shapes depend on a parameter \f$ \alpha\f$ after which they are named. Alpha shapes depend on a parameter \f$ \alpha\f$ after which they are named.
In the ice-cream analogy above, \f$ \alpha\f$ is the squared radius of the In the ice-cream analogy above, \f$ \alpha\f$ is the squared radius of the
carving spoon. A very small value will allow us to eat up all of the carving spoon. A very small value will allow us to eat up all the
ice-cream except the chocolate points themselves. Thus we already see ice-cream except the chocolate points themselves. Thus, we already see
that the alpha shape degenerates to the point-set \f$ S\f$ for that the alpha shape degenerates to the point-set \f$ S\f$ for
\f$ \alpha \rightarrow 0\f$. On the other hand, a huge value of \f$ \alpha\f$ \f$ \alpha \rightarrow 0\f$. On the other hand, a huge value of \f$ \alpha\f$
will prevent us even from moving the spoon between two points since will prevent us even from moving the spoon between two points since
@ -53,7 +53,7 @@ We distinguish two versions of alpha shapes. <I>Basic alpha shapes</I>
are based on the Delaunay triangulation. <I>Weighted alpha shapes</I> are based on the Delaunay triangulation. <I>Weighted alpha shapes</I>
are based on its generalization, the regular triangulation are based on its generalization, the regular triangulation
(cf. Section \ref Triangulation3secclassRegulartriangulation "Regular Triangulations"), (cf. Section \ref Triangulation3secclassRegulartriangulation "Regular Triangulations"),
replacing the euclidean distance by the power to weighted points. replacing the Euclidean distance by the power to weighted points.
Let us consider the basic case with a Delaunay triangulation. Let us consider the basic case with a Delaunay triangulation.
We first define the alpha complex of the set of points \f$ S\f$. We first define the alpha complex of the set of points \f$ S\f$.
@ -79,7 +79,7 @@ of the alpha complex where singular faces are removed
(See \cgalFigureRef{figgenregex} for an example). (See \cgalFigureRef{figgenregex} for an example).
\cgalFigureBegin{figgenregex,gen-reg-ex.png} \cgalFigureBegin{figgenregex,gen-reg-ex.png}
Comparison of general and regularized alpha-shape. <B>Left:</B> Some points are taken on the surface of a torus, three points being taken relatively far from the surface of the torus; <B>Middle:</B> The general alpha-shape (for a large enough alpha value) contains the singular triangle facet of the three isolated points; <B>Right:</B> The regularized version (for the same value of alpha) does not contains any singular facet. Comparison of general and regularized alpha-shape. <B>Left:</B> Some points are taken on the surface of a torus, three points being taken relatively far from the surface of the torus; <B>Middle:</B> The general alpha-shape (for a large enough alpha value) contains the singular triangle facet of the three isolated points; <B>Right:</B> The regularized version (for the same value of alpha) does not contain any singular facet.
\cgalFigureEnd \cgalFigureEnd
The alpha shapes of a set of points The alpha shapes of a set of points
@ -112,11 +112,11 @@ and radii \f$ r_1, r_2 \f$ are said to be orthogonal iff
iff \f$ C_1C_2 ^2 < r_1^2 + r_2^2\f$. iff \f$ C_1C_2 ^2 < r_1^2 + r_2^2\f$.
For a given value of \f$ \alpha\f$, For a given value of \f$ \alpha\f$,
the weighted alpha complex is formed with the simplices of the the weighted alpha complex is formed with the simplices of the
regular triangulation triangulation regular triangulation such that there is a sphere
such that there is a sphere orthogonal to the weighted points associated orthogonal to the weighted points associated
with the vertices of the simplex and suborthogonal to all the other with the vertices of the simplex and suborthogonal to all the other
input weighted points. Once again the alpha shape is then defined as input weighted points. Once again the alpha shape is then defined as
the domain covered by a the alpha complex and comes in general and the domain covered by the alpha complex and comes in general and
regularized versions. regularized versions.
\section Alpha_Shape_3Functionality Functionality \section Alpha_Shape_3Functionality Functionality
@ -273,7 +273,7 @@ alpha-shape, using the `Alpha_shape_3<Dt,ExactAlphaComparisonTag>` requires a ke
with exact predicates and exact constructions (or setting `ExactAlphaComparisonTag` to `Tag_true`) with exact predicates and exact constructions (or setting `ExactAlphaComparisonTag` to `Tag_true`)
while using a kernel with exact predicates is sufficient for the class `Fixed_alpha_shape_3<Dt>`. while using a kernel with exact predicates is sufficient for the class `Fixed_alpha_shape_3<Dt>`.
This makes the class `Fixed_alpha_shape_3<Dt>` even more efficient in this setting. This makes the class `Fixed_alpha_shape_3<Dt>` even more efficient in this setting.
In addition, note that the `Fixed` version is the only of the In addition, note that the `Fixed` version is the only one of the
two that supports incremental insertion and removal of points. two that supports incremental insertion and removal of points.
We give the time spent while computing the alpha shape of a protein (considered We give the time spent while computing the alpha shape of a protein (considered
@ -345,7 +345,7 @@ cube will be chosen and no optimizations will be used.
It is also recommended to switch the triangulation to 1-sheeted It is also recommended to switch the triangulation to 1-sheeted
covering if possible. Note that a periodic triangulation in 27-sheeted covering if possible. Note that a periodic triangulation in 27-sheeted
covering space is degenerate. In this case, an exact constructions covering space is degenerate. In this case, an exact constructions
kernel needs to be used to compute the alpha shapes. Otherwise the kernel needs to be used to compute the alpha shapes. Otherwise, the
results will suffer from round-off problems. results will suffer from round-off problems.
\cgalExample{Alpha_shapes_3/ex_periodic_alpha_shapes_3.cpp} \cgalExample{Alpha_shapes_3/ex_periodic_alpha_shapes_3.cpp}

View File

@ -264,7 +264,7 @@ Secondly, the farther the isosurface is from the input, the more new points are
through the first criterion (i.e., through intersection with dual Voronoi edge, see Section \ref aw3_algorithm); through the first criterion (i.e., through intersection with dual Voronoi edge, see Section \ref aw3_algorithm);
thus, the quality of the output improves in terms of angles of the triangle elements. thus, the quality of the output improves in terms of angles of the triangle elements.
Finally, and depending on the value of the alpha parameter, a large offset can also offer defeaturing capabilities. Finally, and depending on the value of the alpha parameter, a large offset can also offer defeaturing capabilities.
However using a small offset parameter will tend to better preserve sharp features as projection However, using a small offset parameter will tend to better preserve sharp features as projection
Steiner points tend to project onto convex sharp features. Steiner points tend to project onto convex sharp features.
\cgalFigureAnchor{6} \cgalFigureAnchor{6}
@ -278,7 +278,7 @@ Impact of the offset parameter on the output.
The offset parameter is decreasing from left to right, to respectively 1/50, 1/200 and 1/1000 of the longest diagonal of the input bounding box. The offset parameter is decreasing from left to right, to respectively 1/50, 1/200 and 1/1000 of the longest diagonal of the input bounding box.
The alpha parameter is equal to 1/50 of the longest diagonal of the input bounding box for all level of details. The alpha parameter is equal to 1/50 of the longest diagonal of the input bounding box for all level of details.
A larger offset will produce an output less complex with better triangle quality. A larger offset will produce an output less complex with better triangle quality.
However the sharp features (red edges) are well preserved when the offset parameter is small. However, the sharp features (red edges) are well-preserved when the offset parameter is small.
\cgalFigureCaptionEnd \cgalFigureCaptionEnd
\cgalFigureAnchor{7} \cgalFigureAnchor{7}
@ -346,15 +346,15 @@ The charts below plots the computation times of the wrapping algorithm on the Th
\cgalFigureCaptionBegin{9} \cgalFigureCaptionBegin{9}
Execution times and output complexity for different values of alpha on the Thingi10k data set. Execution times and output complexity for different values of alpha on the Thingi10k data set.
Alpha increases from 1/20 to 1/200 of the length of bounding box diagonal. Alpha increases from 1/20 to 1/200 of the length of bounding box diagonal.
The x axis represents the complexity of the output wrap mesh in number of triangle facets. The x-axis represents the complexity of the output wrap mesh in number of triangle facets.
The y axis represents the total computation time, in seconds. The y-axis represents the total computation time, in seconds.
The color and diameter of the dots represent the number of faces in the input triangle soup, The color and diameter of the dots represent the number of faces in the input triangle soup,
ranging from 10 (green) to 3154000 (blue). ranging from 10 (green) to 3154000 (blue).
\cgalFigureCaptionEnd \cgalFigureCaptionEnd
\section aw3_examples Examples \section aw3_examples Examples
Here is an example with an input triangle mesh, with alpha set to 1/20 of the bounding box longest diagonal edge length, Here is an example with an input triangle mesh, with alpha set to 1/20 of the bounding box's longest diagonal edge length,
and offset set to 1/30 of alpha (i.e., 1/600 of the bounding box diagonal edge length). and offset set to 1/30 of alpha (i.e., 1/600 of the bounding box diagonal edge length).
\cgalExample{Alpha_wrap_3/triangle_mesh_wrap.cpp} \cgalExample{Alpha_wrap_3/triangle_mesh_wrap.cpp}

View File

@ -62,7 +62,7 @@ returns one of the halfedges corresponding to `e`.
*/ */
template <typename HalfedgeGraph> template <typename HalfedgeGraph>
boost::graph_traits<HalfedgeGraph>::halfedge_descriptor boost::graph_traits<HalfedgeGraph>::halfedge_descriptor
halfedge(boost::graph_traits<HalfedgeGraph>::edge_descriptor f, const HalfedgeGraph& g); halfedge(boost::graph_traits<HalfedgeGraph>::edge_descriptor e, const HalfedgeGraph& g);
/*! \relates HalfedgeGraph /*! \relates HalfedgeGraph
returns a halfedge with target `v`. returns a halfedge with target `v`.

View File

@ -278,7 +278,9 @@ def main():
encoding="utf-8", encoding="utf-8",
) )
k = 2 k = 2
citeDic = {}
for line in f: for line in f:
foundDouble=False
match = pattern.match(line) match = pattern.match(line)
if match: if match:
pkg = match.group(1) pkg = match.group(1)
@ -304,6 +306,10 @@ def main():
match = pattern_bib.match(pkg_line) match = pattern_bib.match(pkg_line)
if match: if match:
bib = match.group(1) bib = match.group(1)
if bib in citeDic:
foundDouble=True
else:
citeDic[bib] = pkg
continue continue
assert len(bib) > 0, "Did you forget a \\cgalPkgBib{} in %r?" % filename assert len(bib) > 0, "Did you forget a \\cgalPkgBib{} in %r?" % filename
assert len(authors) > 0, ( assert len(authors) > 0, (
@ -313,6 +319,11 @@ def main():
"Did you forget the anchor in \\cgalPkgDescriptionBegin{} in %r?" "Did you forget the anchor in \\cgalPkgDescriptionBegin{} in %r?"
% filename % filename
) )
assert not foundDouble, (
"""Multiple use of citation name '{}' package '{}'
first occurence package '{}'
""".format(bib,pkg,citeDic[bib])
)
result_txt += gen_txt_entry(title, authors, bib, anchor, k) result_txt += gen_txt_entry(title, authors, bib, anchor, k)
# convert title and author to bibtex format # convert title and author to bibtex format
title = protect_upper_case(title) title = protect_upper_case(title)

View File

@ -192,7 +192,7 @@ i.e.\ \f$ |*g| < r\f$. Two random numbers are needed from
`rnd` for each point. `rnd` for each point.
*/ */
Random_points_in_disc_2( double r, Random& rnd = Random_points_in_disc_2( double r = 1.0, Random& rnd =
get_default_random()); get_default_random());
/// @} /// @}
@ -527,7 +527,7 @@ i.e.\ \f$ |*g| == r\f$. A single random number is needed from
`rnd` for each point. `rnd` for each point.
*/ */
Random_points_on_circle_2( double r, Random& rnd = Random_points_on_circle_2( double r=1.0, Random& rnd =
get_default_random()); get_default_random());
/// @} /// @}

View File

@ -153,7 +153,7 @@ i.e.\ \f$ |*g| < r\f$ . Three random numbers are needed from
`rnd` for each point. `rnd` for each point.
*/ */
Random_points_in_sphere_3( double r, Random& rnd = Random_points_in_sphere_3( double r = 1.0, Random& rnd =
get_default_random()); get_default_random());
/// @} /// @}
@ -719,7 +719,7 @@ i.e.\ \f$ |*g| == r\f$ . Two random numbers are needed from
`rnd` for each point. `rnd` for each point.
*/ */
Random_points_on_sphere_3( double r, Random& rnd = Random_points_on_sphere_3( double r=1.0, Random& rnd =
get_default_random()); get_default_random());
/// @} /// @}

View File

@ -91,7 +91,7 @@ i.e.\ \f$ |*g| < r\f$ . \f$ 2\cdot dim+1\f$ random numbers are needed from
`rnd` for each point. `rnd` for each point.
*/ */
Random_points_in_ball_d(int dim, double r); Random_points_in_ball_d(int dim, double r=1.0, Random& rnd = get_default_random());
/// @} /// @}
@ -227,7 +227,7 @@ i.e.\ \f$ |*g| == r\f$ . \f$ 2\cdot dim\f$ random numbers are needed from
`rnd` for each point. `rnd` for each point.
*/ */
Random_points_on_sphere_d(int dim, double r, Random& rnd = Random_points_on_sphere_d(int dim, double r=1.0, Random& rnd =
get_default_random()); get_default_random());
/// @} /// @}

View File

@ -38,7 +38,7 @@ public:
typedef Random_points_in_sphere_3<P,Creator> This; typedef Random_points_in_sphere_3<P,Creator> This;
Random_points_in_sphere_3( double r = 1, Random& rnd = CGAL::get_default_random()) Random_points_in_sphere_3( double r = 1, Random& rnd = CGAL::get_default_random())
// g is an input iterator creating points of type `P' uniformly // g is an input iterator creating points of type `P' uniformly
// distributed in the open sphere with radius r, i.e. |`*g'| < r . // distributed in the open sphere with radius r, i.e., |`*g'| < r .
// Three random numbers are needed from `rnd' for each point // Three random numbers are needed from `rnd' for each point
: Random_generator_base<P>( r, rnd) { generate_point(); } : Random_generator_base<P>( r, rnd) { generate_point(); }
This& operator++() { This& operator++() {

View File

@ -109,6 +109,10 @@ Release date: _______ 2025
enables the user to specify a `Range` of initial points. enables the user to specify a `Range` of initial points.
- Added a new meshing parameter [`surface_only`](https://doc.cgal.org/6.1/Mesh_3/group__PkgMesh3Parameters.html#gaa2618c09b6117d7caab12dccca16ee58), - Added a new meshing parameter [`surface_only`](https://doc.cgal.org/6.1/Mesh_3/group__PkgMesh3Parameters.html#gaa2618c09b6117d7caab12dccca16ee58),
which can be used to improve performance when only surface mesh generation is sought. which can be used to improve performance when only surface mesh generation is sought.
- Added a new mesh domain [`Poisson_mesh_domain_3`](), which should be used when generating a mesh from a Poisson surface
obtained with the package [Poisson Surface Reconstruction](https://doc.cgal.org/6.1/Manual/packages.html#PkgPoissonSurfaceReconstruction3).
This mesh domain re-integrates some optimizations for Poisson surface mesh generation that were lost
when the package [3D Mesh Generation](https://doc.cgal.org/6.1/Manual/packages.html#PkgMesh3) had to be replaced instead of the deprecated package [3D Surface Mesh Generation](https://doc.cgal.org/latest/Manual/packages.html#PkgSurfaceMesher3).
### [3D Subdivision Methods](https://doc.cgal.org/6.1/Manual/packages.html#PkgSurfaceSubdivisionMethod3) ### [3D Subdivision Methods](https://doc.cgal.org/6.1/Manual/packages.html#PkgSurfaceSubdivisionMethod3)

View File

@ -18,7 +18,7 @@
//| a derived class. The workaround is to write a forwarder or not use using. //| a derived class. The workaround is to write a forwarder or not use using.
//| At least SunPro CC 5.3 has this bug where the typical error message is : //| At least SunPro CC 5.3 has this bug where the typical error message is :
//| "Error: The function B<int>::g() has not had a body defined." //| "Error: The function B<int>::g() has not had a body defined."
//| Note that the subtlely is that the error message does not mention //| Note that the subtility is that the error message does not mention
//| "Member"... //| "Member"...
//| This test is updated (hijacked) to detect an issue with sunpro 5.9 //| This test is updated (hijacked) to detect an issue with sunpro 5.9
//| that instantiates a function twice. //| that instantiates a function twice.

View File

@ -7,13 +7,8 @@
// $Id$ // $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
// //
//
// Author(s) : Stéphane Tayeb, Aymeric PELLE // Author(s) : Stéphane Tayeb, Aymeric PELLE
//
//******************************************************************************
// File Description :
// class Labeled_mesh_domain_3. See class description.
//******************************************************************************
#ifndef CGAL_LABELED_MESH_DOMAIN_3_H #ifndef CGAL_LABELED_MESH_DOMAIN_3_H
#define CGAL_LABELED_MESH_DOMAIN_3_H #define CGAL_LABELED_MESH_DOMAIN_3_H
@ -875,17 +870,15 @@ public:
* function. The domain to be discretized is assumed to be the domain where * function. The domain to be discretized is assumed to be the domain where
* the function has negative values. * the function has negative values.
* *
* The method takes as argument a bounding sphere which is required to
* circumscribe the surface and to have its center inside the domain.
*
* \tparam Function a type compatible with the signature `FT(Point_3)`: it takes a point as argument, * \tparam Function a type compatible with the signature `FT(Point_3)`: it takes a point as argument,
* and returns a scalar value. That object must be model of `CopyConstructible` * and returns a scalar value. That object must be model of `CopyConstructible`
* \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" * \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
* \tparam Bounding_object either a bounding sphere (of type `Sphere_3`), a bounding box (type `Bbox_3`), * \tparam Bounding_object either a bounding sphere (of type `Sphere_3`), a bounding box (type `Bbox_3`),
* or a bounding `Iso_cuboid_3` * or a bounding `Iso_cuboid_3` which is required to circumscribe
* the surface and to have its center inside the domain.
* *
* \param function the implicit function * \param function the implicit function
* \param bounding_object object boundint the meshable domain and its center is inside the domain. * \param bounding_object object bounding the meshable domain and its center is inside the domain.
* \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below: * \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below:
* *
* \cgalNamedParamsBegin * \cgalNamedParamsBegin
@ -936,12 +929,11 @@ public:
/// @} /// @}
#ifndef DOXYGEN_RUNNING #ifndef DOXYGEN_RUNNING
template<typename CGAL_NP_TEMPLATE_PARAMETERS> template<typename CGAL_NP_TEMPLATE_PARAMETERS>
static Labeled_mesh_domain_3 create_implicit_mesh_domain(const CGAL_NP_CLASS& np = parameters::default_values()) static Labeled_mesh_domain_3 create_implicit_mesh_domain(const CGAL_NP_CLASS &np)
{ {
static_assert(!parameters::is_default_parameter<CGAL_NP_CLASS, internal_np::function_param_t>::value, "Value for required parameter not found"); static_assert(!parameters::is_default_parameter<CGAL_NP_CLASS, internal_np::function_param_t>::value, "Value for required parameter not found");
static_assert(!parameters::is_default_parameter<CGAL_NP_CLASS, internal_np::bounding_object_param_t>::value, "Value for required parameter not found"); static_assert(!parameters::is_default_parameter<CGAL_NP_CLASS, internal_np::bounding_object_param_t>::value, "Value for required parameter not found");
using parameters::get_parameter;
return create_implicit_mesh_domain(parameters::get_parameter(np, internal_np::function_param), return create_implicit_mesh_domain(parameters::get_parameter(np, internal_np::function_param),
parameters::get_parameter(np, internal_np::bounding_object_param), parameters::get_parameter(np, internal_np::bounding_object_param),
np); np);
@ -1139,11 +1131,7 @@ public:
/* /*
* Returns a point in the intersection of the primitive `type` * Returns a point in the intersection of the primitive `type`
* with some boundary surface. * with some boundary surface.
* `Type1` is either `Segment_3`, `Ray_3` or `Line_3`. * `Type` is either `Segment_3`, `Ray_3` or `Line_3`.
* The integer `dimension` is set to the dimension of the lowest
* dimensional face in the input complex containing the returned point, and
* `index` is set to the index to be stored at a mesh vertex lying
* on this face.
*/ */
struct Construct_intersection struct Construct_intersection
{ {
@ -1170,10 +1158,10 @@ public:
private: private:
/* /*
* Returns a point in the intersection of [a,b] with the surface * Returns a point in the intersection of `[a,b]` with the surface
* `a` must be the source point, and `b` the out point. It's important * `a` must be the source point, and `b` the out point. It is important
* because it drives bisection cuts. * because it drives bisection cuts.
* Indeed, the returned point is the first intersection from `[a,b]` * Indeed, the returned point is the first intersection of `[a,b]`
* with a subdomain surface. * with a subdomain surface.
*/ */
Intersection operator()(const Point_3& a, const Point_3& b) const Intersection operator()(const Point_3& a, const Point_3& b) const
@ -1196,7 +1184,7 @@ public:
// If both extremities are in the same subdomain, // If both extremities are in the same subdomain,
// there is no intersection. // there is no intersection.
// This should not happen... // Should only be able to happen during initial point generation.
if( value_at_p1 == value_at_p2 ) if( value_at_p1 == value_at_p2 )
{ {
return Intersection(); return Intersection();

View File

@ -275,7 +275,7 @@ Nef_polyhedron_2<T> difference(const Nef_polyhedron_2<T>& N1) ;
/*! /*!
returns the symmectric difference `N - T` \f$ \cup\f$ `T - N`. returns the symmetric difference `N - T` \f$ \cup\f$ `T - N`.
*/ */
Nef_polyhedron_2<T> symmetric_difference(const Nef_polyhedron_2<T>& N1) ; Nef_polyhedron_2<T> symmetric_difference(const Nef_polyhedron_2<T>& N1) ;

View File

@ -773,7 +773,7 @@ public:
Nef_polyhedron_2<T,Items,Mark> symmetric_difference( Nef_polyhedron_2<T,Items,Mark> symmetric_difference(
const Nef_polyhedron_2<T,Items,Mark>& N1) const const Nef_polyhedron_2<T,Items,Mark>& N1) const
/*{\Mop returns the symmectric difference |\Mvar - T| $\cup$ /*{\Mop returns the symmetric difference |\Mvar - T| $\cup$
|T - \Mvar|. }*/ |T - \Mvar|. }*/
{ Nef_polyhedron_2<T,Items,Mark> res(pm(),false); // empty, no frame { Nef_polyhedron_2<T,Items,Mark> res(pm(),false); // empty, no frame
Overlayer D(res.pm()); Overlayer D(res.pm());

View File

@ -1541,7 +1541,7 @@ protected:
Nef_polyhedron_3<Kernel,Items, Mark> Nef_polyhedron_3<Kernel,Items, Mark>
symmetric_difference(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const symmetric_difference(const Nef_polyhedron_3<Kernel,Items, Mark>& N1) const
/*{\Mop returns the symmectric difference |\Mvar - T| $\cup$ /*{\Mop returns the symmetric difference |\Mvar - T| $\cup$
|T - \Mvar|. }*/ { |T - \Mvar|. }*/ {
CGAL_NEF_TRACEN(" symmetric difference between nef3 "<<&*this<<" and "<<&N1); CGAL_NEF_TRACEN(" symmetric difference between nef3 "<<&*this<<" and "<<&N1);
if (is_empty()) return N1; if (is_empty()) return N1;

View File

@ -1072,7 +1072,7 @@ Nef_polyhedron_S2<K> difference(const Nef_polyhedron_S2<K>&
N1) ; N1) ;
/*! /*!
returns the symmectric difference returns the symmetric difference
`N - T` \f$ \cup\f$ `T - N`. `N - T` \f$ \cup\f$ `T - N`.
*/ */
Nef_polyhedron_S2<K> symmetric_difference( const Nef_polyhedron_S2<K> symmetric_difference( const

View File

@ -479,7 +479,7 @@ public:
Self symmetric_difference( Self symmetric_difference(
const Self& N1) const const Self& N1) const
/*{\Mop returns the symmectric difference |\Mvar - T| $\cup$ /*{\Mop returns the symmetric difference |\Mvar - T| $\cup$
|T - \Mvar|. }*/ |T - \Mvar|. }*/
{ Self res(sphere_map(),false); // empty { Self res(sphere_map(),false); // empty
Overlayer D(&res.sphere_map()); Overlayer D(&res.sphere_map());

View File

@ -13,8 +13,7 @@ This \cgal component implements a surface reconstruction method which
takes as input point sets with oriented normals and computes an takes as input point sets with oriented normals and computes an
implicit function. We assume that the input points contain no outliers implicit function. We assume that the input points contain no outliers
and little noise. The output surface mesh is generated by extracting and little noise. The output surface mesh is generated by extracting
an isosurface of this function with the \cgal Surface Mesh Generator an isosurface of this function with the \ref PkgMesh3 or potentially with any other surface
\cgalCite{cgal:ry-gsddrm-06} or potentially with any other surface
contouring algorithm. contouring algorithm.
\cgalFigureBegin{Poisson_surface_reconstruction_3figintroduction,introduction.jpg} \cgalFigureBegin{Poisson_surface_reconstruction_3figintroduction,introduction.jpg}
@ -75,8 +74,8 @@ during refinement is set to zero. It then solves for a scalar
indicator function \f$ f\f$ represented as a piecewise linear function indicator function \f$ f\f$ represented as a piecewise linear function
over the refined triangulation. More specifically, it solves for the over the refined triangulation. More specifically, it solves for the
Poisson equation \f$ \Delta f = div(\mathbf{n})\f$ at each vertex of Poisson equation \f$ \Delta f = div(\mathbf{n})\f$ at each vertex of
the triangulation using a sparse linear solver. Eventually, the \cgal the triangulation using a sparse linear solver. Eventually, the \ref PkgMesh3
surface mesh generator extracts an isosurface with function value set extracts an isosurface with function value set
by default to be the median value of \f$ f\f$ at all input points. by default to be the median value of \f$ f\f$ at all input points.
\section Poisson_surface_reconstruction_3Function Reconstruction Function \section Poisson_surface_reconstruction_3Function Reconstruction Function
@ -86,9 +85,7 @@ provided. It takes points with normals as input and handles the whole
reconstruction pipeline : reconstruction pipeline :
- it computes the implicit function - it computes the implicit function
- it reconstructs the surface with a given precision using the \cgal - it reconstructs the surface with a given precision using the \ref PkgMesh3
surface mesh generator based on Delaunay refinement
\cgalCite{cgal:ry-gsddrm-06} \cgalCite{cgal:bo-pgsms-05}
- it outputs the result in a polygon mesh. - it outputs the result in a polygon mesh.
This function aims at providing a quick and user-friendly API for This function aims at providing a quick and user-friendly API for
@ -118,26 +115,19 @@ The following example reads a point set, creates a Poisson implicit function and
\subsection Poisson_surface_reconstruction_3Contouring Contouring \subsection Poisson_surface_reconstruction_3Contouring Contouring
The computed implicit functions can be iso-contoured to reconstruct a The computed implicit functions can be iso-contoured to reconstruct a
surface by using the \cgal surface mesh generator surface by using the \ref PkgMesh3 component, and in particular the function
\cgalCite{cgal:ry-gsddrm-06} \cgalCite{cgal:bo-pgsms-05} : `make_mesh_3()` with the `surface_only()` parameter to only mesh the surface.
`make_surface_mesh()` The following `Tag` parameters affect the behavior of `make_mesh_3()`:
The parameter `Tag` affects the behavior of `make_surface_mesh()`:
- `Manifold_tag`: the output mesh is guaranteed to be a manifold surface without boundary. - `Manifold_tag`: the output mesh is guaranteed to be a manifold surface without boundary.
- `Manifold_with_boundary_tag`: the output mesh is guaranteed to be manifold and may have boundaries. - `Manifold_with_boundary_tag`: the output mesh is guaranteed to be manifold and may have boundaries.
- `Non_manifold_tag`: the output mesh has no guarantee and hence is outputted as a polygon soup. - `Non_manifold_tag`: the output mesh has no guarantee and hence is outputted as a polygon soup.
\subsection Poisson_surface_reconstruction_3Output Output \subsection Poisson_surface_reconstruction_3Output Output
The surface reconstructed by `make_surface_mesh()` is required to be a The surface reconstructed by `make_mesh_3()` is required to be a model of the concept
model of the concept `SurfaceMeshComplex_2InTriangulation_3`, a data `MeshComplex_3InTriangulation_3`, a data structure devised to represent a three dimensional complex embedded into a three dimensional triangulation. The surface facets can then be extracted into a face graph by `facets_in_complex_3_to_triangle_mesh()`.
structure devised to represent a two dimensional complex embedded into
a three dimensional triangulation.
`SurfaceMeshComplex_2InTriangulation_3` defines the methods to traverse the reconstructed surface, and e.g. convert it to a triangle soup.
Other \cgal components provide functions to write the reconstructed Other \cgal components provide functions to write the reconstructed
surface mesh to the %Object File Format (OFF) \cgalCite{cgal:p-gmgv16-96} surface mesh to the %Object File Format (OFF) \cgalCite{cgal:p-gmgv16-96}
@ -218,7 +208,7 @@ function over the tetrahedra of a 3D Delaunay triangulation
constructed from the input points then refined through Delaunay constructed from the input points then refined through Delaunay
refinement. For this reason, any iso-surface is also piecewise linear refinement. For this reason, any iso-surface is also piecewise linear
and hence may contain sharp creases. As the contouring algorithm and hence may contain sharp creases. As the contouring algorithm
`make_surface_mesh()` expects a smooth implicit function these `make_mesh_3()` expects a smooth implicit function these
sharp creases may create spurious clusters of vertices in the final sharp creases may create spurious clusters of vertices in the final
reconstructed surface mesh when setting a small mesh sizing or surface reconstructed surface mesh when setting a small mesh sizing or surface
approximation error parameter (see approximation error parameter (see
@ -339,136 +329,238 @@ Left: 5K points sampled on a mechanical piece with sharp features (creases, dart
We provide some performance numbers for scanning data. We measure the Poisson implicit function computation time, We provide some performance numbers for scanning data. We measure the Poisson implicit function computation time,
the contouring time for a range of approximation distances, the memory occupancy as well as the influence of the contouring time for a range of approximation distances, the memory occupancy as well as the influence of
the point set simplification. The machine used is a PC running Windows 7 64 bits with an Intel CPU Core 2 Duo the point set simplification. The machine used is a PC running Windows 10 64 bits with an Intel CPU Core i7-11850H
processor clocked at 2.81 GHz and with 8 GB of RAM. The software is compiled with Visual \CC 2010 (VC9) compiler processor with 8 cores and 32 GB of RAM. The software is compiled with Visual \CC 2022 compiler
with the 03 option which maximizes speed. All measurements were done using the \ref thirdpartyEigen "Eigen" library. with the 03 option which maximizes speed. All measurements were done using the \ref thirdpartyEigen "Eigen" library.
\subsection SurfReconstPerfPIF Poisson Implicit Function \subsection SurfReconstPerfPIF Poisson Implicit Function
The point set chosen for benchmarking the Poisson implicit function is the Bimba con Nastrino point set The point set chosen for benchmarking the Poisson implicit function is the Lucy statue point set from the
(1.6 million points) depicted by \cgalFigureRef{Poisson_surface_reconstruction_3-fig-contouring_bench}. <a href="https://graphics.stanford.edu/data/3Dscanrep/">The Stanford 3D Scanning Repository</a>
(originally 14 million points, here downsampled to 2.9 million points) depicted by \cgalFigureRef{Poisson_surface_reconstruction_3-fig-contouring_bench}.
We measure the Poisson implicit function computation (i.e., the call to We measure the Poisson implicit function computation (i.e., the call to
`Poisson_reconstruction_function::compute_implicit_function()` denoted by Poisson solve hereafter) `Poisson_reconstruction_function::compute_implicit_function()` denoted by Poisson solve hereafter)
for this point set as well as for simplified versions obtained through random simplification. for this point set as well as for simplified versions obtained through random simplification.
The following table provides Poisson solve computation times in seconds for an increasing number of points. The following table provides Poisson solve computation times in seconds for an increasing number of points.
<CENTER>
<TABLE CELLSPACING=5 > <TABLE CELLSPACING=5 >
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR> <TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR>
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
Number of points (x1000) Number of points (x1000)
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
Poisson solve duration (in s) Poisson solve duration (in s)
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR> <TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR>
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
30
<TD class="math" ALIGN=CENTER NOWRAP>
3.3
<TR>
<TD class="math" ALIGN=CENTER NOWRAP>
60 60
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
15 7.7
<TR>
<TD class="math" ALIGN=CENTER NOWRAP>
100
<TD class="math" ALIGN=CENTER NOWRAP>
25
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
250 120
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
96 18.1
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
500 237.5
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
150 35.1
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
1,000 375
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
249 64
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
1,800 750
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
478 129
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP>
1,500
<TD class="math" ALIGN=CENTER NOWRAP>
303
<TR>
<TD class="math" ALIGN=CENTER NOWRAP>
2,900
<TD class="math" ALIGN=CENTER NOWRAP>
486
<TR><TD ALIGN=CENTER NOWRAP COLSPAN=2><HR>
</TABLE> </TABLE>
</CENTER>
\subsection SurfReconstPerfCont Contouring \subsection SurfReconstPerfCont Contouring
The point set chosen for benchmarking the contouring stage is the Bimba con Nastrino point The point set chosen for benchmarking the contouring stage is the Lucy point
set simplified to 100k points. We measure the contouring (i.e.\ the call to `make_surface_mesh()`) set simplified to 2.9M points. We measure the contouring (i.e., the calls to `make_mesh_3()` and `facets_in_complex_3_to_triangle_mesh()`)
duration and the reconstruction error for a range of approximation distances. duration and the reconstruction error for a range of approximation distances.
The reconstruction error is expressed as the average distance from input points to the reconstructed surface The reconstruction error is expressed as the average distance from input points to the reconstructed surface in mm (the Lucy statue is 1597 mm tall).
in mm (the Bimba con Nastrino statue is 324 mm tall).
<CENTER>
<TABLE CELLSPACING=5 > <TABLE CELLSPACING=5 >
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=3><HR> <TR><TD ALIGN=CENTER NOWRAP COLSPAN=4><HR>
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
Approx. distance (*average spacing) Approx. distance (*average spacing)
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
Contouring duration (in s) Contouring duration single-thread (in s)
<TD class="math" ALIGN=CENTER NOWRAP>
Contouring duration parallel (in s)
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
Reconstruction error (mm) Reconstruction error (mm)
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=3><HR> <TR><TD ALIGN=CENTER NOWRAP COLSPAN=4><HR>
<TR>
<TD class="math" ALIGN=CENTER NOWRAP>
0.05
<TD class="math" ALIGN=CENTER NOWRAP>
582
<TD class="math" ALIGN=CENTER NOWRAP>
112
<TD class="math" ALIGN=CENTER NOWRAP>
0.114
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.1 0.1
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
19.2 221
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.055 26
<TD class="math" ALIGN=CENTER NOWRAP>
0.119
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP>
0.15
<TD class="math" ALIGN=CENTER NOWRAP>
104
<TD class="math" ALIGN=CENTER NOWRAP>
25
<TD class="math" ALIGN=CENTER NOWRAP>
0.129
<TR>
<TD class="math" ALIGN=CENTER NOWRAP>
0.2
<TD class="math" ALIGN=CENTER NOWRAP>
69.4
<TD class="math" ALIGN=CENTER NOWRAP>
9.2
<TD class="math" ALIGN=CENTER NOWRAP>
0.14
<TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.25 0.25
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
6.9 53.6
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.106 7.0
<TD class="math" ALIGN=CENTER NOWRAP>
0.151
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.5 0.5
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
3.2 25.2
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.18 3.6
<TD class="math" ALIGN=CENTER NOWRAP>
0.209
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP>
0.75
<TD class="math" ALIGN=CENTER NOWRAP>
16.4
<TD class="math" ALIGN=CENTER NOWRAP>
4.9
<TD class="math" ALIGN=CENTER NOWRAP>
0.209
<TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
1 1
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
1.65 12.4
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.36 2.3
<TD class="math" ALIGN=CENTER NOWRAP>
0.33
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP>
1.5
<TD class="math" ALIGN=CENTER NOWRAP>
8.2
<TD class="math" ALIGN=CENTER NOWRAP>
1.4
<TD class="math" ALIGN=CENTER NOWRAP>
0.455
<TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
2 2
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
6.1
<TD class="math" ALIGN=CENTER NOWRAP>
1.1
<TD class="math" ALIGN=CENTER NOWRAP>
0.59
<TR>
<TD class="math" ALIGN=CENTER NOWRAP>
3
<TD class="math" ALIGN=CENTER NOWRAP>
4.0
<TD class="math" ALIGN=CENTER NOWRAP>
0.8 0.8
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.76 0.87
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=3><HR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP>
5
<TD class="math" ALIGN=CENTER NOWRAP>
2.3
<TD class="math" ALIGN=CENTER NOWRAP>
0.7
<TD class="math" ALIGN=CENTER NOWRAP>
1.50
<TR>
<TD ALIGN=CENTER NOWRAP COLSPAN=4><HR>
</TABLE> </TABLE>
</CENTER>
\cgalFigureAnchor{Poisson_surface_reconstruction_3-fig-contouring_bench}
\cgalFigureBegin{Poisson_surface_reconstruction_3-fig-contouring_bench,contouring_bench.jpg} <center>
<img src="contouring_bench.jpg" style="max-width:80%;"/>
</center>
\cgalFigureCaptionBegin{Poisson_surface_reconstruction_3-fig-contouring_bench}
Contouring duration (in s) and reconstruction error (mm) Contouring duration (in s) and reconstruction error (mm)
against several approximation distance parameters against several approximation distance parameters
for the Bimba con Nastrino point set simplified to 100k points. for the Lucy point set simplified to 100k points.
\cgalFigureEnd \cgalFigureCaptionEnd
\subsection SurfReconstPerfMem Memory \subsection SurfReconstPerfMem Memory
We measure the memory occupancy for the reconstruction of the full Bimba con Nastrino point We measure the memory occupancy for the reconstruction of the Lucy point
set (1.8 millions points) as well as for simplified versions.\n set (2.9 millions points) as well as for further simplified versions.\n
The Poisson implicit function computation has a memory peak when solving the Poisson linear The Poisson implicit function computation has a memory peak when solving the Poisson linear
system using the sparse linear solver. system using the sparse linear solver.
<CENTER>
<TABLE CELLSPACING=5 > <TABLE CELLSPACING=5 >
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR> <TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR>
<TR> <TR>
@ -479,47 +571,59 @@ Memory occupancy (MBytes)
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR> <TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR>
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
30
<TD class="math" ALIGN=CENTER NOWRAP>
128
<TR>
<TD class="math" ALIGN=CENTER NOWRAP>
60 60
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
180 226
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
100 120
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
270 431
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
250 237.5
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
790 813
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
500 375
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
1300 1,232
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
1,000 750
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
2200 2,283
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
1,800 1,500
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
3800 4,042
<TR>
<TD class="math" ALIGN=CENTER NOWRAP>
2,900
<TD class="math" ALIGN=CENTER NOWRAP>
6,868
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR> <TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR>
</TABLE> </TABLE>
</CENTER>
\subsection SurfReconstPerfPSS Point Set Simplification \subsection SurfReconstPerfPSS Point Set Simplification
Due to the memory limitations described above, we recommend to simplify the point sets captured by laser scanners.\n Due to the memory limitations described above, we recommend to simplify the point sets captured by laser scanners.\n
We measure the reconstruction error for the Bimba con Nastrino point set (1.6M points) as well as for We measure the reconstruction error for the Lucy point set (2.9M points) as well as for
simplified versions. All reconstructions use the recommended contouring parameter simplified versions. All reconstructions use the recommended contouring parameter
`approximation distance = 0.25 * the input point` set's average spacing. `approximation distance = 0.25 * the input point` set's average spacing.
The reconstruction error is expressed as the average distance from input points to the reconstructed surface in mm The reconstruction error is expressed as the average distance from input points to the reconstructed surface in mm
(the Bimba con Nastrino statue is 324 mm tall). (the Lucy statue is 1597 mm tall).
<CENTER>
<TABLE CELLSPACING=5 > <TABLE CELLSPACING=5 >
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR> <TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR>
<TR> <TR>
@ -530,46 +634,67 @@ Reconstruction error (mm)
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR> <TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR>
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
3.75
<TD class="math" ALIGN=CENTER NOWRAP>
9.88395
<TR>
<TD class="math" ALIGN=CENTER NOWRAP>
7.5
<TD class="math" ALIGN=CENTER NOWRAP>
5.81843
<TR>
<TD class="math" ALIGN=CENTER NOWRAP>
15
<TD class="math" ALIGN=CENTER NOWRAP>
3.13479
<TR>
<TD class="math" ALIGN=CENTER NOWRAP>
30
<TD class="math" ALIGN=CENTER NOWRAP>
2.25391
<TR>
<TD class="math" ALIGN=CENTER NOWRAP>
60 60
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.27 1.42965
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
120 120
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.15 1.17589
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
250 237.5
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.11 0.99509
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
500 375
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.079 0.75215
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
1,000 750
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.066 0.344654
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
1,500 1,500
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.061 0.225341
<TR> <TR>
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
1,600 2,900
<TD class="math" ALIGN=CENTER NOWRAP> <TD class="math" ALIGN=CENTER NOWRAP>
0.06 0.150947
<TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR> <TR><TD ALIGN=LEFT NOWRAP COLSPAN=2><HR>
</TABLE> </TABLE>
</CENTER>
\cgalFigureBegin{Poisson_surface_reconstruction_3-fig-simplification_bench,simplification_bench.jpg} \cgalFigureBegin{Poisson_surface_reconstruction_3-fig-simplification_bench,simplification_bench.jpg}
Reconstruction error (mm) against number of points Reconstruction error (mm) against number of points
for the Bimba con Nastrino point set with 1.6M points for the Lucy point set with 2.9M points
as well as for simplified versions. as well as for simplified versions.
\cgalFigureEnd \cgalFigureEnd

View File

@ -1,8 +1,11 @@
Manual Manual
Kernel_23 Kernel_23
BGL
STL_Extension STL_Extension
Mesh_3
Algebraic_foundations Algebraic_foundations
Circulator Circulator
Stream_support Stream_support
Point_set_processing_3 Point_set_processing_3
Solver_interface Solver_interface
SMDS_3

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View File

@ -7,7 +7,7 @@
#include <CGAL/Mesh_triangulation_3.h> #include <CGAL/Mesh_triangulation_3.h>
#include <CGAL/Mesh_complex_3_in_triangulation_3.h> #include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <CGAL/Mesh_criteria_3.h> #include <CGAL/Mesh_criteria_3.h>
#include <CGAL/Labeled_mesh_domain_3.h> #include <CGAL/Poisson_mesh_domain_3.h>
#include <CGAL/make_mesh_3.h> #include <CGAL/make_mesh_3.h>
#include <CGAL/facets_in_complex_3_to_triangle_mesh.h> #include <CGAL/facets_in_complex_3_to_triangle_mesh.h>
@ -44,7 +44,7 @@ namespace params = CGAL::parameters;
template<typename Concurrency_tag, typename PointSet> template<typename Concurrency_tag, typename PointSet>
void poisson_reconstruction(const PointSet& points, const char* output) void poisson_reconstruction(const PointSet& points, const char* output)
{ {
typedef CGAL::Labeled_mesh_domain_3<Kernel> Mesh_domain; typedef CGAL::Poisson_mesh_domain_3<Kernel> Mesh_domain;
typedef typename CGAL::Mesh_triangulation_3<Mesh_domain, CGAL::Default, Concurrency_tag>::type Tr; typedef typename CGAL::Mesh_triangulation_3<Mesh_domain, CGAL::Default, Concurrency_tag>::type Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3; typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria; typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
@ -111,15 +111,14 @@ void poisson_reconstruction(const PointSet& points, const char* output)
params::facet_size = sm_radius * average_spacing, params::facet_size = sm_radius * average_spacing,
params::facet_distance = sm_distance * average_spacing); params::facet_distance = sm_distance * average_spacing);
Mesh_domain domain = Mesh_domain::create_implicit_mesh_domain(function, bsphere, Mesh_domain domain = Mesh_domain::create_Poisson_mesh_domain(function, bsphere,
params::relative_error_bound(sm_dichotomy_error / sm_sphere_radius)); params::relative_error_bound(sm_dichotomy_error / sm_sphere_radius));
// Generates surface mesh with manifold option // Generates surface mesh with manifold option
std::cout << "Start meshing..."; std::cout << "Start meshing...";
std::cout.flush(); std::cout.flush();
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria, C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria,
params::no_exude() params::surface_only()
.no_perturb()
.manifold_with_boundary()); .manifold_with_boundary());
time.stop(); time.stop();

View File

@ -18,7 +18,7 @@
#include <CGAL/Mesh_triangulation_3.h> #include <CGAL/Mesh_triangulation_3.h>
#include <CGAL/Mesh_complex_3_in_triangulation_3.h> #include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <CGAL/Mesh_criteria_3.h> #include <CGAL/Mesh_criteria_3.h>
#include <CGAL/Labeled_mesh_domain_3.h> #include <CGAL/Poisson_mesh_domain_3.h>
#include <CGAL/make_mesh_3.h> #include <CGAL/make_mesh_3.h>
#include <CGAL/facets_in_complex_3_to_triangle_mesh.h> #include <CGAL/facets_in_complex_3_to_triangle_mesh.h>
@ -56,7 +56,7 @@ typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
typedef CGAL::Poisson_reconstruction_function<Kernel> Poisson_reconstruction_function; typedef CGAL::Poisson_reconstruction_function<Kernel> Poisson_reconstruction_function;
// Mesh_3 // Mesh_3
typedef CGAL::Labeled_mesh_domain_3<Kernel> Mesh_domain; typedef CGAL::Poisson_mesh_domain_3<Kernel> Mesh_domain;
typedef typename CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr; typedef typename CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3; typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria; typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
@ -327,12 +327,12 @@ int main(int argc, char * argv[])
<< " manifold_with_boundary()\n"; << " manifold_with_boundary()\n";
// Defines mesh domain // Defines mesh domain
Mesh_domain domain = Mesh_domain::create_implicit_mesh_domain(function, bsphere, Mesh_domain domain = Mesh_domain::create_Poisson_mesh_domain(function, bsphere,
CGAL::parameters::relative_error_bound(sm_dichotomy_error / sm_sphere_radius)); CGAL::parameters::relative_error_bound(sm_dichotomy_error / sm_sphere_radius));
// Generates mesh with manifold option // Generates mesh with manifold option
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria, C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria,
CGAL::parameters::no_exude().no_perturb() CGAL::parameters::surface_only()
.manifold_with_boundary()); .manifold_with_boundary());
// Prints status // Prints status

View File

@ -5,7 +5,7 @@
#include <CGAL/Mesh_triangulation_3.h> #include <CGAL/Mesh_triangulation_3.h>
#include <CGAL/Mesh_complex_3_in_triangulation_3.h> #include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <CGAL/Mesh_criteria_3.h> #include <CGAL/Mesh_criteria_3.h>
#include <CGAL/Labeled_mesh_domain_3.h> #include <CGAL/Poisson_mesh_domain_3.h>
#include <CGAL/make_mesh_3.h> #include <CGAL/make_mesh_3.h>
#include <CGAL/facets_in_complex_3_to_triangle_mesh.h> #include <CGAL/facets_in_complex_3_to_triangle_mesh.h>
@ -32,7 +32,7 @@ typedef Kernel::Sphere_3 Sphere;
typedef std::vector<Point_with_normal> PointList; typedef std::vector<Point_with_normal> PointList;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron; typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
typedef CGAL::Poisson_reconstruction_function<Kernel> Poisson_reconstruction_function; typedef CGAL::Poisson_reconstruction_function<Kernel> Poisson_reconstruction_function;
typedef CGAL::Labeled_mesh_domain_3<Kernel> Mesh_domain; typedef CGAL::Poisson_mesh_domain_3<Kernel> Mesh_domain;
typedef CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr; typedef CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3; typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria; typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
@ -85,12 +85,12 @@ int main(void)
CGAL::parameters::facet_distance = sm_distance*average_spacing); CGAL::parameters::facet_distance = sm_distance*average_spacing);
// Defines mesh domain // Defines mesh domain
Mesh_domain domain = Mesh_domain::create_implicit_mesh_domain(function, bsphere, Mesh_domain domain = Mesh_domain::create_Poisson_mesh_domain(function, bsphere,
CGAL::parameters::relative_error_bound(sm_dichotomy_error / sm_sphere_radius)); CGAL::parameters::relative_error_bound(sm_dichotomy_error / sm_sphere_radius));
// Generates mesh with manifold option // Generates mesh with manifold option
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria, C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria,
CGAL::parameters::no_exude().no_perturb() CGAL::parameters::surface_only()
.manifold_with_boundary()); .manifold_with_boundary());
const Tr& tr = c3t3.triangulation(); const Tr& tr = c3t3.triangulation();

View File

@ -0,0 +1,409 @@
// Copyright (c) 2025 GeometryFactory (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Sven Oesau
#ifndef CGAL_POISSON_MESH_DOMAIN_3_H
#define CGAL_POISSON_MESH_DOMAIN_3_H
#include <CGAL/license/Poisson_surface_reconstruction_3.h>
#include <CGAL/Labeled_mesh_domain_3.h>
#include <CGAL/Poisson_reconstruction_function.h>
namespace CGAL {
/*!
\ingroup PkgPoissonSurfaceReconstruction3Ref
\brief The class `Poisson_mesh_domain_3` derives from `Labeled_mesh_domain_3` for the handling of `Poisson_reconstruction_function`.
This class has a constructor taking a labeling function. It has also a static template member
function that acts as named constructor:
<ul><li>`create_Poisson_mesh_domain()`</li>, to create a domain from a `Poisson_reconstruction_function`</ul>
\tparam BGT is a geometric traits class that provides
the basic operations to implement intersection tests and intersection computations through a bisection
method. This parameter must be instantiated with a model of the concept `BisectionGeometricTraits_3`.
\cgalModels{MeshDomain_3}
\sa `CGAL::Labeled_mesh_domain_3`
\sa `CGAL::make_mesh_3()`
*/
template<class BGT>
class Poisson_mesh_domain_3
#ifndef DOXYGEN_RUNNING
: public Labeled_mesh_domain_3<BGT>
#endif
{
public:
using Base = Labeled_mesh_domain_3<BGT>;
typedef typename Base::Subdomain Subdomain;
typedef typename Base::Subdomain_index Subdomain_index;
typedef typename Base::Surface_patch_index Surface_patch_index;
typedef typename Base::Intersection Intersection;
// Type of indexes for cells of the input complex
typedef std::optional<Surface_patch_index> Surface_patch;
// Type of indexes to characterize the lowest dimensional face of the input
// complex on which a vertex lie
typedef typename CGAL::Mesh_3::internal::Index_generator<Subdomain_index, Surface_patch_index>::Index Index;
// Geometric object types
#ifdef DOXYGEN_RUNNING
/// \name Types imported from the geometric traits class
///@{
/// The point type of the geometric traits class
typedef typename Geom_traits::Point_3 Point_3;
/// The sphere type of the geometric traits class
typedef typename Geom_traits::Sphere_3 Sphere_3;
/// The iso-cuboid type of the geometric traits class
typedef typename Geom_traits::Iso_cuboid_3 Iso_cuboid_3;
/// The bounding box type
typedef CGAL::Bbox_3 Bbox_3;
/// The number type (a field type) of the geometric traits class
typedef typename Geom_traits::FT FT;
/// The ray type of the geometric traits class
typedef typename Geom_traits::Ray_3 Ray_3;
/// The line type of the geometric traits class
typedef typename Geom_traits::Line_3 Line_3;
/// The segment type of the geometric traits class
typedef typename Geom_traits::Segment_3 Segment_3;
/// The Poisson function type
typedef CGAL::Poisson_reconstruction_function<Geom_traits> Function;
///@}
#else
/// The point type of the geometric traits class
typedef typename BGT::Point_3 Point_3;
/// The sphere type of the geometric traits class
typedef typename BGT::Sphere_3 Sphere_3;
/// The iso-cuboid type of the geometric traits class
typedef typename BGT::Iso_cuboid_3 Iso_cuboid_3;
/// The bounding box type
typedef CGAL::Bbox_3 Bbox_3;
/// The number type (a field type) of the geometric traits class
typedef typename BGT::FT FT;
/// The ray type of the geometric traits class
typedef typename BGT::Ray_3 Ray_3;
/// The line type of the geometric traits class
typedef typename BGT::Line_3 Line_3;
/// The segment type of the geometric traits class
typedef typename BGT::Segment_3 Segment_3;
/// The Poisson function type
typedef CGAL::Poisson_reconstruction_function<BGT> Function;
#endif
Function poisson_function;
/// \name Creation
/// @{
/*! \brief Construction from a function, a bounding object and a relative error bound.
*
* \tparam Bounding_object either a bounding sphere (of type `Sphere_3`), a bounding box (type `Bbox_3`),
* or a bounding `Iso_cuboid_3`
* \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
*
* \param function the Poisson reconstruction function
* \param bounding_object the bounding object bounding the meshable space.
* \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below:
*
* \cgalNamedParamsBegin
* \cgalParamNBegin{relative_error_bound}
* \cgalParamDescription{the relative error bound used to compute intersection points between the implicit surface and query segments.
* The bisection is stopped when the length of the intersected segment is less than the product
* of `relative_error_bound` by the diameter of the bounding object.}
* \cgalParamDefault{FT(1e-3)}
* \cgalParamNEnd
* \cgalNamedParamsEnd
*/
template<typename Bounding_object, typename CGAL_NP_TEMPLATE_PARAMETERS>
Poisson_mesh_domain_3(const Function& function,
const Bounding_object& bounding_object,
const CGAL_NP_CLASS& np = parameters::default_values()
#ifndef DOXYGEN_RUNNING
, typename std::enable_if<!is_named_function_parameter<Function>>::type* = nullptr
#endif // DOXYGEN_RUNNING
)
: Base(make_implicit_to_labeling_function_wrapper<BGT>(function), bounding_object, np),
poisson_function(function)
{}
/*! \brief Construction from a function, a bounding object and a relative error bound.
*
* \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
*
* \param function the Poisson reconstruction function
* \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below:
*
* \cgalNamedParamsBegin
* \cgalParamNBegin{relative_error_bound}
* \cgalParamDescription{the relative error bound used to compute intersection points between the implicit surface and query segments.
* The bisection is stopped when the length of the intersected segment is less than the product
* of `relative_error_bound` by the diameter of the bounding object.}
* \cgalParamDefault{FT(1e-3)}
* \cgalParamNEnd
* \cgalNamedParamsEnd
*/
template<typename CGAL_NP_TEMPLATE_PARAMETERS>
Poisson_mesh_domain_3(const Function & function,
const CGAL_NP_CLASS& np = parameters::default_values()
#ifndef DOXYGEN_RUNNING
, typename std::enable_if<!is_named_function_parameter<Function>>::type * = nullptr
#endif // DOXYGEN_RUNNING
)
: Base(make_implicit_to_labeling_function_wrapper<BGT>(function), function.bounding_sphere(), np),
poisson_function(function)
{}
///@}
#ifndef DOXYGEN_RUNNING
template<typename CGAL_NP_TEMPLATE_PARAMETERS_NO_DEFAULT>
Poisson_mesh_domain_3(const CGAL_NP_CLASS& np)
: Base(np)
{}
// Overload handling parameters passed with operator=
template<typename CGAL_NP_TEMPLATE_PARAMETERS_NO_DEFAULT_1,
typename CGAL_NP_TEMPLATE_PARAMETERS_NO_DEFAULT_2,
typename ... NP>
Poisson_mesh_domain_3(const Function& function,
const CGAL_NP_CLASS_1& np1,
const CGAL_NP_CLASS_2& np2,
const NP& ... nps)
: Base(internal_np::combine_named_parameters(
CGAL::parameters::function(make_implicit_to_labeling_function_wrapper<BGT>(function)), np1, np2, nps...)),
poisson_function(function)
{}
#endif
/// \name Creation of domains from Poisson implicit functions
/// @{
/*! \brief Construction from a Poisson implicit function
*
* This static method is a <em>named constructor</em>. It constructs a domain
* whose bounding surface is described implicitly as the zero level set of a
* function. The domain to be discretized is assumed to be the domain where
* the function has negative values.
*
* \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
* \tparam Bounding_object either a bounding sphere (of type `Sphere_3`), a bounding box (type `Bbox_3`),
* or a bounding `Iso_cuboid_3` which is required to circumscribe
* the surface and to have its center inside the domain.
*
* \param function the Poisson reconstruction function
* \param bounding_object object bounding the meshable domain and its center is inside the domain.
* \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below:
*
* \cgalNamedParamsBegin
* \cgalParamNBegin{relative_error_bound}
* \cgalParamDescription{ is the relative error
* bound, relative to the diameter of the box of the image.}
* \cgalParamDefault{FT(1e-3)}
* \cgalParamNEnd
* \cgalNamedParamsEnd
*
*/
template<typename Bounding_object, typename CGAL_NP_TEMPLATE_PARAMETERS>
static Poisson_mesh_domain_3 create_Poisson_mesh_domain(const Function& function,
const Bounding_object& bounding_object,
const CGAL_NP_CLASS& np = parameters::default_values()
#ifndef DOXYGEN_RUNNING
,typename std::enable_if<!is_named_function_parameter<Function>>::type* = nullptr
#endif
)
{
using parameters::get_parameter;
using parameters::choose_parameter;
FT relative_error_bound_ = choose_parameter(get_parameter(np, internal_np::error_bound), FT(1e-3));
CGAL::Random* p_rng_ = choose_parameter(get_parameter(np, internal_np::rng), nullptr);
auto null_subdomain_index_ = choose_parameter(get_parameter(np, internal_np::null_subdomain_index_param), Null_functor());
auto construct_surface_patch_index_ = choose_parameter(get_parameter(np, internal_np::surface_patch_index), Null_functor());
return Poisson_mesh_domain_3(function,
bounding_object,
CGAL::parameters::relative_error_bound(relative_error_bound_)
.function(make_implicit_to_labeling_function_wrapper<BGT>(function))
.p_rng(p_rng_)
.null_subdomain_index(Base::create_null_subdomain_index(null_subdomain_index_))
.construct_surface_patch_index(Base::create_construct_surface_patch_index(construct_surface_patch_index_)));
}
/// @}
#ifndef DOXYGEN_RUNNING
template<typename CGAL_NP_TEMPLATE_PARAMETERS>
static Poisson_mesh_domain_3 create_Poisson_mesh_domain(const CGAL_NP_CLASS& np) {
using parameters::get_parameter;
static_assert(!parameters::is_default_parameter<CGAL_NP_CLASS, internal_np::function_param_t>::value, "Value for required parameter not found");
static_assert(!parameters::is_default_parameter<CGAL_NP_CLASS, internal_np::bounding_object_param_t>::value, "Value for required parameter not found");
return create_Poisson_mesh_domain(get_parameter(np, internal_np::function_param),
get_parameter(np, internal_np::bounding_object_param),
np);
}
// Overload handling parameters passed with operator=
template<typename CGAL_NP_TEMPLATE_PARAMETERS_NO_DEFAULT_1,
typename CGAL_NP_TEMPLATE_PARAMETERS_NO_DEFAULT_2,
typename ... NP>
static Poisson_mesh_domain_3 create_Poisson_mesh_domain(const CGAL_NP_CLASS_1& np1,
const CGAL_NP_CLASS_2& np2,
const NP& ... nps)
{
return create_Poisson_mesh_domain(internal_np::combine_named_parameters(np1, np2, nps...));
}
#endif
/*
* Returns a point in the intersection of the primitive `type`
* with some boundary surface.
* `Type` is either `Segment_3`, `Ray_3` or `Line_3`.
*/
struct Construct_intersection
{
Construct_intersection(const Poisson_mesh_domain_3& domain) : domain_(domain) {}
Intersection operator()(const Segment_3& s) const
{
#ifndef CGAL_MESH_3_NO_LONGER_CALLS_DO_INTERSECT_3
CGAL_precondition(r_domain_.do_intersect_surface_object()(s) != std::nullopt);
#endif // NOT CGAL_MESH_3_NO_LONGER_CALLS_DO_INTERSECT_3
return this->operator()(s.source(), s.target());
}
Intersection operator()(const Ray_3& r) const
{
return clip_to_segment(r);
}
Intersection operator()(const Line_3& l) const
{
return clip_to_segment(l);
}
private:
/*
* Returns a point in the intersection of `[a,b]` with the surface
* `a` must be the source point, and `b` the out point. It is important
* because it drives bisection cuts.
* Indeed, the returned point is the first intersection of `[a,b]`
* with a subdomain surface.
*
* The difference from the Labeled_mesh_domain_3::Construct_intersection is that
* the underlying Delaunay triangulation in the Poisson function is used for the bisection.
*/
Intersection operator()(const Point_3& a, const Point_3& b) const
{
// Functors
typename BGT::Compute_squared_distance_3 squared_distance =
BGT().compute_squared_distance_3_object();
typename BGT::Construct_midpoint_3 midpoint =
BGT().construct_midpoint_3_object();
// Non const points
Point_3 p1 = a;
Point_3 p2 = b;
Point_3 mid = midpoint(p1, p2);
FT value_at_p1, value_at_p2;
typename Function::Cell_handle c1, c2;
bool c1_is_inf, c2_is_inf;
std::tie(value_at_p1, c1, c1_is_inf) = domain_.poisson_function.special_func(p1);
std::tie(value_at_p2, c2, c2_is_inf) = domain_.poisson_function.special_func(p2);
Subdomain_index label_at_p1 = (value_at_p1 < 0) ? 1 : 0;
Subdomain_index label_at_p2 = (value_at_p2 < 0) ? 1 : 0;
// If both extremities are in the same subdomain,
// there is no intersection.
// Should only be able to happen during initial point generation.
if(label_at_p1 == label_at_p2)
return Intersection();
// Else lets find a point (by bisection)
// Bisection ends when the point is nearer from surface than the error bound
while(true) {
if(c1 == c2) {
if(c1_is_inf) {
std::cout << "Intersection(): c1 == c2 and inf!" << std::endl;
return Intersection();
} else {
const Surface_patch_index sp_index = domain_.make_surface_index(label_at_p1, label_at_p2);
const Index index = domain_.index_from_surface_patch_index(sp_index);
return Intersection(Point_3(ORIGIN + ((value_at_p2 * (p1 - ORIGIN)) - (value_at_p1 * (p2 - ORIGIN))) /
(value_at_p2 - value_at_p1)), index, 2);
}
}
mid = midpoint(p1, p2);
// If the two points are enough close, then we return midpoint
if ( squared_distance(p1, p2) < domain_.squared_error_bound_ )
{
CGAL_assertion(value_at_p1 * value_at_p2 <= 0);
const Surface_patch_index sp_index = domain_.make_surface_index(label_at_p1, label_at_p2);
const Index index = domain_.index_from_surface_patch_index(sp_index);
return Intersection(mid, index, 2);
}
// Cannot be const: those values are modified below.
FT value_at_mid;
typename Function::Cell_handle c_at_mid;
bool c_is_inf;
std::tie(value_at_mid, c_at_mid, c_is_inf) = domain_.poisson_function.special_func(mid);
Subdomain_index label_at_mid = (value_at_mid < 0) ? 1 : 0;
// Else we must go on
// Here we consider that p1(a) is the source point. Thus, we keep p1 and
// change p2 if f(p1)!=f(p2).
// That allows us to find the first intersection from a of [a,b] with
// a surface.
if(label_at_p1 != label_at_mid && !(domain_.null(label_at_p1) && domain_.null(label_at_mid)))
{
p2 = mid;
value_at_p2 = value_at_mid;
label_at_p2 = label_at_mid;
}
else
{
p1 = mid;
value_at_p1 = value_at_mid;
label_at_p1 = label_at_mid;
}
}
}
// Clips `query` to a segment `s`, and call `operator()(s)`
template<typename Query>
Intersection clip_to_segment(const Query& query) const
{
const auto clipped = CGAL::intersection(query, domain_.bbox_);
if (clipped)
if (const Segment_3* s = std::get_if<Segment_3>(&*clipped))
return this->operator()(*s);
return Intersection();
}
const Poisson_mesh_domain_3& domain_;
};
// Returns Construct_intersection object
Construct_intersection construct_intersection_object() const
{
return Construct_intersection(*this);
}
}; // end class Poisson_mesh_domain_3
} // end namespace CGAL
#endif // CGAL_LABELED_MESH_DOMAIN_3_H

View File

@ -460,7 +460,7 @@ public:
// Add a pass of Delaunay refinement. // Add a pass of Delaunay refinement.
// //
// In that pass, the sizing field, of the refinement process of the // In that pass, the sizing field, of the refinement process of the
// triangulation, is based on the result of a poisson function with a // triangulation, is based on the result of a Poisson function with a
// sample of the input points. The ratio is 'approximation_ratio'. // sample of the input points. The ratio is 'approximation_ratio'.
// //
// For optimization reasons, the cell criteria of the refinement // For optimization reasons, the cell criteria of the refinement

View File

@ -17,7 +17,7 @@
#include <CGAL/Mesh_triangulation_3.h> #include <CGAL/Mesh_triangulation_3.h>
#include <CGAL/Mesh_complex_3_in_triangulation_3.h> #include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <CGAL/Mesh_criteria_3.h> #include <CGAL/Mesh_criteria_3.h>
#include <CGAL/Labeled_mesh_domain_3.h> #include <CGAL/Poisson_mesh_domain_3.h>
#include <CGAL/make_mesh_3.h> #include <CGAL/make_mesh_3.h>
#include <CGAL/facets_in_complex_3_to_triangle_mesh.h> #include <CGAL/facets_in_complex_3_to_triangle_mesh.h>
#include <CGAL/Poisson_reconstruction_function.h> #include <CGAL/Poisson_reconstruction_function.h>
@ -99,7 +99,7 @@ namespace CGAL {
typedef typename Kernel::FT FT; typedef typename Kernel::FT FT;
typedef CGAL::Poisson_reconstruction_function<Kernel> Poisson_reconstruction_function; typedef CGAL::Poisson_reconstruction_function<Kernel> Poisson_reconstruction_function;
typedef CGAL::Labeled_mesh_domain_3<Kernel> Mesh_domain; typedef CGAL::Poisson_mesh_domain_3<Kernel> Mesh_domain;
typedef typename CGAL::Mesh_triangulation_3<Mesh_domain, CGAL::Default, Sequential_tag>::type Tr; typedef typename CGAL::Mesh_triangulation_3<Mesh_domain, CGAL::Default, Sequential_tag>::type Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3; typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria; typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
@ -115,7 +115,7 @@ namespace CGAL {
FT sm_sphere_radius = 5.0 * radius; FT sm_sphere_radius = 5.0 * radius;
FT sm_dichotomy_error = sm_distance * spacing / 1000.0; FT sm_dichotomy_error = sm_distance * spacing / 1000.0;
Mesh_domain domain = Mesh_domain::create_implicit_mesh_domain(function, Sphere(inner_point, sm_sphere_radius), Mesh_domain domain = Mesh_domain::create_Poisson_mesh_domain(function, Sphere(inner_point, sm_sphere_radius),
CGAL::parameters::relative_error_bound(sm_dichotomy_error / sm_sphere_radius)); CGAL::parameters::relative_error_bound(sm_dichotomy_error / sm_sphere_radius));
Mesh_criteria criteria(CGAL::parameters::facet_angle = sm_angle, Mesh_criteria criteria(CGAL::parameters::facet_angle = sm_angle,
@ -134,7 +134,7 @@ namespace CGAL {
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria, C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria,
turn_tag_into_mesh_3_manifold_option(tag) turn_tag_into_mesh_3_manifold_option(tag)
.no_exude().no_perturb() .surface_only()
.manifold_with_boundary()); .manifold_with_boundary());
const auto& tr = c3t3.triangulation(); const auto& tr = c3t3.triangulation();

View File

@ -5,6 +5,8 @@ project(Poisson_surface_reconstruction_3_Tests)
# Find CGAL # Find CGAL
find_package(CGAL REQUIRED) find_package(CGAL REQUIRED)
find_package(TBB QUIET)
include(CGAL_TBB_support)
# VisualC++ optimization for applications dealing with large data # VisualC++ optimization for applications dealing with large data
if(MSVC) if(MSVC)
@ -22,15 +24,25 @@ find_package(Eigen3 3.1.0 QUIET) #(requires 3.1.0 or greater)
include(CGAL_Eigen3_support) include(CGAL_Eigen3_support)
if(TARGET CGAL::Eigen3_support) if(TARGET CGAL::Eigen3_support)
# Executables that require Eigen 3.1 # Executables that require Eigen 3.1
create_single_source_cgal_program("poisson_reconstruction_test_surface_mesher.cpp") if(TARGET CGAL::TBB_support)
target_link_libraries(poisson_reconstruction_test_surface_mesher PRIVATE CGAL::Eigen3_support) create_single_source_cgal_program("poisson_reconstruction_test_surface_mesher.cpp")
target_link_libraries(poisson_reconstruction_test_surface_mesher PRIVATE CGAL::Eigen3_support CGAL::TBB_support)
create_single_source_cgal_program("poisson_reconstruction_test_mesh_3.cpp") create_single_source_cgal_program("poisson_reconstruction_test_mesh_3.cpp")
target_link_libraries(poisson_reconstruction_test_mesh_3 PRIVATE CGAL::Eigen3_support) target_link_libraries(poisson_reconstruction_test_mesh_3 PRIVATE CGAL::Eigen3_support CGAL::TBB_support)
create_single_source_cgal_program("compare_mesh_3_vs_Poisson_implicit_surface_3.cpp") create_single_source_cgal_program("compare_mesh_3_vs_Poisson_implicit_surface_3.cpp")
target_link_libraries(compare_mesh_3_vs_Poisson_implicit_surface_3 PRIVATE CGAL::Eigen3_support) target_link_libraries(compare_mesh_3_vs_Poisson_implicit_surface_3 PRIVATE CGAL::Eigen3_support CGAL::TBB_support)
else()
create_single_source_cgal_program("poisson_reconstruction_test_surface_mesher.cpp")
target_link_libraries(poisson_reconstruction_test_surface_mesher PRIVATE CGAL::Eigen3_support)
create_single_source_cgal_program("poisson_reconstruction_test_mesh_3.cpp")
target_link_libraries(poisson_reconstruction_test_mesh_3 PRIVATE CGAL::Eigen3_support)
create_single_source_cgal_program("compare_mesh_3_vs_Poisson_implicit_surface_3.cpp")
target_link_libraries(compare_mesh_3_vs_Poisson_implicit_surface_3 PRIVATE CGAL::Eigen3_support)
endif()
else() else()
message("NOTICE: Tests in this directory require Eigen 3.1 (or greater), and will not be compiled.") message("NOTICE: Tests in this directory require Eigen 3.1 (or greater), and will not be compiled.")
endif() endif()

View File

@ -14,6 +14,7 @@
#include <CGAL/Mesh_complex_3_in_triangulation_3.h> #include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <CGAL/Mesh_criteria_3.h> #include <CGAL/Mesh_criteria_3.h>
#include <CGAL/Labeled_mesh_domain_3.h> #include <CGAL/Labeled_mesh_domain_3.h>
#include <CGAL/Poisson_mesh_domain_3.h>
#include <CGAL/make_mesh_3.h> #include <CGAL/make_mesh_3.h>
#include <CGAL/facets_in_complex_3_to_triangle_mesh.h> #include <CGAL/facets_in_complex_3_to_triangle_mesh.h>
@ -61,7 +62,12 @@ typedef CGAL::Surface_mesh_default_triangulation_3 STr;
typedef CGAL::Surface_mesh_complex_2_in_triangulation_3<STr> C2t3; typedef CGAL::Surface_mesh_complex_2_in_triangulation_3<STr> C2t3;
// Mesh_3 // Mesh_3
typedef CGAL::Labeled_mesh_domain_3<Kernel> Mesh_domain; typedef CGAL::Labeled_mesh_domain_3<Kernel> LMesh_domain;
typedef typename CGAL::Mesh_triangulation_3<LMesh_domain>::type LTr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<LTr> LC3t3;
typedef CGAL::Mesh_criteria_3<LTr> LMesh_criteria;
typedef CGAL::Poisson_mesh_domain_3<Kernel> Mesh_domain;
typedef typename CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr; typedef typename CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3; typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria; typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
@ -290,10 +296,10 @@ int main(int argc, char * argv[])
} }
#endif #endif
task_timer.stop();
// Prints status // Prints status
std::cerr << "Total implicit function (triangulation+refinement+solver): " << task_timer.time() << " seconds\n"; std::cerr << "Total implicit function (triangulation+refinement+solver): " << task_timer.time() << " seconds\n";
task_timer.reset();
//*************************************** //***************************************
// Surface mesh generation // Surface mesh generation
@ -331,47 +337,88 @@ int main(int argc, char * argv[])
const double implicit_function_time = reconstruction_timer.time(); const double implicit_function_time = reconstruction_timer.time();
reconstruction_timer.reset(); reconstruction_timer.reset();
// MESH_3 // MESH_3 labeled
{ {
// Defines generation criteria
LMesh_criteria criteria(CGAL::parameters::facet_angle = fangle, CGAL::parameters::facet_size = fsize,
CGAL::parameters::facet_distance = fdist);
std::cout << "* Use Mesh_3 implicit *" << std::endl;
CGAL::Real_timer meshing_timer; CGAL::Real_timer meshing_timer;
meshing_timer.start(); meshing_timer.start();
std::cout << "* Use Mesh_3 *" << std::endl;
// Defines generation criteria // Defines generation criteria
Mesh_criteria criteria(CGAL::parameters::facet_angle = fangle,
CGAL::parameters::facet_size = fsize,
CGAL::parameters::facet_distance = fdist);
// Defines mesh domain // Defines mesh domain
Mesh_domain domain = Mesh_domain::create_implicit_mesh_domain(function, bsphere, LMesh_domain domain = LMesh_domain::create_implicit_mesh_domain(
CGAL::parameters::relative_error_bound(sm_dichotomy_error / sm_sphere_radius)); function, bsphere, CGAL::parameters::relative_error_bound(sm_dichotomy_error / sm_sphere_radius));
// Generates mesh with manifold option // Generates mesh with manifold option
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria, LC3t3 c3t3 =
CGAL::parameters::no_exude().no_perturb() CGAL::make_mesh_3<LC3t3>(domain, criteria, CGAL::parameters::surface_only().manifold_with_boundary());
.manifold_with_boundary());
meshing_timer.stop(); meshing_timer.stop();
const Tr& tr = c3t3.triangulation(); const LTr& tr = c3t3.triangulation();
// Prints status // Prints status
std::cerr << "Mesh_3 meshing: " << meshing_timer.time() << " seconds, " std::cerr << "Mesh_3 meshing: " << meshing_timer.time() << " seconds, " << tr.number_of_vertices()
<< tr.number_of_vertices() << " output vertices" << " output vertices" << std::endl;
<< std::endl;
if (tr.number_of_vertices() == 0) if(tr.number_of_vertices() == 0)
return EXIT_FAILURE; return EXIT_FAILURE;
// Prints total reconstruction duration // Prints total reconstruction duration
reconstruction_timer.stop();
std::cerr << "Total reconstruction (implicit function + meshing): " std::cerr << "Total reconstruction (implicit function + meshing): "
<< (implicit_function_time + reconstruction_timer.time()) << " seconds\n"; << (implicit_function_time + meshing_timer.time()) << " seconds\n";
reconstruction_timer.reset();
// Converts to polyhedron // Converts to polyhedron
Polyhedron output_mesh; Polyhedron output_mesh;
CGAL::facets_in_complex_3_to_triangle_mesh(c3t3, output_mesh); CGAL::facets_in_complex_3_to_triangle_mesh(c3t3, output_mesh);
std::ofstream out(output_basename + "_mesh_3.off"); std::ofstream out(output_basename + "_implicit_mesh_3.off");
out << output_mesh;
out.close();
}
// MESH_3 poisson
{
// Defines generation criteria
Mesh_criteria criteria(CGAL::parameters::facet_angle = fangle, CGAL::parameters::facet_size = fsize,
CGAL::parameters::facet_distance = fdist);
std::cout << "* Use Mesh_3 poisson *" << std::endl;
CGAL::Real_timer meshing_timer;
meshing_timer.start();
// Defines generation criteria
// Defines mesh domain
Mesh_domain domain = Mesh_domain::create_Poisson_mesh_domain(
function, bsphere, CGAL::parameters::relative_error_bound(sm_dichotomy_error / sm_sphere_radius));
// Generates mesh with manifold option
C3t3 c3t3 =
CGAL::make_mesh_3<C3t3>(domain, criteria, CGAL::parameters::surface_only().manifold_with_boundary());
meshing_timer.stop();
const Tr& tr = c3t3.triangulation();
// Prints status
std::cerr << "Mesh_3 meshing: " << meshing_timer.time() << " seconds, " << tr.number_of_vertices()
<< " output vertices" << std::endl;
if(tr.number_of_vertices() == 0)
return EXIT_FAILURE;
// Prints total reconstruction duration
std::cerr << "Total reconstruction (poisson function + meshing): "
<< (implicit_function_time + meshing_timer.time()) << " seconds\n";
// Converts to polyhedron
Polyhedron output_mesh;
CGAL::facets_in_complex_3_to_triangle_mesh(c3t3, output_mesh);
std::ofstream out(output_basename + "_poisson_mesh_3.off");
out << output_mesh; out << output_mesh;
out.close(); out.close();
} }
@ -380,7 +427,6 @@ int main(int argc, char * argv[])
{ {
CGAL::Real_timer meshing_timer; CGAL::Real_timer meshing_timer;
meshing_timer.start(); meshing_timer.start();
reconstruction_timer.start();
std::cout << "\n\n* Use Surface_mesher with Poisson_implicit_surface_3 *" << std::endl; std::cout << "\n\n* Use Surface_mesher with Poisson_implicit_surface_3 *" << std::endl;
Surface_3 surface(function, Surface_3 surface(function,
@ -408,9 +454,8 @@ int main(int argc, char * argv[])
return EXIT_FAILURE; return EXIT_FAILURE;
// Prints total reconstruction duration // Prints total reconstruction duration
reconstruction_timer.stop();
std::cerr << "Total reconstruction (implicit function + meshing): " std::cerr << "Total reconstruction (implicit function + meshing): "
<< (implicit_function_time + reconstruction_timer.time()) << " seconds\n"; << (implicit_function_time + meshing_timer.time()) << " seconds\n";
Polyhedron output_mesh; Polyhedron output_mesh;
CGAL::facets_in_complex_2_to_triangle_mesh(c2t3, output_mesh); CGAL::facets_in_complex_2_to_triangle_mesh(c2t3, output_mesh);

View File

@ -18,6 +18,7 @@
#include <CGAL/Mesh_complex_3_in_triangulation_3.h> #include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <CGAL/Mesh_criteria_3.h> #include <CGAL/Mesh_criteria_3.h>
#include <CGAL/Labeled_mesh_domain_3.h> #include <CGAL/Labeled_mesh_domain_3.h>
#include <CGAL/Poisson_mesh_domain_3.h>
#include <CGAL/make_mesh_3.h> #include <CGAL/make_mesh_3.h>
#include <CGAL/facets_in_complex_3_to_triangle_mesh.h> #include <CGAL/facets_in_complex_3_to_triangle_mesh.h>
@ -57,12 +58,18 @@ typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
// Poisson implicit function // Poisson implicit function
typedef CGAL::Poisson_reconstruction_function<Kernel> Poisson_reconstruction_function; typedef CGAL::Poisson_reconstruction_function<Kernel> Poisson_reconstruction_function;
// Mesh_3 // Mesh_3 using Labeled_mesh_domain_3
typedef CGAL::Labeled_mesh_domain_3<Kernel> Mesh_domain; typedef CGAL::Labeled_mesh_domain_3<Kernel> Mesh_domain;
typedef CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr; typedef CGAL::Mesh_triangulation_3<Mesh_domain>::type Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3; typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria; typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
// Mesh_3 using Poisson_mesh_domain_3
typedef CGAL::Poisson_mesh_domain_3<Kernel> Poisson_mesh_domain;
typedef CGAL::Mesh_triangulation_3<Poisson_mesh_domain>::type Poisson_Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<Poisson_Tr> Poisson_C3t3;
typedef CGAL::Mesh_criteria_3<Poisson_Tr> Poisson_mesh_criteria;
namespace params = CGAL::parameters; namespace params = CGAL::parameters;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -171,7 +178,6 @@ int main(int argc, char * argv[])
<< task_timer.time() << " seconds, " << task_timer.time() << " seconds, "
<< (memory>>20) << " Mb allocated" << (memory>>20) << " Mb allocated"
<< std::endl; << std::endl;
task_timer.reset();
//*************************************** //***************************************
// Checks requirements // Checks requirements
@ -192,14 +198,14 @@ int main(int argc, char * argv[])
continue; continue;
} }
CGAL::Timer reconstruction_timer; reconstruction_timer.start();
//*************************************** //***************************************
// Computes implicit function // Computes implicit function
//*************************************** //***************************************
std::cerr << "Computes Poisson implicit function...\n"; std::cerr << "Computes Poisson implicit function...\n";
task_timer.reset();
// Creates implicit function from the read points. // Creates implicit function from the read points.
// Note: this method requires an iterator over points // Note: this method requires an iterator over points
// + property maps to access each point's position and normal. // + property maps to access each point's position and normal.
@ -218,9 +224,9 @@ int main(int argc, char * argv[])
continue; continue;
} }
double poisson_time = task_timer.time();
// Prints status // Prints status
std::cerr << "Total implicit function (triangulation+refinement+solver): " << task_timer.time() << " seconds\n"; std::cerr << "Total implicit function (triangulation+refinement+solver): " << poisson_time << " seconds\n";
task_timer.reset();
//*************************************** //***************************************
// Surface mesh generation // Surface mesh generation
@ -250,45 +256,92 @@ int main(int argc, char * argv[])
FT sm_sphere_radius = 5.0 * radius; FT sm_sphere_radius = 5.0 * radius;
FT sm_dichotomy_error = sm_distance*average_spacing/1000.0; // Dichotomy error must be << sm_distance FT sm_dichotomy_error = sm_distance*average_spacing/1000.0; // Dichotomy error must be << sm_distance
// Defines surface mesh generation criteria {
Mesh_criteria criteria(params::facet_angle = sm_angle, task_timer.reset();
params::facet_size = sm_radius*average_spacing, // Defines surface mesh generation criteria
params::facet_distance = sm_distance*average_spacing); Mesh_criteria criteria(params::facet_angle = sm_angle, params::facet_size = sm_radius * average_spacing,
params::facet_distance = sm_distance * average_spacing);
std::cerr << " make_mesh_3 with sphere center=("<<inner_point << "),\n" std::cerr << " make_mesh_3 with sphere center=(" << inner_point << "),\n"
<< " sphere radius="<<sm_sphere_radius<<",\n" << " sphere radius=" << sm_sphere_radius << ",\n"
<< " angle="<<sm_angle << " degrees,\n" << " angle=" << sm_angle << " degrees,\n"
<< " triangle size="<<sm_radius<<" * average spacing="<<sm_radius*average_spacing<<",\n" << " triangle size=" << sm_radius
<< " distance="<<sm_distance<<" * average spacing="<<sm_distance*average_spacing<<",\n" << " * average spacing=" << sm_radius * average_spacing << ",\n"
<< " dichotomy = distance/"<<sm_distance*average_spacing/sm_dichotomy_error<<",\n" << " distance=" << sm_distance
<< " manifold_with_boundary()\n"; << " * average spacing=" << sm_distance * average_spacing << ",\n"
<< " dichotomy = distance/" << sm_distance * average_spacing / sm_dichotomy_error
<< ",\n"
<< " manifold_with_boundary()\n";
// Generates surface mesh with manifold option // Generates surface mesh with manifold option
Mesh_domain domain = Mesh_domain::create_implicit_mesh_domain(function, bsphere, Mesh_domain domain = Mesh_domain::create_implicit_mesh_domain(
params::relative_error_bound(sm_dichotomy_error / sm_sphere_radius)); function, bsphere, params::relative_error_bound(sm_dichotomy_error / sm_sphere_radius));
C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria, C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria, params::surface_only().manifold_with_boundary());
params::no_exude().no_perturb().manifold_with_boundary());
// Prints status // Prints status
/*long*/ memory = CGAL::Memory_sizer().virtual_size(); /*long*/ memory = CGAL::Memory_sizer().virtual_size();
const Tr& tr = c3t3.triangulation(); const Tr& tr = c3t3.triangulation();
std::cerr << "Surface meshing: " << task_timer.time() << " seconds, " std::cerr << "Surface meshing: " << task_timer.time() << " seconds, " << tr.number_of_vertices()
<< tr.number_of_vertices() << " output vertices, " << " output vertices, " << (memory >> 20) << " Mb allocated" << std::endl;
<< (memory>>20) << " Mb allocated" task_timer.reset();
<< std::endl;
task_timer.reset();
if(tr.number_of_vertices() == 0) { if(tr.number_of_vertices() == 0) {
accumulated_fatal_err = EXIT_FAILURE; accumulated_fatal_err = EXIT_FAILURE;
continue; continue;
}
// Converts to polyhedron
Polyhedron output_mesh;
CGAL::facets_in_complex_3_to_triangle_mesh(c3t3, output_mesh);
// Prints total reconstruction duration
std::cerr << "Total reconstruction using Labeled_mesh_domain_3 (implicit function + meshing): "
<< poisson_time + task_timer.time() << " seconds\n";
} }
// Converts to polyhedron {
Polyhedron output_mesh; task_timer.reset();
CGAL::facets_in_complex_3_to_triangle_mesh(c3t3, output_mesh); // Defines surface mesh generation criteria
Poisson_mesh_criteria criteria(params::facet_angle = sm_angle, params::facet_size = sm_radius * average_spacing,
params::facet_distance = sm_distance * average_spacing);
// Prints total reconstruction duration std::cerr << " make_mesh_3 with sphere center=(" << inner_point << "),\n"
std::cerr << "Total reconstruction (implicit function + meshing): " << reconstruction_timer.time() << " seconds\n"; << " sphere radius=" << sm_sphere_radius << ",\n"
<< " angle=" << sm_angle << " degrees,\n"
<< " triangle size=" << sm_radius
<< " * average spacing=" << sm_radius * average_spacing << ",\n"
<< " distance=" << sm_distance
<< " * average spacing=" << sm_distance * average_spacing << ",\n"
<< " dichotomy = distance/" << sm_distance * average_spacing / sm_dichotomy_error
<< ",\n"
<< " manifold_with_boundary()\n";
// Generates surface mesh with manifold option
Poisson_mesh_domain domain = Poisson_mesh_domain::create_Poisson_mesh_domain(
function, bsphere, params::relative_error_bound(sm_dichotomy_error / sm_sphere_radius));
Poisson_C3t3 c3t3 =
CGAL::make_mesh_3<Poisson_C3t3>(domain, criteria, params::surface_only().manifold_with_boundary());
// Prints status
/* long */ memory = CGAL::Memory_sizer().virtual_size();
const Poisson_Tr& tr = c3t3.triangulation();
std::cerr << "Surface meshing: " << task_timer.time() << " seconds, " << tr.number_of_vertices()
<< " output vertices, " << (memory >> 20) << " Mb allocated" << std::endl;
task_timer.reset();
if(tr.number_of_vertices() == 0) {
accumulated_fatal_err = EXIT_FAILURE;
continue;
}
// Converts to polyhedron
Polyhedron output_mesh;
CGAL::facets_in_complex_3_to_triangle_mesh(c3t3, output_mesh);
// Prints total reconstruction duration
std::cerr << "Total reconstruction using Poisson_mesh_domain_3 (implicit function + meshing): "
<< poisson_time + task_timer.time() << " seconds\n";
}
} // for each input file } // for each input file

View File

@ -219,7 +219,7 @@ void refine_with_plane(PolygonMesh& pm,
/* /*
* \cgalParamNBegin{visitor} * \cgalParamNBegin{visitor}
* \cgalParamDescription{TODO add concept} * \cgalParamDescription{TODO add concept}
* \cgalParamType{reference wrapper recommeded if it has state TODO} * \cgalParamType{reference wrapper recommended if it has state TODO}
* \cgalParamDefault{None} * \cgalParamDefault{None}
* \cgalParamNEnd * \cgalParamNEnd
*/ */

View File

@ -27,7 +27,7 @@
\cgalPkgShortInfoBegin \cgalPkgShortInfoBegin
\cgalPkgSince{6.1} \cgalPkgSince{6.1}
\cgalPkgDependsOn{\ref PkgCombinatorialMaps} \cgalPkgDependsOn{\ref PkgCombinatorialMaps}
\cgalPkgBib{cgal:y-t2} \cgalPkgBib{cgal:ddpt-thss}
\cgalPkgLicense{\ref licensesGPL "GPL"} \cgalPkgLicense{\ref licensesGPL "GPL"}
\cgalPkgDemo{2D Triangulations on Hyperbolic Surfaces,nofilefornow.zip} \cgalPkgDemo{2D Triangulations on Hyperbolic Surfaces,nofilefornow.zip}
\cgalPkgShortInfoEnd \cgalPkgShortInfoEnd