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_tex/IOstream/io.png -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/PQQStencil.fig -text svneol=unset#application/octet-stream
|
||||
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>
|
||||
</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>
|
||||
<name>2D Placement of Streamlines</name>
|
||||
<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>../Voronoi_diagram_2/doc/Voronoi_diagram_2/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>../Stream_lines_2/doc/Stream_lines_2/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/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/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_support.tag=../../CGAL.CGAL.IO-Streams/html</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 |