Add Subdivision_method_3 doc
|
|
@ -5577,6 +5577,31 @@ Stream_support/doc/IOstream/PackageDescription.txt -text
|
||||||
Stream_support/doc/IOstream/fig/io.png -text svneol=unset#image/png
|
Stream_support/doc/IOstream/fig/io.png -text svneol=unset#image/png
|
||||||
Stream_support/doc_tex/IOstream/io.png -text
|
Stream_support/doc_tex/IOstream/io.png -text
|
||||||
Stream_support/test/Stream_support/data/io.cin -text
|
Stream_support/test/Stream_support/data/io.cin -text
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/CGAL/Subdivision_mask_3.h -text
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/CGAL/Subdivision_method_3.h -text
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/Concepts/DQQMask_3.h -text
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/Concepts/PQQMask_3.h -text
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/Concepts/PTQMask_3.h -text
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/Concepts/Sqrt3Mask_3.h -text
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/PackageDescription.txt -text
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/Subdivision_method_3.txt -text
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/CCBorderMask.pdf -text svneol=unset#application/pdf
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/CCBorderMask.png -text svneol=unset#image/png
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/CCSubdivision.png -text svneol=unset#image/png
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/DSCornerMask.pdf -text svneol=unset#application/pdf
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/DSCornerMask.png -text svneol=unset#image/png
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/LoopBorderMask.pdf -text svneol=unset#application/pdf
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/LoopBorderMask.png -text svneol=unset#image/png
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/PQQStencil.gif -text svneol=unset#image/gif
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/PQQStencil.pdf -text svneol=unset#application/pdf
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/RefSchemes.gif -text svneol=unset#image/gif
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/RefSchemes.pdf -text svneol=unset#application/pdf
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/cc_mask.gif -text svneol=unset#image/gif
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/cc_mask.pdf -text svneol=unset#application/pdf
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/teaser.jpg -text svneol=unset#image/jpeg
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/teaser.pdf -text svneol=unset#application/pdf
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/twoheads-detail.png -text svneol=unset#image/png
|
||||||
|
Subdivision_method_3/doc/Subdivision_method_3/fig/twoheads.png -text svneol=unset#image/png
|
||||||
Subdivision_method_3/doc_tex/Subdivision_method_3/FIG/CCSubdivision.png -text svneol=unset#image/png
|
Subdivision_method_3/doc_tex/Subdivision_method_3/FIG/CCSubdivision.png -text svneol=unset#image/png
|
||||||
Subdivision_method_3/doc_tex/Subdivision_method_3/FIG/PQQStencil.fig -text svneol=unset#application/octet-stream
|
Subdivision_method_3/doc_tex/Subdivision_method_3/FIG/PQQStencil.fig -text svneol=unset#application/octet-stream
|
||||||
Subdivision_method_3/doc_tex/Subdivision_method_3/FIG/PQQStencil.gif -text svneol=unset#image/gif
|
Subdivision_method_3/doc_tex/Subdivision_method_3/FIG/PQQStencil.gif -text svneol=unset#image/gif
|
||||||
|
|
|
||||||
|
|
@ -298,6 +298,20 @@ namespace for the XML file to be processed properly. -->
|
||||||
</doxygen>
|
</doxygen>
|
||||||
</project>
|
</project>
|
||||||
|
|
||||||
|
<project>
|
||||||
|
<name>3D Surface Subdivision Methods</name>
|
||||||
|
<input>../Subdivision_method_3/doc</input>
|
||||||
|
<doxygen>
|
||||||
|
<string name="STRIP_FROM_PATH">../Subdivision_method_3/doc/Subdivision_method_3/</string>
|
||||||
|
<string name="STRIP_FROM_INC_PATH">../Subdivision_method_3/doc/Subdivision_method_3/</string>
|
||||||
|
<string name="GENERATE_TAGFILE">./tags/Subdivision_method_3.tag</string>
|
||||||
|
<string name="EXAMPLE_PATH">../Subdivision_method_3/examples</string>
|
||||||
|
<string name="IMAGE_PATH">../Subdivision_method_3/doc/Subdivision_method_3/fig</string>
|
||||||
|
</doxygen>
|
||||||
|
</project>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<project>
|
<project>
|
||||||
<name>2D Placement of Streamlines</name>
|
<name>2D Placement of Streamlines</name>
|
||||||
<input>../Stream_lines_2/doc</input>
|
<input>../Stream_lines_2/doc</input>
|
||||||
|
|
@ -1052,6 +1066,7 @@ namespace for the XML file to be processed properly. -->
|
||||||
<item>../Straight_skeleton_2/doc/Straight_skeleton_2/fig</item>
|
<item>../Straight_skeleton_2/doc/Straight_skeleton_2/fig</item>
|
||||||
<item>../Voronoi_diagram_2/doc/Voronoi_diagram_2/fig</item>
|
<item>../Voronoi_diagram_2/doc/Voronoi_diagram_2/fig</item>
|
||||||
<item>../Surface_mesh_simplification/doc/Surface_mesh_simplification/fig</item>
|
<item>../Surface_mesh_simplification/doc/Surface_mesh_simplification/fig</item>
|
||||||
|
<item>../Subdivision_method_3/doc/Subdivision_method_3/fig</item>
|
||||||
<item>../Surface_mesh_parameterization/doc/Surface_mesh_parameterization/fig</item>
|
<item>../Surface_mesh_parameterization/doc/Surface_mesh_parameterization/fig</item>
|
||||||
<item>../Stream_lines_2/doc/Stream_lines_2/fig</item>
|
<item>../Stream_lines_2/doc/Stream_lines_2/fig</item>
|
||||||
<item>../Stream_support/doc/IOstream/fig</item>
|
<item>../Stream_support/doc/IOstream/fig</item>
|
||||||
|
|
@ -1115,6 +1130,7 @@ namespace for the XML file to be processed properly. -->
|
||||||
<item>./tags/Straight_skeleton_2.tag=../../CGAL.CGAL.2D-Straight-Skeleton-and-Polygon-Offsetting/html</item>
|
<item>./tags/Straight_skeleton_2.tag=../../CGAL.CGAL.2D-Straight-Skeleton-and-Polygon-Offsetting/html</item>
|
||||||
<item>./tags/Voronoi_diagram_2.tag=../../CGAL.CGAL.2D-Voronoi-Diagram-Adaptor/html</item>
|
<item>./tags/Voronoi_diagram_2.tag=../../CGAL.CGAL.2D-Voronoi-Diagram-Adaptor/html</item>
|
||||||
<item>./tags/Surface_mesh_simplification.tag=../../CGAL.CGAL.Triangulated-Surface-Mesh-Simplification/html</item>
|
<item>./tags/Surface_mesh_simplification.tag=../../CGAL.CGAL.Triangulated-Surface-Mesh-Simplification/html</item>
|
||||||
|
<item>./tags/Subdivision_method_3.tag=../../CGAL.CGAL.3D-Surface-Subdivion-Methods/html</item>
|
||||||
<item>./tags/Stream_lines_2.tag=../../CGAL.CGAL.2D Placement-of-Streamlines/html</item>
|
<item>./tags/Stream_lines_2.tag=../../CGAL.CGAL.2D Placement-of-Streamlines/html</item>
|
||||||
<item>./tags/Stream_support.tag=../../CGAL.CGAL.IO-Streams/html</item>
|
<item>./tags/Stream_support.tag=../../CGAL.CGAL.IO-Streams/html</item>
|
||||||
<item>./tags/Surface_mesh_parameterization.tag=../../CGAL.CGAL.Planar-Parameterization-of-Triangulated-Surface-Meshes</item>
|
<item>./tags/Surface_mesh_parameterization.tag=../../CGAL.CGAL.Planar-Parameterization-of-Triangulated-Surface-Meshes</item>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,256 @@
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\ingroup PkgSurfaceSubdivisionMethods3
|
||||||
|
|
||||||
|
A stencil determines a source neighborhood
|
||||||
|
whose points contribute to the position of a refined point.
|
||||||
|
The geometry mask of a stencil specifies
|
||||||
|
the computation on the nodes of the stencil.
|
||||||
|
`CatmullClark_mask_3` implements the geometry masks of
|
||||||
|
Catmull-Clark subdivision on a `Polyhedron_3<Cartesian>`.
|
||||||
|
|
||||||
|
\image html CCBorderMask.png
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The only parameter requires a `Polyhedron_3` as the argument. The
|
||||||
|
`Polyhedron_3` should be specialized with the `Cartesian`
|
||||||
|
kernel, which defines the `Point_3` for the vertices.
|
||||||
|
|
||||||
|
\sa `CGAL::Subdivision_method_3`
|
||||||
|
|
||||||
|
*/
|
||||||
|
template< typename Polyhedron_3 >
|
||||||
|
class CatmullClark_mask_3 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Creation
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
default constructor.
|
||||||
|
*/
|
||||||
|
CatmullClark_mask_3<Polyhedron_3>();
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// \name Stencil functions
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the Catmull-Clark facet-point `pt` of the facet `f`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void facet_node(Facet_handle f, Point_3& pt);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the Catmull-Clark edge-point `pt` of the edge `e`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void edge_node(Edge_handle e, Point_3& pt);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the Catmull-Clark vertex-point `pt` of the vertex `v`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void vertex_node(Vertex_handle v, Point_3& pt);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the Catmull-Clark edge-point `ept` and the
|
||||||
|
Catmull-Clark vertex-point `vpt` of the border edge `e`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void border_node(Halfedge_handle e, Point_3& ept, Point_3& vpt);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}; /* end CatmullClark_mask_3 */
|
||||||
|
} /* end namespace CGAL */
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\ingroup PkgSurfaceSubdivisionMethods3
|
||||||
|
|
||||||
|
A stencil determines a source neighborhood
|
||||||
|
whose points contribute to the position of a refined point.
|
||||||
|
The geometry mask of a stencil specifies
|
||||||
|
the computation on the nodes of the stencil.
|
||||||
|
`DooSabin_mask_3` implements the geometry masks of
|
||||||
|
Doo-Sabin subdivision on a `Polyhedron_3<Cartesian>`.
|
||||||
|
|
||||||
|
\image html DSCornerMask.png
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The only parameter requires a `Polyhedron_3` as the argument. The
|
||||||
|
`Polyhedron_3` should be specialized with the `Cartesian`
|
||||||
|
kernel, which defines the `Point_3` for the vertices.
|
||||||
|
|
||||||
|
\sa `CGAL::Subdivision_method_3`
|
||||||
|
|
||||||
|
*/
|
||||||
|
template< typename Polyhedron_3 >
|
||||||
|
class DooSabin_mask_3 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Creation
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
default constructor.
|
||||||
|
*/
|
||||||
|
DooSabin_mask_3<Polyhedron_3>();
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// \name Stencil functions
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the Doo-Sabin point `pt` of the vertex pointed
|
||||||
|
by the halfedge `he`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void corner_node(Halfedge_handle he, Point_3& pt);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}; /* end DooSabin_mask_3 */
|
||||||
|
} /* end namespace CGAL */
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\ingroup PkgSurfaceSubdivisionMethods3
|
||||||
|
|
||||||
|
A stencil determines a source neighborhood
|
||||||
|
whose points contribute to the position of a refined point.
|
||||||
|
The geometry mask of a stencil specifies
|
||||||
|
the computation on the nodes of the stencil.
|
||||||
|
`Loop_mask_3` implements the geometry masks of
|
||||||
|
Loop subdivision on a triangulated `Polyhedron_3<Cartesian>`.
|
||||||
|
|
||||||
|
\image html LoopBorderMask.png
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The only parameter requires a `Polyhedron_3` as the argument. The
|
||||||
|
`Polyhedron_3` should be specialized with the `Cartesian`
|
||||||
|
kernel, which defines the `Point_3` for the vertices.
|
||||||
|
|
||||||
|
\sa `CGAL::Subdivision_method_3`
|
||||||
|
|
||||||
|
*/
|
||||||
|
template< typename Polyhedron_3 >
|
||||||
|
class Loop_mask_3 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Creation
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
default constructor.
|
||||||
|
*/
|
||||||
|
Loop_mask_3<Polyhedron_3>();
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// \name Stencil functions
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the Loop edge-point `pt` of the edge `e`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void edge_node(Edge_handle e, Point_3& pt);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the Loop vertex-point `pt` of the vertex `v`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void vertex_node(Vertex_handle v, Point_3& pt);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the Loop edge-point `ept` and the
|
||||||
|
Loop vertex-point `vpt` of the border edge `e`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void border_node(Halfedge_handle e, Point_3& ept, Point_3& vpt);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}; /* end Loop_mask_3 */
|
||||||
|
} /* end namespace CGAL */
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\ingroup PkgSurfaceSubdivisionMethods3
|
||||||
|
|
||||||
|
A stencil determines a source neighborhood
|
||||||
|
whose points contribute to the position of a refined point.
|
||||||
|
The geometry mask of a stencil specifies
|
||||||
|
the computation on the nodes of the stencil.
|
||||||
|
`Sqrt3_mask_3` implements the geometry masks of
|
||||||
|
\f$ \sqrt{3}\f$ subdivision on a triangulated
|
||||||
|
`Polyhedron_3<Cartesian>`.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The only parameter requires a `Polyhedron_3` as the argument. The
|
||||||
|
`Polyhedron_3` should be specialized with the `Cartesian`
|
||||||
|
kernel, which defines the `Point_3` for the vertices.
|
||||||
|
|
||||||
|
\sa `CGAL::Subdivision_method_3`
|
||||||
|
|
||||||
|
*/
|
||||||
|
template< typename Polyhedron_3 >
|
||||||
|
class Sqrt3_mask_3 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Creation
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
default constructor.
|
||||||
|
*/
|
||||||
|
Sqrt3_mask_3<Polyhedron_3>();
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// \name Stencil functions
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the \f$ \sqrt{3}\f$ facet-point `pt` of the facet `f`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void facet_node(Facet_handle f, Point_3& pt);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the \f$ \sqrt{3}\f$ vertex-point `pt` of the vertex `v`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void vertex_node(Vertex_handle v, Point& pt);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}; /* end Sqrt3_mask_3 */
|
||||||
|
} /* end namespace CGAL */
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
/// The namespace containing the subdivision methods.
|
||||||
|
namespace Subdivision_method_3 {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\addtogroup PkgSurfaceSubdivisionMethods3Functions
|
||||||
|
|
||||||
|
A subdivision method recursively refines a coarse mesh and
|
||||||
|
generates an ever closer approximation to a smooth surface.
|
||||||
|
`Subdivision_method_3` consists of four subdivision methods
|
||||||
|
and their refinement hosts. Each refinement host is a template
|
||||||
|
function of a polyhedron class and a
|
||||||
|
geometry policy class. It refines the connectivity of the
|
||||||
|
control mesh and computes the geometry of the refined mesh.
|
||||||
|
The geometry computation is dedicated to the custom
|
||||||
|
geometry policy. A geometry policy consists of functions
|
||||||
|
that compute the new point based on the subdivision stencil.
|
||||||
|
A stencil defines the footprint (a submesh of the control mesh)
|
||||||
|
of a new point.
|
||||||
|
|
||||||
|
The four supported refinement hosts are the
|
||||||
|
primal quadrilateral quadrisection (PQQ),
|
||||||
|
the primal triangle quadrisection (PTQ),
|
||||||
|
the dual quadrilateral quadrisection (DQQ),
|
||||||
|
and the \f$ \sqrt{3}\f$ triangulation.
|
||||||
|
These refinements are respectively used in
|
||||||
|
Catmull-Clark, Loop, Doo-Sabin and \f$ \sqrt{3}\f$ subdivision.
|
||||||
|
|
||||||
|
Refinement Host
|
||||||
|
--------------
|
||||||
|
|
||||||
|
A refinement host is a template function of
|
||||||
|
a polyhedron class and a geometry mask class. It refines
|
||||||
|
the input polyhedron, and computes new points through
|
||||||
|
the geometry masks.
|
||||||
|
`Subdivision_method_3` supports four refinement hosts:
|
||||||
|
`PQQ`, `PTQ`, `DQQ` and `Sqrt3`.
|
||||||
|
|
||||||
|
\image html RefSchemes.gif
|
||||||
|
Example
|
||||||
|
--------------
|
||||||
|
|
||||||
|
This example program subdivides a polyhedral mesh with
|
||||||
|
Catmull-Clark subdivision.
|
||||||
|
|
||||||
|
\cgalexample{CatmullClark_subdivision.cpp}
|
||||||
|
|
||||||
|
|
||||||
|
\sa `CGAL::CatmullClark_mask_3<Polyhedron_3>`
|
||||||
|
\sa `CGAL::Loop_mask_3<Polyhedron_3>`
|
||||||
|
\sa `CGAL::Sqrt3_mask_3<Polyhedron_3>`
|
||||||
|
*/
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
applies the PQQ refinement on the control mesh `p` `step` times.
|
||||||
|
The geometry of the refined mesh is computed by the geometry policy `mask`.
|
||||||
|
This function overwrites the control mesh `p` with the refined mesh.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Polyhedron_3, template <typename> class Mask>
|
||||||
|
void PQQ(Polyhedron_3& p, Mask<Polyhedron_3> mask, int step = 1);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
applies the PTQ refinement on the control mesh `p` `step` times,
|
||||||
|
where `p` contains only triangle facets.
|
||||||
|
The geometry of the refined mesh is computed by the geometry policy `mask`.
|
||||||
|
This function overwrites the control mesh `p` with the refined mesh.
|
||||||
|
The result of a non-triangle mesh `p` is undefined.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Polyhedron_3, template <typename> class Mask>
|
||||||
|
void PTQ(Polyhedron_3& p, Mask<Polyhedron_3> mask, int step = 1);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
applies the DQQ refinement on the control mesh `p` `step` times.
|
||||||
|
The geometry of the refined mesh is computed by the geometry policy `mask`.
|
||||||
|
This function overwrites the control mesh `p` with the refined mesh.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Polyhedron_3, template <typename> class Mask>
|
||||||
|
void DQQ(Polyhedron_3& p, Mask<Polyhedron_3> mask, int step = 1);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
applies the \f$ \sqrt{3}\f$ triangulation on the control mesh `p`
|
||||||
|
`step` times, where `p` contains only triangle facets.
|
||||||
|
The geometry of the refined mesh is computed by the geometry policy `mask`.
|
||||||
|
This function overwrites the control mesh `p` with the refined mesh.
|
||||||
|
The result of a non-triangle mesh `p` is undefined.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Polyhedron_3, template <typename> class Mask>
|
||||||
|
void Sqrt3(Polyhedron_3& p, Mask<Polyhedron_3> mask, int step = 1);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
applies Catmull-Clark subdivision `step` times on the control mesh `p`.
|
||||||
|
This function overwrites the control mesh `p` with the subdivided mesh.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
void CatmullClark_subdivision(Polyhedron_3& p, int step = 1);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
applies Loop subdivision `step` times on the control mesh `p`.
|
||||||
|
This function overwrites the control mesh `p` with the subdivided mesh.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
void Loop_subdivision(Polyhedron_3& p, int step = 1);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
applies Doo-Sabin subdivision `step` times on the control mesh `p`.
|
||||||
|
This function overwrites the control mesh `p` with the subdivided mesh.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
void DooSabin_subdivision(Polyhedron_3& p, int step = 1);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
applies \f$ \sqrt{3}\f$ subdivision `step` times on the control mesh `p`.
|
||||||
|
This function overwrites the control mesh `p` with the subdivided mesh.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
void Sqrt3_subdivision(Polyhedron_3& p, int step = 1);
|
||||||
|
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
} /* end namespace Subdivision_method_3 */
|
||||||
|
} /* end namespace CGAL */
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\ingroup PkgSurfaceSubdivisionMethods3Concepts
|
||||||
|
\cgalconcept
|
||||||
|
|
||||||
|
Required member functions for the `DQQMask_3` concept. This
|
||||||
|
policy concept of geometric computations is used in
|
||||||
|
`CGAL::Subdivision_method_3::DQQ<Polyhedron_3, Mask>`.
|
||||||
|
|
||||||
|
\image html DSCornerMask.png
|
||||||
|
|
||||||
|
\hasModel `CGAL::DooSabin_mask_3<Polyhedron_3>`
|
||||||
|
|
||||||
|
\sa `CGAL::Subdivision_method_3`
|
||||||
|
|
||||||
|
*/
|
||||||
|
class DQQMask_3 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Operations
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the subdivided point `pt` based on the neighborhood
|
||||||
|
of the vertex pointed by the halfedge `he`.
|
||||||
|
*/
|
||||||
|
void corner_node(Halfedge_handle he, Point_3& pt);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}; /* end DQQMask_3 */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\ingroup PkgSurfaceSubdivisionMethods3Concepts
|
||||||
|
\cgalconcept
|
||||||
|
|
||||||
|
Required member functions for the `PQQMask_3` concept. This
|
||||||
|
policy concept of geometric computations is used in
|
||||||
|
`CGAL::Subdivision_method_3::PQQ<Polyhedron_3, Mask>`.
|
||||||
|
|
||||||
|
\image html CCBorderMask.png
|
||||||
|
|
||||||
|
\hasModel `CGAL::CatmullClark_mask_3<Polyhedron_3>`
|
||||||
|
|
||||||
|
\sa CGAL::Subdivision_method_3`
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PQQMask_3 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Operations
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the facet-point `pt` based on the neighborhood
|
||||||
|
of the facet `f`.
|
||||||
|
*/
|
||||||
|
void facet_node(Facet_handle facet, Point_3& pt);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the edge-point `pt` based on the neighborhood
|
||||||
|
of the edge `e`.
|
||||||
|
*/
|
||||||
|
void edge_node(Edge_handle e, Point_3& pt);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the vertex-point `pt` based on the neighborhood
|
||||||
|
of the vertex `v`.
|
||||||
|
*/
|
||||||
|
void vertex_node(Vertex_handle v, Point_3& pt);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the edge-point `ept` and the vertex-point `vpt`
|
||||||
|
based on the neighborhood of the border edge `e`.
|
||||||
|
*/
|
||||||
|
void border_node(Halfedge_handle e, Point_3& ept, Point_3& vpt);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}; /* end PQQMask_3 */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*!
|
||||||
|
\ingroup PkgSurfaceSubdivisionMethods3Concepts
|
||||||
|
\cgalconcept
|
||||||
|
|
||||||
|
Required member functions for the `PTQMask_3` concept. This
|
||||||
|
policy concept of geometric computations is used in
|
||||||
|
`CGAL::Subdivision_method_3::PTQ<Polyhedron_3, Mask>`.
|
||||||
|
|
||||||
|
\image html LoopBorderMask.png
|
||||||
|
|
||||||
|
\hasModel `CGAL::Loop_mask_3<Polyhedron_3>`
|
||||||
|
|
||||||
|
\sa `CGAL::Subdivision_method_3`
|
||||||
|
*/
|
||||||
|
class PTQMask_3 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Operations
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
computes the edge-point `pt` based on the neighborhood
|
||||||
|
of the edge `e`.
|
||||||
|
*/
|
||||||
|
void edge_node(Edge_handle e, Point_3& pt);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the vertex-point `pt` based on the neighborhood
|
||||||
|
of the vertex `v`.
|
||||||
|
*/
|
||||||
|
void vertex_node(Vertex_handle v, Point_3& pt);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the edge-point `ept` and the vertex-point `vpt`
|
||||||
|
based on the neighborhood of the border edge `e`.
|
||||||
|
*/
|
||||||
|
void border_node(Halfedge_handle e, Point_3& ept, Point_3& vpt);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}; /* end PTQMask_3 */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\ingroup PkgSurfaceSubdivisionMethods3Concepts
|
||||||
|
\cgalconcept
|
||||||
|
|
||||||
|
Required member functions for the `Sqrt3Mask_3` concept. This
|
||||||
|
policy concept of geometric computations is used in
|
||||||
|
`CGAL::Subdivision_method_3::Sqrt3<Polyhedron_3, Mask>`.
|
||||||
|
|
||||||
|
\hasModel `CGAL::Sqrt3_mask_3<Polyhedron_3>`
|
||||||
|
|
||||||
|
\sa `CGAL::Subdivision_method_3`
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Sqrt3Mask_3 {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// \name Operations
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the subdivided point `pt` based on the neighborhood
|
||||||
|
of the facet `f`.
|
||||||
|
*/
|
||||||
|
void facet_node(Facet_handle f, Point_3& pt);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
|
||||||
|
computes the subdivided point `pt` based on the neighborhood
|
||||||
|
of the vertex `v`.
|
||||||
|
*/
|
||||||
|
void vertex_node(Vertex_handle v, Point& pt);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}; /* end Sqrt3Mask_3 */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
/// \defgroup PkgSurfaceSubdivisionMethods3 3D Surface Subdivision Methods
|
||||||
|
|
||||||
|
/// \defgroup PkgSurfaceSubdivisionMethods3Concepts Concepts
|
||||||
|
/// \ingroup PkgSurfaceSubdivisionMethods3
|
||||||
|
|
||||||
|
/// \defgroup PkgSurfaceSubdivisionMethods3Functions Subdivision Methods
|
||||||
|
/// \ingroup PkgSurfaceSubdivisionMethods3
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\addtogroup PkgSurfaceSubdivisionMethods3
|
||||||
|
\todo check generated documentation
|
||||||
|
\PkgDescriptionBegin{3D Surface Subdivision Methods}
|
||||||
|
\PkgPicture{twoheads-detail.png}
|
||||||
|
\PkgAuthor{Le-Jeng Andy Shiue}
|
||||||
|
\PkgDesc{Subdivision methods recursively refine a control mesh and generate points approximating the limit surface. This package consists of four popular subdivision methods and their refinement hosts. Supported subdivision methods include Catmull-Clark, Loop, Doo-Sabin and sqrt(3) subdivisions. Their respective refinement hosts are <span class="textsc">Pqq</span>, <span class="textsc">Ptq</span>, <span class="textsc">Dqq</span> and sqrt(3) refinements. Variations of those methods can be easily extended by substituting the geometry computation of the refinement host.}
|
||||||
|
\PkgSince{3.2}
|
||||||
|
\cgalbib{cgal:s-ssm2}
|
||||||
|
\license{\ref licensesLGPL "LGPL"}
|
||||||
|
\PkgDescriptionEnd
|
||||||
|
|
||||||
|
Subdivision methods recursively refine the control mesh
|
||||||
|
(i.e. the input mesh) and generate points approximating
|
||||||
|
the limit surface.
|
||||||
|
Designed to work on the class `Polyhedron_3`,
|
||||||
|
`Subdivision_method_3` aims to be easy to use and to extend.
|
||||||
|
`Subdivision_method_3` is not a class, but a namespace
|
||||||
|
which consists of four popular subdivision methods and their refinement
|
||||||
|
hosts. Supported subdivision methods include Catmull-Clark, Loop,
|
||||||
|
Doo-Sabin and \f$ \sqrt{3}\f$ subdivisions. Their respective refinement
|
||||||
|
hosts are PQQ, PTQ, DQQ and \f$ \sqrt{3}\f$ refinements.
|
||||||
|
Variations of those methods can be easily
|
||||||
|
extended by substituting the geometry computation of the refinement
|
||||||
|
host.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
@ -0,0 +1,569 @@
|
||||||
|
|
||||||
|
\page chapterSubdivision 3D Surface Subdivision Methods
|
||||||
|
|
||||||
|
namespace CGAL {
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\mainpage 3D Surface Subdivision Methods
|
||||||
|
\anchor chapterSubdivision
|
||||||
|
|
||||||
|
\authors Le-Jeng Andy Shiue
|
||||||
|
|
||||||
|
\image html teaser.jpg
|
||||||
|
|
||||||
|
\section sectionSubIntro Introduction
|
||||||
|
|
||||||
|
Subdivision methods are simple yet powerful ways to
|
||||||
|
generate smooth surfaces from arbitrary polyhedral meshes.
|
||||||
|
Unlike spline-based surfaces (e.g NURBS) or other numeric-based
|
||||||
|
modeling techniques, users of subdivision
|
||||||
|
methods do not need the mathematical knowledge of
|
||||||
|
the subdivision methods.
|
||||||
|
The natural intuition of the geometry suffices to control the
|
||||||
|
subdivision methods.
|
||||||
|
|
||||||
|
`Subdivision_method_3`, designed to work on the class
|
||||||
|
`Polyhedron_3`, aims to be easy to use and to extend.
|
||||||
|
`Subdivision_method_3` is not a class, but a namespace
|
||||||
|
which contains four popular subdivision methods and their refinement
|
||||||
|
functions. These include Catmull-Clark, Loop, Doo-Sabin and
|
||||||
|
\f$ \sqrt{3}\f$ subdivisions. Variations of these methods can be easily
|
||||||
|
extended by substituting the geometry computation of the refinement
|
||||||
|
host.
|
||||||
|
|
||||||
|
\section secSubAlgo Subdivision Method
|
||||||
|
|
||||||
|
In this chapter, we explain some fundamentals of
|
||||||
|
subdivision methods. We focus only on the topics that help you
|
||||||
|
to understand the design of the package. \cite cgal:ww-smgd-02
|
||||||
|
has details on subdivision methods.
|
||||||
|
Some terminology introduced in this section will be used again
|
||||||
|
in later sections. If you are only interested in using a
|
||||||
|
specific subdivision method, Section \ref secFirstSub
|
||||||
|
gives a quick tutorial on Catmull-Clark subdivision.
|
||||||
|
|
||||||
|
A subdivision method recursively refines a coarse mesh and
|
||||||
|
generates an ever closer approximation to a smooth surface.
|
||||||
|
The coarse mesh can have arbitrary shape, but it has to
|
||||||
|
be a 2-manifold. In a 2-manifold, every interior point has
|
||||||
|
a neighborhood homeomorphic to a 2D disk. Subdivision methods
|
||||||
|
on non-manifolds have been developed, but are not considered
|
||||||
|
in `Subdivision_method_3`.
|
||||||
|
The chapter teaser shows the steps of Catmull-Clark
|
||||||
|
subdivision on a CAD model. The coarse mesh is repeatedly refined
|
||||||
|
by a quadrisection pattern, and new points are generated
|
||||||
|
to approximate a smooth surface.
|
||||||
|
|
||||||
|
Many refinement patterns are used in practice.
|
||||||
|
`Subdivision_method_3` supports the four most popular
|
||||||
|
patterns, and each of them is used by
|
||||||
|
Catmull-Clark\cite cgal:cc-rgbss-78, Loop, Doo-Sabin
|
||||||
|
and \f$ \sqrt{3}\f$ subdivision (left to right in the
|
||||||
|
figure). We name these patterns by their topological
|
||||||
|
characteristics instead of the associated subdivision methods.
|
||||||
|
PQQ indicates the <I>P</I>rimal <I>Q</I>uadtrateral <I>Q</I>uadrisection.
|
||||||
|
PTQ indicates the <I>P</I>rimal <I>T</I>riangle <I>Q</I>uadrisection.
|
||||||
|
DQQ indicates the <I>D</I>ual <I>Q</I>uadtrateral <I>Q</I>uadrisection.
|
||||||
|
\f$ \sqrt{3}\f$ indicates the converging speed of the triangulation toward
|
||||||
|
the subdivision surface.
|
||||||
|
|
||||||
|
\image html RefSchemes.gif
|
||||||
|
|
||||||
|
The figure demonstrates these four refinement patterns on
|
||||||
|
the 1-disk of a valence-5 vertex/facet.
|
||||||
|
Refined meshes are shown below the source meshes.
|
||||||
|
Points on the refined mesh are generated by averaging
|
||||||
|
neighbor points on the source mesh. A graph, called <I>stencil</I>,
|
||||||
|
determines the source neighborhood whose points contribute to the
|
||||||
|
position of a refined point. A refinement pattern usually defines
|
||||||
|
more than one stencil.
|
||||||
|
For example, the PQQ
|
||||||
|
refinement has a vertex-node stencil,
|
||||||
|
which defines the 1-ring of an input vertex; an edge-node stencil,
|
||||||
|
which defines the 1-ring of an input edge; and a facet-node stencil,
|
||||||
|
which defines an input facet. The stencils of the PQQ refinement are
|
||||||
|
shown in the following figure. The blue neighborhoods in the
|
||||||
|
top row indicate the corresponding stencils of the refined nodes
|
||||||
|
in red.
|
||||||
|
|
||||||
|
\image html PQQStencil.gif
|
||||||
|
|
||||||
|
Stencils with weights are called <I>geometry masks</I>.
|
||||||
|
A subdivision method defines a geometry mask for each stencil, and
|
||||||
|
generates new points by averaging source points weighted by the mask.
|
||||||
|
Geometry masks are carefully chosen to meet requirements of
|
||||||
|
certain surface smoothness and shape quality.
|
||||||
|
The geometry masks of Catmull-Clark subdivision are shown
|
||||||
|
below.
|
||||||
|
|
||||||
|
\image html cc_mask.gif
|
||||||
|
|
||||||
|
The weights shown here are unnormalized, and \f$ n\f$ is the valence
|
||||||
|
of the vertex. The generated point, in red, is computed by a summation
|
||||||
|
of the weighted points. For example, a Catmull-Clark facet-node is
|
||||||
|
computed by the summation of \f$ 1/4\f$ of each point on its stencil.
|
||||||
|
|
||||||
|
A stencil can have an unlimited number of geometry masks. For example,
|
||||||
|
a facet-node of PQQ refinement may be computed by
|
||||||
|
the summation of \f$ 1/5\f$ of each stencil node instead of \f$ 1/4\f$.
|
||||||
|
Although it is legal in `Subdivision_method_3` to have
|
||||||
|
any kind of geometry mask, the result surfaces may be odd,
|
||||||
|
not smooth, or not even exist. \cite cgal:ww-smgd-02 explains the
|
||||||
|
details on designing masks for a quality subdivision surface.
|
||||||
|
|
||||||
|
\section secFirstSub A Quick Example: Catmull-Clark Subdivision
|
||||||
|
|
||||||
|
Assuming you are familiar with `Polyhedron_3`,
|
||||||
|
you can integrate `Subdivision_method_3` into your program
|
||||||
|
without much effort.
|
||||||
|
|
||||||
|
\cgalexample{CatmullClark_subdivision.cpp}
|
||||||
|
|
||||||
|
This example demonstrates the use of the Catmull-Clark subdivision method
|
||||||
|
on a `Polyhedron_3`. The polyhedron is restricted in the Cartesian
|
||||||
|
space, where most subdivision applications are designed to work.
|
||||||
|
There is only one line deserving a detailed explanation:
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
|
||||||
|
Subdivision_method_3::CatmullClark_subdivision(P,d);
|
||||||
|
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
`Subdivision_method_3` specifies the namespace of our
|
||||||
|
subdivision functions. `CatmullClark_subdivision(P,d)` computes the
|
||||||
|
Catmull-Clark subdivision surface of the polyhedron `P` after
|
||||||
|
`d` iterations of the refinements. The polyhedron `P` is
|
||||||
|
passed by reference, and is modified (i.e. subdivided) by the
|
||||||
|
subdivision function.
|
||||||
|
|
||||||
|
This example shows how to subdivide a simple `Polyhedron_3`
|
||||||
|
with `Subdivision_method_3`.
|
||||||
|
An application-defined polyhedron might use a specialized kernel and/or
|
||||||
|
a specialized internal container. There are two major restrictions on the
|
||||||
|
application-defined polyhedron to work with
|
||||||
|
`Subdivision_method_3`.
|
||||||
|
<UL>
|
||||||
|
<LI>`Point_3` is type-defined by the kernel. Without `Point_3`
|
||||||
|
and the associated operations being defined, `Subdivision_method_3`
|
||||||
|
can not know how to compute and store the new vertex points.
|
||||||
|
<LI>The primitives (such as vertices, halfedges and facets)
|
||||||
|
in the internal container are sequentially ordered (e.g.
|
||||||
|
`std::vector` and `std::list`).
|
||||||
|
This implies that the iterators traverse the primitives in
|
||||||
|
the order of their creations/insertions.
|
||||||
|
</UL>
|
||||||
|
|
||||||
|
Section \ref secRefHost gives detailed explanations on those
|
||||||
|
two restrictions.
|
||||||
|
|
||||||
|
\section secCC Catmull-Clark Subdivision
|
||||||
|
|
||||||
|
`Subdivision_method_3` is designed to allow customization of
|
||||||
|
the subdivision methods. This section explains the implementation
|
||||||
|
of the Catmull-Clark subdivision function in `Subdivision_method_3`.
|
||||||
|
The implementation demonstrates the customization of the PQQ refinement
|
||||||
|
to Catmull-Clark subdivision.
|
||||||
|
|
||||||
|
When a subdivision method is developed, a refinement pattern is
|
||||||
|
chosen, and then a set of geometry masks are developed to
|
||||||
|
position the new points. There are three key components
|
||||||
|
to implement a subdivision method:
|
||||||
|
<UL>
|
||||||
|
<LI>a mesh data structure that can represent arbitrary 2-manifolds,
|
||||||
|
<LI>a process that refines the mesh data structure,
|
||||||
|
<LI>and the geometry masks that compute the new points.
|
||||||
|
</UL>
|
||||||
|
|
||||||
|
E. Catmull and J. Clark picked the
|
||||||
|
PQQ refinement for their subdivision method,
|
||||||
|
and developed a set of geometry masks to generate (or more
|
||||||
|
precisely, to approximate) the B-spline surface from
|
||||||
|
the control mesh.
|
||||||
|
`Subdivision_method_3` provides a function that glues all
|
||||||
|
three components of the Catmull-Clark subdivision method.
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
|
||||||
|
template <class Polyhedron_3, template <typename> class Mask>
|
||||||
|
void PQQ(Polyhedron_3& p, Mask<Polyhedron_3> mask, int depth)
|
||||||
|
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
`Polyhedron_3` is a generic mesh data structure for
|
||||||
|
arbitrary 2-manifolds. `PQQ()`, which refines the control mesh
|
||||||
|
`p`, is a <I>refinement host</I> that uses a policy class
|
||||||
|
`Mask<Polyhedron_3>` as part of it geometry computation.
|
||||||
|
During the refinement, `PQQ()` computes and assigns
|
||||||
|
new points by cooperating with the `mask`.
|
||||||
|
To implement Catmull-Clark subdivision,
|
||||||
|
`Mask`, the <I>geometry policy</I>, has to realize the
|
||||||
|
geometry masks of Catmull-Clark subdivision.
|
||||||
|
`depth` specifies the iterations of the refinement
|
||||||
|
on the control mesh.
|
||||||
|
|
||||||
|
To implement the geometry masks, we need to know how
|
||||||
|
a refinement host communicates with its geometry masks.
|
||||||
|
The PQQ refinement defines three stencils, and hence
|
||||||
|
three geometry masks are required for Catmull-Clark subdivision.
|
||||||
|
The following class defines the interfaces of the stencils
|
||||||
|
for the PQQ refinement.
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
class PQQ_stencil_3 {
|
||||||
|
void facet_node(Facet_handle facet, Point_3& pt);
|
||||||
|
void edge_node(Halfedge_handle edge, Point_3& pt);
|
||||||
|
void vertex_node(Vertex_handle vertex, Point_3& pt);
|
||||||
|
};
|
||||||
|
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
Each class function in `PQQ_stencil_3`
|
||||||
|
computes a new point based on the neighborhood of the primitive
|
||||||
|
handle, and assigns the new point to `Point_3& pt`.
|
||||||
|
|
||||||
|
We realize each class function with the geometry masks of
|
||||||
|
Catmull-Clark subdivision.
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
class CatmullClark_mask_3 {
|
||||||
|
void facet_node(Facet_handle facet, Point_3& pt) {
|
||||||
|
Halfedge_around_facet_circulator hcir = facet->facet_begin();
|
||||||
|
int n = 0;
|
||||||
|
Point_3 p(0,0,0);
|
||||||
|
do {
|
||||||
|
p = p + (hcir->vertex()->point() - ORIGIN);
|
||||||
|
++n;
|
||||||
|
} while (++hcir != facet->facet_begin());
|
||||||
|
pt = ORIGIN + (p - ORIGIN)/FT(n);
|
||||||
|
}
|
||||||
|
void edge_node(Halfedge_handle edge, Point_3& pt) {
|
||||||
|
Point_3 p1 = edge->vertex()->point();
|
||||||
|
Point_3 p2 = edge->opposite()->vertex()->point();
|
||||||
|
Point_3 f1, f2;
|
||||||
|
facet_node(edge->facet(), f1);
|
||||||
|
facet_node(edge->opposite()->facet(), f2);
|
||||||
|
pt = Point_3((p1[0]+p2[0]+f1[0]+f2[0])/4,
|
||||||
|
(p1[1]+p2[1]+f1[1]+f2[1])/4,
|
||||||
|
(p1[2]+p2[2]+f1[2]+f2[2])/4 );
|
||||||
|
}
|
||||||
|
void vertex_node(Vertex_handle vertex, Point_3& pt) {
|
||||||
|
Halfedge_around_vertex_circulator vcir = vertex->vertex_begin();
|
||||||
|
int n = circulator_size(vcir);
|
||||||
|
|
||||||
|
FT Q[] = {0.0, 0.0, 0.0}, R[] = {0.0, 0.0, 0.0};
|
||||||
|
Point_3& S = vertex->point();
|
||||||
|
|
||||||
|
Point_3 q;
|
||||||
|
for (int i = 0; i < n; i++, ++vcir) {
|
||||||
|
Point_3& p2 = vcir->opposite()->vertex()->point();
|
||||||
|
R[0] += (S[0]+p2[0])/2;
|
||||||
|
R[1] += (S[1]+p2[1])/2;
|
||||||
|
R[2] += (S[2]+p2[2])/2;
|
||||||
|
facet_node(vcir->facet(), q);
|
||||||
|
Q[0] += q[0];
|
||||||
|
Q[1] += q[1];
|
||||||
|
Q[2] += q[2];
|
||||||
|
}
|
||||||
|
R[0] /= n; R[1] /= n; R[2] /= n;
|
||||||
|
Q[0] /= n; Q[1] /= n; Q[2] /= n;
|
||||||
|
|
||||||
|
pt = Point_3((Q[0] + 2*R[0] + S[0]*(n-3))/n,
|
||||||
|
(Q[1] + 2*R[1] + S[1]*(n-3))/n,
|
||||||
|
(Q[2] + 2*R[2] + S[2]*(n-3))/n );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
This example shows the default implementation of Catmull-Clark
|
||||||
|
masks in `Subdivision_method_3`.
|
||||||
|
This default implementation assumes the <I>types</I>
|
||||||
|
(such as `Point_3` and `Facet_handle`) are defined
|
||||||
|
within `Polyhedron_3`. `CatmullClark_mask_3`
|
||||||
|
is designed to work on a `Polyhedron_3` with the `Cartesian`
|
||||||
|
kernel. You may need to rewrite the geometry computation
|
||||||
|
to match the kernel geometry of your application.
|
||||||
|
|
||||||
|
To invoke the Catmull-Clark subdivision method, we
|
||||||
|
call `PQQ()` with the Catmull-Clark masks we just defined.
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
|
||||||
|
PQQ(p, CatmullClark_mask_3<Polyhedron_3>(), depth);
|
||||||
|
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
Loop, Doo-Sabin and \f$ \sqrt{3}\f$ subdivisions are implemented
|
||||||
|
in the similar process: pick a refinement host and implement
|
||||||
|
the geometry policy. The key of developing your own
|
||||||
|
subdivision method is implementing the right combination of
|
||||||
|
the refinement host and the geometry policy. It is
|
||||||
|
explained in the next two sections.
|
||||||
|
|
||||||
|
\section secRefHost Refinement Host
|
||||||
|
|
||||||
|
A refinement host is a template function of
|
||||||
|
a polyhedron class and a geometry mask class. It refines
|
||||||
|
the input polyhedron, and computes new points through the geometry masks.
|
||||||
|
`Subdivision_method_3` supports four refinement hosts:
|
||||||
|
primal quadrilateral quadrisection (PQQ),
|
||||||
|
primal triangle quadrisection (PTQ), dual quadrilateral
|
||||||
|
quadrisection (DQQ) and \f$ \sqrt{3}\f$ triangulation.
|
||||||
|
Respectively, they are used by Catmull-Clark, Loop, Doo-Sabin
|
||||||
|
and \f$ \sqrt{3}\f$ subdivision.
|
||||||
|
|
||||||
|
\image html RefSchemes.gif
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
|
||||||
|
namespace Subdivision_method_3 {
|
||||||
|
template <class Polyhedron_3, template <typename> class Mask>
|
||||||
|
void PQQ(Polyhedron_3& p, Mask<Polyhedron_3> mask, int step);
|
||||||
|
|
||||||
|
template <class Polyhedron_3, template <typename> class Mask>
|
||||||
|
void PTQ(Polyhedron_3& p, Mask<Polyhedron_3> mask, int step);
|
||||||
|
|
||||||
|
template <class Polyhedron_3, template <typename> class Mask>
|
||||||
|
void DQQ(Polyhedron_3& p, Mask<Polyhedron_3> mask, int step)
|
||||||
|
|
||||||
|
template <class Polyhedron_3, template <typename> class Mask>
|
||||||
|
void Sqrt3(Polyhedron_3& p, Mask<Polyhedron_3> mask, int step)
|
||||||
|
}
|
||||||
|
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
The polyhedron class is a specialization of
|
||||||
|
`Polyhedron_3`, and the mask is a policy
|
||||||
|
class realizing the geometry masks of the subdivision
|
||||||
|
method.
|
||||||
|
|
||||||
|
A refinement host refines the input polyhedron, maintains
|
||||||
|
the stencils (i.e., the mapping between the control mesh
|
||||||
|
and the refined mesh), and calls the geometry masks
|
||||||
|
to compute the new points.
|
||||||
|
In `Subdivision_method_3`, refinements are implemented
|
||||||
|
as a sequence of connectivity operations (mainly Euler operations).
|
||||||
|
The order of the connectivity operations plays a key role when maintaining
|
||||||
|
stencils. By matching the order of the source submeshes to the refined
|
||||||
|
vertices, no flag in the primitives is required to register the stencils.
|
||||||
|
It avoids the data dependency of the refinement host on the polyhedron class.
|
||||||
|
To make the ordering trick work, the polyhedron class must
|
||||||
|
have a sequential container, such as a vector or a linked-list, as
|
||||||
|
the internal storage.
|
||||||
|
A sequential container guarantees that the iterators of the
|
||||||
|
polyhedron always traverse the primitives in the order of their
|
||||||
|
insertions. Non-sequential structures such as
|
||||||
|
trees or maps do not provide the required ordering, and hence
|
||||||
|
can not be used with `Subdivision_method_3`.
|
||||||
|
|
||||||
|
Although `Subdivision_method_3` does not require flags
|
||||||
|
to support the refinements and the stencils, it
|
||||||
|
still needs to know how to compute and store the geometry
|
||||||
|
data (i.e. the points). `Subdivision_method_3`
|
||||||
|
expects that the typename `Point_3` is
|
||||||
|
defined in the geometry kernel of the polyhedron
|
||||||
|
(i.e. the `Polyhedron_3::Traits::Kernel`).
|
||||||
|
A point of the type `Point_3` is returned by the geometry
|
||||||
|
policy and is then assigned to the new vertex.
|
||||||
|
The geometry policy is explained in next section.
|
||||||
|
|
||||||
|
Refinement hosts `PQQ` and `DQQ` work on a general
|
||||||
|
polyhedron, and `PTQ` and `Sqrt3` work on a triangulated
|
||||||
|
polyhedron. The result of `PTQ` and `Sqrt3` on a non-triangulated
|
||||||
|
polyhedron is undefined. `Subdivision_method_3` does not verify
|
||||||
|
the precondition of the mesh characteristics before the refinement.
|
||||||
|
|
||||||
|
For details of the refinement implementation,
|
||||||
|
interested users should refer to \cite cgal:sp-mrbee-05.
|
||||||
|
|
||||||
|
# Geometry Policy #
|
||||||
|
|
||||||
|
A geometry policy defines a set of geometry masks.
|
||||||
|
Each geometry mask is realized as a member function
|
||||||
|
that computes new points of the subdivision surface.
|
||||||
|
|
||||||
|
Each geometry mask receives a primitive handle
|
||||||
|
(e.g. `Halfedge_handle`) of the control mesh,
|
||||||
|
and returns a `Point_3` to the subdivided vertex.
|
||||||
|
The function collects the vertex neighbors of the primitive handle
|
||||||
|
(i.e. nodes on the stencil), and computes the new point
|
||||||
|
based on the neighbors and the mask (i.e. the stencil weights).
|
||||||
|
|
||||||
|
\image html cc_mask.gif
|
||||||
|
|
||||||
|
This figure shows the geometry masks of
|
||||||
|
Catmull-Clark subdivision. The weights shown here are unnormalized,
|
||||||
|
and \f$ n\f$ is the valence of the vertex. The new points are
|
||||||
|
computed by the summation of the weighted points on their stencils.
|
||||||
|
Following codes show an implementation of the geometry mask of
|
||||||
|
the facet-node. The complete listing
|
||||||
|
of a Catmull-Clark geometry policy is in the Section \ref secCC.
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
class CatmullClark_mask_3 {
|
||||||
|
void facet_node(Facet_handle facet, Point_3& pt) {
|
||||||
|
Halfedge_around_facet_circulator hcir = facet->facet_begin();
|
||||||
|
int n = 0;
|
||||||
|
Point_3 p(0,0,0);
|
||||||
|
do {
|
||||||
|
p = p + (hcir->vertex()->point() - ORIGIN);
|
||||||
|
++n;
|
||||||
|
} while (++hcir != facet->facet_begin());
|
||||||
|
pt = ORIGIN + (p - ORIGIN)/FT(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
In this example, the computation is based on the assumption that
|
||||||
|
the `Point_3` is the `CGAL::Point_3`. It is an assumption,
|
||||||
|
but not a restriction.
|
||||||
|
You are allowed to use any point class as long as it is
|
||||||
|
defined as the `Point_3` in your polyhedron.
|
||||||
|
You may need to modify the geometry policy to support the computation
|
||||||
|
and the assignment of the specialized point. This extension is not unusual
|
||||||
|
in graphics applications. For example, you might want to subdivide the
|
||||||
|
texture coordinates for your subdivision surface.
|
||||||
|
|
||||||
|
The refinement host of Catmull-Clark subdivision
|
||||||
|
requires three geometry masks for
|
||||||
|
polyhedrons without open boundaries: a vertex-node
|
||||||
|
mask, an edge-node mask, and a facet-node mask.
|
||||||
|
To support polyhedrons with boundaries, a border-node mask is
|
||||||
|
also required. The border-node mask for Catmull-Clark subdivision
|
||||||
|
is listed below, where `ept` returns the new point splitting
|
||||||
|
`edge` and `vpt` returns the new point on the vertex pointed by
|
||||||
|
`edge`.
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
|
||||||
|
void border_node(Halfedge_handle edge, Point_3& ept, Point_3& vpt) {
|
||||||
|
Point_3& ep1 = edge->vertex()->point();
|
||||||
|
Point_3& ep2 = edge->opposite()->vertex()->point();
|
||||||
|
ept = Point_3((ep1[0]+ep2[0])/2, (ep1[1]+ep2[1])/2, (ep1[2]+ep2[2])/2);
|
||||||
|
|
||||||
|
Halfedge_around_vertex_circulator vcir = edge->vertex_begin();
|
||||||
|
Point_3& vp1 = vcir->opposite()->vertex()->point();
|
||||||
|
Point_3& vp0 = vcir->vertex()->point();
|
||||||
|
Point_3& vp_1 = (--vcir)->opposite()->vertex()->point();
|
||||||
|
vpt = Point_3((vp_1[0] + 6*vp0[0] + vp1[0])/8,
|
||||||
|
(vp_1[1] + 6*vp0[1] + vp1[1])/8,
|
||||||
|
(vp_1[2] + 6*vp0[2] + vp1[2])/8 );
|
||||||
|
}
|
||||||
|
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
The mask interfaces of all four refinement hosts are listed below.
|
||||||
|
`DQQ_stencil_3` and `Sqrt3_stencil_3`
|
||||||
|
do not have the border-node stencil because the refinement hosts of
|
||||||
|
DQQ and \f$ \sqrt{3}\f$ refinements do not support global boundaries in the
|
||||||
|
current release. This might be changed in the future releases.
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
class PQQ_stencil_3 {
|
||||||
|
void facet_node(Facet_handle, Point_3&);
|
||||||
|
void edge_node(Halfedge_handle, Point_3&);
|
||||||
|
void vertex_node(Vertex_handle, Point_3&);
|
||||||
|
|
||||||
|
void border_node(Halfedge_handle, Point_3&, Point_3&);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
class PTQ_stencil_3 {
|
||||||
|
void edge_node(Halfedge_handle, Point_3&);
|
||||||
|
void vertex_node(Vertex_handle, Point_3&);
|
||||||
|
|
||||||
|
void border_node(Halfedge_handle, Point_3&, Point_&);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
class DQQ_stencil_3 {
|
||||||
|
public:
|
||||||
|
void corner_node(Halfedge_handle edge, Point_3& pt);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
class Sqrt3_stencil_3 {
|
||||||
|
public:
|
||||||
|
void vertex_node(Vertex_handle vertex, Point_3& pt);
|
||||||
|
};
|
||||||
|
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
The source codes of `CatmullClark_mask_3`, `Loop_mask_3`,
|
||||||
|
`DooSabin_mask_3`, and `Sqrt3_mask_3` are
|
||||||
|
the best sources of learning these stencil interfaces.
|
||||||
|
|
||||||
|
# The Four Subdivision Methods #
|
||||||
|
|
||||||
|
`Subdivision_method_3` supports Catmull-Clark, Loop,
|
||||||
|
Doo-Sabin and \f$ \sqrt{3}\f$ subdivisions by specializing
|
||||||
|
their respective refinement hosts.
|
||||||
|
They are designed to work on a `Polyhedron_3`. If your application
|
||||||
|
uses a polyhedron with a specialized geometry kernel, you need to
|
||||||
|
specialize the refinement host with a geometry policy
|
||||||
|
based on that kernel.
|
||||||
|
|
||||||
|
\code{.cpp}
|
||||||
|
|
||||||
|
namespace Subdivision_method_3 {
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
void CatmullClark_subdivision(Polyhedron_3& p, int step = 1) {
|
||||||
|
PQQ(p, CatmullClark_mask_3<Polyhedron_3>(), step);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
void Loop_subdivision(Polyhedron_3& p, int step = 1) {
|
||||||
|
PTQ(p, Loop_mask_3<Polyhedron_3>() , step);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
void DooSabin_subdivision(Polyhedron_3& p, int step = 1) {
|
||||||
|
DQQ(p, DooSabin_mask_3<Polyhedron_3>(), step);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Polyhedron_3>
|
||||||
|
void Sqrt3_subdivision(Polyhedron_3& p, int step = 1) {
|
||||||
|
Sqrt3(p, Sqrt3_mask_3<Polyhedron_3>(), step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
The following example demonstrates the use of Doo-Sabin subdivision
|
||||||
|
on a polyhedral mesh.
|
||||||
|
\cgalexample{DooSabin_subdivision.cpp}
|
||||||
|
|
||||||
|
# Other Subdivision Methods #
|
||||||
|
|
||||||
|
`Subdivision_method_3` supports four practical subdivision methods on a
|
||||||
|
Cartesian `Polyhedron_3`. More subdivision methods can be supported
|
||||||
|
through the specialization of refinement hosts with custom geometry masks.
|
||||||
|
The following example develops a subdivision method
|
||||||
|
generating an improved Loop subdivision surface.
|
||||||
|
|
||||||
|
\cgalexample{Customized_subdivision.cpp}
|
||||||
|
|
||||||
|
The points generated by the geometry mask are semantically
|
||||||
|
required to converge to a smooth surface. This is the requirement
|
||||||
|
imposed by the theory of the subdivision surface.
|
||||||
|
`Subdivision_method_3` does not enforce this requirement, nor will
|
||||||
|
it verify the smoothness of the subdivided mesh.
|
||||||
|
`Subdivision_method_3` guarantees the topological properties of
|
||||||
|
the subdivided mesh. A genus-\f$ n\f$ 2-manifold is assured to be subdivided
|
||||||
|
into a genus-\f$ n\f$ 2-manifold. But when specialized with ill-designed
|
||||||
|
geometry masks, `Subdivision_method_3` may generate a surface that is
|
||||||
|
odd, not smooth, or not even exist.
|
||||||
|
|
||||||
|
*/
|
||||||
|
} /* namespace CGAL */
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 979 B |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 71 KiB |