diff --git a/Documentation/doc/biblio/cgal_manual.bib b/Documentation/doc/biblio/cgal_manual.bib index 09fd352dc3c..c15b34e6d08 100644 --- a/Documentation/doc/biblio/cgal_manual.bib +++ b/Documentation/doc/biblio/cgal_manual.bib @@ -387,6 +387,12 @@ Boissonnat} organization={ACM} } +@techreport{ cgal:c-mcctci-95, + title={Marching Cubes 33: Construction of Topologically Correct Isosurfaces}, + author={Chernyaev, Evgeni}, + year={1995} +} + @inproceedings{cgal::c-mssbo-04, author={Chen, L.}, title={{Mesh Smoothing Schemes based on Optimal Delaunay Triangulations}}, @@ -643,6 +649,17 @@ note="Conference version: Symp. on Geometry Processing 2003" , year = 2009 } +@article{cgal:dljjaw-sisp-15, + title={A survey on Implicit Surface Polygonization}, + author={De Ara{\'u}jo, Bruno Rodrigues and Lopes, Daniel S and Jepp, Pauline and Jorge, Joaquim A and Wyvill, Brian}, + journal={ACM Computing Surveys (CSUR)}, + volume={47}, + number={4}, + pages={1--39}, + year={2015}, + publisher={ACM New York, NY, USA} +} + @article{cgal:dfg-cvtaa-99t, title={{Centroidal Voronoi Tessellations: Applications and Algorithms}}, author={Du, Q. and Faber, V. and Gunzburger, M.}, @@ -910,7 +927,7 @@ Teillaud" year = "2003"} @inproceedings{ cgal:g-ctcmi-16, - title={Construction of topologically correct and manifold isosurfaces}, + title={Construction of Topologically Correct and Manifold Isosurfaces}, author={Grosso, Roberto}, booktitle={Computer Graphics Forum}, volume={35}, @@ -1259,6 +1276,14 @@ Teillaud" ,update = "01.06 hoffmann" } +@inproceedings{ cgal:jlsw-dchd-02, + title={Dual contouring of Hermite Data}, + author={Ju, Tao and Losasso, Frank and Schaefer, Scott and Warren, Joe}, + booktitle={Proceedings of the 29th annual conference on Computer graphics and interactive techniques}, + pages={339--346}, + year={2002} +} + @incollection{ cgal:k-dat-96 ,author = "Keffer, T." ,title = "The Design and Architecture of {T}ools.h{\tt ++}" diff --git a/Isosurfacing_3/doc/Isosurfacing_3/Isosurfacing_3.txt b/Isosurfacing_3/doc/Isosurfacing_3/Isosurfacing_3.txt index 40752ae4269..28d1f825a44 100644 --- a/Isosurfacing_3/doc/Isosurfacing_3/Isosurfacing_3.txt +++ b/Isosurfacing_3/doc/Isosurfacing_3/Isosurfacing_3.txt @@ -5,177 +5,242 @@ namespace CGAL { \anchor Chapter_Isosurfacing3 \cgalAutoToc -\author Julian Stahl, Daniel Zint, and Pierre Alliez +\author Mael Rouxel-Labbé, Julian Stahl, Daniel Zint, and Pierre Alliez -\cgalFigureAnchor{isosurfacing_tractor_offset} +\cgalFigureAnchor{Fig_IsosurfacingTeaser}
- +
-\cgalFigureCaptionBegin{isosurfacing_tractor_offset} -%Isosurfacing with different isovalues for the tractor model (courtesy the GrabCAD library). +\cgalFigureCaptionBegin{IsosurfacingTeaser} +%Isosurfacing Teaser [todo]. \cgalFigureCaptionEnd -\section secmyintroduction Introduction +\section SecIntroduction Introduction -%Isosurfacing, also referred to as isosurface extraction, involves the generation of an approximate isosurface from a sampled 3D scalar field. The output isosurface may consist of a single or of multiple, disjoint connected components. %Isosurfacing is commonly required for volume visualization or simulation of physical phenomena. +Given a scalar field, an isosurface is defined as the locus of points where the scalar field +has a given constant value; in other words, it is a level set. +This constant value is referred to as "isovalue", and, for well-behaved scalar fields, +the level set forms a surface. +"Isosurfacing", also known as "isosurface extraction" or "contouring", is the process of constructing +the isosurface corresponding to a given scalar field and isovalue. +This process is often needed for volume visualization and the simulation of physical phenomena. -This package provides several isosurfacing algorithms that compute a surface mesh approximating an isosurface of a 3D scalar field defined over an input 3D domain. -An isosurface is defined as the points of constant value of this scalar field, i.e., a level set. -Such a constant value, referred to as isovalue, is user-defined. For well-behaved scalar fields -(e.g., non-zero gradient), the above level set is a surface. Depending on the isosurfacing method and the input data structure, the output is either a triangle, a quadrangle or a polygon surface mesh represented as an indexed face set. Note that the output may be empty when the isosurface is absent from the sampled input scalar field. +This \cgal package provides methods to extract isosurfaces from 3D scalar fields. +These contouring techniques rely on the discretization of the 3D space to construct +an approximate representation of the isosurface. +The 3D scalar field can be described through various representations: an implicit function, +an interpolated set of discrete sampling values, etc. (see \ref SecExamples). The isovalue is user-defined. +The output is a polygon soup, made either of triangles or quads depending on the method, +and can be a single connected component, or made of multiple, disjoint components. +Note that due to the inherent approximate nature of these discrete methods, parts of the "true" +isosurface may be missing from the output, and the output may contain artifacts that are not present +in the true isosurface. -\section secmyalgorithms Algorithms +\section SecIsosurfacingMethods Isosurfacing Methods -The scientific literature abounds with algorithms for extracting isosurfaces, each coming with different properties for the output and requirements for the input. -@todo add references to a recent survey or to a series of surveys -This package offers Marching Cubes, topologically correct Marching Cubes and %Dual Contouring. +The scientific literature abounds with algorithms for extracting isosurfaces, each coming +with different properties for the output and requirements for the input \cgalCite{cgal:dljjaw-sisp-15}. +This package offers the following methods + -\subsection subsecmc Marching Cubes (MC) -MC runs over a 3D grid, i.e., a 3D domain partitioned into hexahedral cells, and processes all cells of the input 3D domain individually while sampling the input scalar field at the grid corners. -Each cell corner is assigned a sign (+/-) to indicate whether its scalar field value is above or below the user-defined isovalue. -MC creates a vertex for each grid edge with a sign change, i.e., where the edge intersects the isosurface. -More specifically, the vertex position is computed via linear interpolation of the scalar field values evaluated at the cell corners forming the edge. Depending on the configuration of signs at the cell corners, the resulting vertices are connected to form triangles within the cell. The figure below illustrates the configurations in 2D. There is no less than 33 cases in 3D (not shown). +\subsection SubSecMarchingCubes Marching Cubes (MC) +Marching Cubes (MC) uses a volumetric grid, i.e., a 3D iso-cuboid partitioned into hexahedral cells. +All cells of the grid are processed individually using values of the scalar field at the grid corners. +Each cell corner is assigned a sign (+/-) to indicate whether its scalar field value is above +or below the user-defined isovalue. +A vertex is created for each grid edge with a sign change, i.e., where the edge intersects the isosurface. +More specifically, the vertex position is computed via linear interpolation of +the scalar field values evaluated at the cell corners forming the edge. +These vertices are connected to form triangles within the cell, depending on the configuration +of signs at the cell corners. Figure \ref Fig_IsosurfacingMCCases illustrates the configurations in 2D. +In 3D, there is no less than 33 cases (not shown) \cgalCite{cgal:c-mcctci-95}. -\cgalFigureAnchor{isosurfacing_mc_cases} +\cgalFigureAnchor{Fig_IsosurfacingMCCases}
-\cgalFigureCaptionBegin{isosurfacing_mc_cases} -Different configurations of Marching Cubes in 2D. +\cgalFigureCaptionBegin{Fig_IsosurfacingMCCases} +Examples of configurations for 2D Marching Cubes [todo 3D illustrations]. \cgalFigureCaptionEnd +The implementation within \cgal is generic in the sense that it can process any grid-like data structure +that consists of hexahedral cells. +In case of a conforming [not defined] grid, the Marching Cubes algorithm generates +as output a surface triangle mesh that is 2-manifold in most scenarios. +[@todo PA: reformulate, as it is either strict or not - precise in which cases it is not, and say +whether you talk about just combinatorially 2-manifold, or truly 2-manifold with 3D embedding taken into account] +If the mesh is 2-manifold and the isosurface does not intersect the domain boundary, +then the output mesh is watertight. Conversely, the output mesh has boundaries when the isosurface +intersects the domain boundaries (see Figure \ref Fig_IsosurfacingMCOpen). -The proposed implementation is generic in that it can process any grid-based data structure that consists of hexahedral cells. -In case of a conforming grid, MC generates as output a surface triangle mesh that is 2-manifold in most scenarios. -@todo PA: reformulate, as it is either strict or not - precise in which cases it is not, and say whether you talk about just combinatorially 2-manifold, or truly 2-manifold with 3D embedding taken into account -If the mesh is 2-manifold and the isosurface does not intersect the domain boundary, then the output mesh is watertight. Conversely, the output mesh has boundaries when the isosurface intersects the domain boundaries (see Figure below). - -\cgalFigureAnchor{isosurfacing_mc_open} +\cgalFigureAnchor{Fig_IsosurfacingMCOpen}
- +
-\cgalFigureCaptionBegin{isosurfacing_mc_open} -The output MC mesh has boundaries when the isosurface intersects the domain boundary. +\cgalFigureCaptionBegin{Fig_IsosurfacingMCOpen} +The output MC mesh has boundaries when the isosurface intersects the domain boundary. [todo remake] \cgalFigureCaptionEnd - - - -As MC only proceeds by linear interpolation of the sampled scalar field along the grid edges, -it can miss details or components that are not captured by the said sampling and interpolation. +As the Marching Cubes algorithm uses linear interpolation of the sampled scalar field along the grid edges, +it can miss details or components that are not captured by the sampling of the scalar field. Compared to other approaches such as Delaunay refinement, and depending on the parameters, -the MC algorithm often generates more triangles, and more skinny triangles with small or large angles. +MC often generates more triangles, and more skinny triangles with small or large angles. [The statement is too strong - I would largely reformulate it as this depends too much on the parameters. I recommend to add instead a figure with different parameters and methods, depicting the mesh edges in black in addition to the shaded facets] MC does not preserve the sharp features present in the isovalue of the input scalar field -@todo PA: add a figure +(see Figure \ref Fig_IsosurfacingMCDC). +\subsection SubSecTMC Topologically Correct Marching Cubes (TMC) -\subsection subsectmc Topologically Correct Marching Cubes (TMC) -This algorithm is an extension to MC and provides additional guarantees for the output \cgalCite{cgal:g-ctcmi-16}. -It generates as output a mesh that is homeomorphic to the trilinear interpolant of the input scalar field inside each cube. -This means that the output mesh can accurately represent small complex features. +Topologically Correct Marching Cubes is an extension to the Marching Cubes algorithm +which provides additional guarantees for the output \cgalCite{cgal:g-ctcmi-16}. +It generates as output a mesh that is homeomorphic to the trilinear interpolant of the input scalar +field inside each cube. This means that the output mesh can accurately represent small complex features. For example, a tunnel of the isosurface within a single cell is topologically resolved. -Furthermore, the mesh is guaranteed to be 2-manifold and watertight, as long as the isosurface does not intersect the domain boundaries. -@todo PA: add a figure comparing without and with the option activated +To achieve this, the algorithm can insert additional vertices within cells. +Furthermore, the mesh is guaranteed to be 2-manifold and watertight, as long as the isosurface +does not intersect the domain boundaries. [and the input is 2-manifold?] - -\subsection subsecdc Dual Contouring (DC) -The DC algorithm generates one vertex for each cell that is intersected by the isosurface. Next, a face is created for each edge that intersects the isosurface, by connecting the vertices of the incident cells. For a uniform hexahedral grid, this results into a quadrilateral surface mesh. - -As the original DC method requires the gradient of the scalar field, the domain must implement -the concept `IsosurfacingDomainWithGradient_3` in order to provide a gradient field in addition to a scalar field. -All default domain implementations provide a gradient field, but assume the gradient -to be null everywhere when it is not provided as an additional parameter. -Alternatively, some default gradient fields are provided such as `Isosurfacing::Finite_difference_gradient_3` -and `Isosurfacing::Explicit_Cartesian_grid_gradient_3`. - -Variants of DC differ in the way they compute vertex positions. -The vertex positioning is thus configurable with an optional parameter passed to the DC algorithm. -Some variants do not require the gradient and therefore run successfully even when the default null gradient is provided. - -%Dual Contouring can deal with any domain but guarantees neither a 2-manifold nor a watertight mesh. -It generates fewer faces than Marching Cubes, in general. -Its advantage over MC is its ability to recover sharp creases and corners. -@todo PA: add a figure. - - - -\cgalFigureAnchor{isosurfacing_iwp_dc} +\cgalFigureAnchor{Fig_IsosurfacingMCTMC}
- +
-\cgalFigureCaptionBegin{isosurfacing_iwp_dc} -Isosurface of the IWP scalar field generated by %Dual Contouring. -@todo PA: do not assume that the iwp scalar field is well known to the reader - explicit first what it means. in addition, the shape is too complex, adding confusion to the reader. try to pass only one message per figure and provide a caption to not let the reader guess. show mesh edges in black +\cgalFigureCaptionBegin{Fig_IsosurfacingMCTMC} +MC vs TMC [todo] \cgalFigureCaptionEnd +\subsection SubSecDualContouring Dual Contouring (DC) + +%Dual Contouring (DC) is a method that does not generate vertices on the grid edges, but within cells. +Next, a face is created for each edge that intersects the isosurface by connecting the vertices +of the incident cells. For a uniform hexahedral grid, this results into a quadrilateral surface mesh. +%Dual Contouring can deal with any domain but guarantees neither a 2-manifold nor a watertight mesh. +On the other hand it generates fewer faces and high quality faces than Marching Cubes, in general. +Finally, its main advantage over Marching Cubes is its ability to recover sharp creases and corners. + +\cgalFigureAnchor{Fig_IsosurfacingDC} +
+ +
+\cgalFigureCaptionBegin{Fig_IsosurfacingDC} +Isosurface of the a scalar field generated by %Dual Contouring. +\cgalFigureCaptionEnd + +In addition to the scalar field, %Dual Contouring requires knowledge of the gradient of said scalar field. + +The \cgal implementation uses a point positioning strategy based on Quadric Error Metrics: for +a cell, the position of the vertex is computed by minimizing the error to the sum of the quadrics +defined at each edge-isosurface intersection. +Using this strategy, the position can in fact lie outside the cell, which is a desirable property +to improve the odds of recovering sharp features, but it might also create self-intersections. +Users can choose to constrain the placement to lie within the cell. + +By default, the Dual Contouring algorithm creates quads, but using edge-isosurface intersections, +one can "star" these quads to create four triangles. This is the default behavior in \cgal, +and it can be changed in the named parameters. + \subsection subseccomparison Comparisons -The following table compares the algorithms in terms of constraints over the input 3D domain, the facets of the output surface mesh, and the 2-manifold property of the output surface mesh. +The following table summarizes the differences between the algorithms in terms of constraints +over the input 3D domain, the facets of the output surface mesh, and the properties +of the output surface mesh. -| Algorithm | Domains | Facets | 2-Manifold | Watertight* | Topologically correct | -| ---- | ---- | ---- | ---- | ---- | ---- | - MC | Hexahedral | Triangles | no | no | no | - TMC | Hexahedral | Triangles | yes | yes | yes | - DC | All | Polygons | no | no | no | +| Algorithm | Facets | 2-Manifold | Watertight* | Topologically correct | Sharpness | +| ---- | ---- | ---- | ---- | ---- | ---- | + MC | Triangles | no | no | no | no | + TMC | Triangles | yes | yes | yes | no | + DC | Polygons | no | no | no | yes** | (* assuming the isosurface does not exit the specified bounding box of the input 3D domain) +(** not guaranteed) -\cgalFigureAnchor{isosurfacing_compare_mc_dc} +\cgalFigureAnchor{Fig_IsosurfacingMCDC}
-\cgalFigureCaptionBegin{isosurfacing_compare_mc_dc} -Comparison between a cube generated by Marching Cubes (left) and Dual Contouring (right). +\cgalFigureCaptionBegin{Fig_IsosurfacingMCDC} +Comparison between a cube generated by Marching Cubes (left) and %Dual Contouring (right). \cgalFigureCaptionEnd +\section SecInterface Interface -\section secmyinterface Interface +The following functions are the main entry points to the isosurfacing algorithms: + -Each algorithm can be called by a single templated function, and the function signature is common to all algorithms: +These free functions share the same signature: \code{.cpp} -template -void marching_cubes(const Domain& domain, const typename Domain::FT isovalue, PointRange& points, PolygonRange& polygons); +template +void ...(const Domain& domain, + const typename Domain::FT isovalue, + PointRange& points, + PolygonRange& polygons); \endcode -The input is provided in the form of a `domain` (see \ref secmydomains). +The input (space partition, scalar field, gradient field) is provided in the form of a `domain`, +see \ref SubSecDomains for a complete description. -The `isovalue` scalar parameter denotes the value used for sampling the input scalar field for generating the isosurface. +The `isovalue` scalar parameter is the value used that defines the isosurface being approximated. -The output surface mesh is provided in the form of a indexed face set, which is stored into two containers of `points` and `polygons`. -The vertex positions are stored as `Point_3` in `points`. Each face in `polygons` is a list of indices pointing into the `points` container. -Depending on the algorithm, the indexed face set may store either a polygon soup (unorganized polygons with no relationship whatsoever, i.e., no connectivity between them) or a mesh with connectivity. +The output discrete surface is provided in the form of a polygon soup, which is stored into +two containers: `points` and `polygons`. Depending on the algorithm, the polygon soup may +store either unorganized polygons with no relationship to one another (i.e., no connectivity between them) +or polygons sharing points (i.e., the same point is adjacent polygon will be the same point in the point range). -The isosurfacing algorithms can run either sequentially on one CPU core or in parallel on multicore architectures with shared memory. -The template parameter `ConcurrencyTag` is used to specify how the algorithm is executed: either `Sequential_tag` or `Parallel_tag`. -To enable parallelism, CGAL must be linked with the Intel TBB library. -When the parallel version is not available due to unsuccessful link with the TBB library, then the sequential version is utilized as a fallback. +The isosurfacing algorithms can run either sequentially in one thread or in parallel (multithread). +The template parameter `ConcurrencyTag` is used to specify how the algorithm is executed. +To enable parallelism, \cgal must be linked with the Intel TBB library (see the CMakeLists.txt files in the examples folder). -\section secmydomains Domains -A domain is an object that provides functions to access the input data, its geometry, topology, and optionally its gradient. -@todo I fail to understand how you specify the topology - for me the domain is the support of the scalar field, whose sampling/interpolation will yield the output mesh topology - not more. -For common representations, we offer a set of predefined domain classes that wrap the input data and provide a generalized interface for the algorithm. -Users can also define new domains by implementing the `IsosurfacingDomain_3` or `IsosurfacingDomainWithGradient_3` concepts. +\subsection SubSecDomains Domains -\subsection mysubsecimplicitdomain Implicit Cartesian Grid Domain -The class `CGAL::Isosurfacing::Implicit_Cartesian_grid_domain_3` represents the input scalar field in an implicit form without storing any values. -It takes a function-object (functor) or lambda function that computes the value of the scalar field from the position of a vertex query. -Additionally, the bounding box and spacing between the grid points must be provided. +A domain is an object that provides functions to access the partition of the 3D volume, +the scalar field, and - optionally - the gradient field at a given position. +These requirements are described through two concepts: `IsosurfacingDomain_3` and `IsosurfacingDomainWithGradient_3`. -\subsection mysubseccartesiandomain Explicit Cartesian Grid Domain +Two domains, `CGAL::Isosurfacing::Marching_cubes_domain_3` and `CGAL::Isosurfacing::Dual_contouring_domain_3`, +are provided as the respective default class models that fulfill the requirements of the concepts. +Both these domain models possess template parameters to allow the user to customize the domain: +- Partition: this must be a class that describes the partition of the 3D volume into cells. + The most basic example of such class is `CGAL::Isosurfacing::Cartesian_grid_3`, but users + can provide their own partition, provided it meets the requirements described + by the concept `IsosurfacingPartition_3`. +- ValueField: this must be a class that provides the scalar field at the vertices of the partition. + A few classes are provided by default, such as `CGAL::Isosurfacing::Value_function_3` and + `CGAL::Isosurfacing::Interpolated_discrete_values_3`. Users can provide their own value class, + provided it meets the requirements described by the concept `ValueField_3`. +- GradientField (`Dual_contouring_domain_3` only): this must be a class that provides the gradient + of the scalar field at the vertices of the partition. + A few classes are provided by default, such as + `CGAL::Isosurfacing::Finite_difference_gradient_3` and + `CGAL::Isosurfacing::Interpolated_discrete_gradients_3`. + Users can provide their own gradient class, + provided it meets the requirements described + by the concept `GradientField_3`. +- EdgeIntersectionOracle: this must be a class that provides a function to compute the intersection + between an edge and the isosurface. The default is linear interpolation + for `CGAL::Isosurfacing::Marching_cubes_domain_3`, and a dichotomy + for `CGAL::Isosurfacing::Dual_contouring_domain_3`. This parameter should + be adjusted depending on how your value field is defined: there is for + example no point doing a dichotomy in DC if the value field is defined + through linear interpolation. Users can provide their own edge intersection + oracle, provided it meets the requirements described by the concept + `EdgeIntersectionOracle_3`. -The class `CGAL::Isosurfacing::Explicit_Cartesian_grid_domain_3` only takes a grid as parameter, such as `CGAL::Isosurfacing::Cartesian_grid_3`. -It represents a uniform grid of scalar field values that are either computed by the user or read from an `Image_3`. -The constructor of `Cartesian_grid_3` requires the number of grid points in each dimension (x, y, z) and the bounding box. -The field values are read and written with `value(x, y, z)` where x, y, and z denote the coordinates of a grid point. -Alternatively, all required data can be copied from an `CGAL::Image_3`. - -\section secmybenchmarks Performance +\section SecPerformance Performance \cgalFigureAnchor{isosurfacing_perf_iwp_mc}
@@ -185,34 +250,56 @@ Alternatively, all required data can be copied from an `CGAL::Image_3`. Scalability of the Marching Cubes algorithm. We plot the algorithm efficiency (number of thousand-cubes per second) against the number of CPU cores. \cgalFigureCaptionEnd +\section SecExamples Examples -\section secmyexamples Examples +The first two examples are very basic examples for Marching Cubes and Dual Contouring. +Afterwards, the focus is shifted from the method to the type of input data, and examples +run both methods on different types of input data. -\subsection myExampleImplicit_domain Implicit Sphere +\subsection SubSecMCExample Marching Cubes -The following example shows the usage of the Marching Cubes algorithm to extract an isosurface. -The domain is an implicit domain that describes the unit sphere by the distance to its center (set to the origin) as an implicit field. +The following example illustrates a basic of the Marching Cubes algorithm, and in particular +the free function to create a domain from a Cartesian grid, and the named parameter +that enable the user to switch beetween Marching Cubes and Topologically Correct Marching Cubes. -\cgalExample{Isosurfacing_3/marching_cubes_implicit_sphere.cpp} +\cgalExample{Isosurfacing_3/marching_cubes.cpp} -\subsection myExampleAll_cube Cartesian_grid_3 Cube Comparison +The following example illustrates a basic of the Marching Cubes algorithm, and in particular +the free function to create a domain from a Cartesian grid, and its named parameters. -The following example runs all provided algorithms to extract an isosurface. The input 3D domain is a `Cartesian_grid_domain` that describes a cube by storing the Manhattan distance to its origin in an explicit %Cartesian grid domain. +\subsection SubSecDCExample Dual Contouring -\cgalExample{Isosurfacing_3/all_Cartesian_cube.cpp} +\cgalExample{Isosurfacing_3/dual_contouring.cpp} -\subsection myExampleImage Image_3 +\subsection SubSecImplicitDataExample Implicit Data -The following example shows how to load data from an `Image_3`. +The following example shows the usage of Marching Cubes and Dual Contouring algorithms to extract +an isosurface. The domain is an implicit domain that describes the unit sphere +by the distance to its center (set to the origin) as an implicit field. -\cgalExample{Isosurfacing_3/marching_cubes_inrimage.cpp} +\cgalExample{Isosurfacing_3/contouring_implicit_data.cpp} -\subsection myExampleMeshOffset Offset Mesh +\subsection SubSecDiscreteDataExample Discrete Data -The following example illustrates how to generates a mesh approximating a signed offset to an input closed surface mesh. -The input mesh is stored into an `AABB_tree` data structure to provide fast distance queries. Via the `Side_of_triangle_mesh` functor, the sign of the distance field is made negative inside the mesh. +In the following example, the input data is sampled at the vertices of a grid, and interpolated. -\cgalExample{Isosurfacing_3/dual_contouring_mesh_offset.cpp} +\cgalExample{Isosurfacing_3/contouring_discrete_data.cpp} + +\subsection SubSecImageDataExample 3D Image + +The following example shows how to load data from an `Image_3`, and generate an isosurface +from this voxel data. + +\cgalExample{Isosurfacing_3/contouring_image.cpp} + +\subsection SubSecOffsetDataExample Offset Mesh + +The following example illustrates how to generates a mesh approximating a signed offset to an input +closed surface mesh. The input mesh is stored into an `AABB_tree` data structure to provide fast +distance queries. Via the `Side_of_triangle_mesh` functor, the sign of the distance field is made +negative inside the mesh. + +\cgalExample{Isosurfacing_3/contouring_mesh_offset.cpp} */ } /* namespace CGAL */