mirror of https://github.com/CGAL/cgal
105 lines
2.8 KiB
TeX
105 lines
2.8 KiB
TeX
|
|
The quad-triangle subdivision scheme was introduced by
|
|
Levin~\cite{l-pg-03}, then Stam and Loop~\cite{qts}. It applies
|
|
to polygon meshes and basically features Loop subdivision on triangles
|
|
and Catmull-Clark subdivision on polygons of the control mesh (see
|
|
Fig.\ref{fig:quad-triangle}). After one iteration of subdivision the
|
|
subdivided model is only composed of triangles and quads.
|
|
|
|
|
|
% quad-triangle subdivision scheme
|
|
|
|
\begin{figure}[htb]
|
|
\centering{\includegraphics[width=10.0cm]{figs/quad-triangle}}
|
|
\caption{Quad-triangle subdivision of the rhombicuboctahedron mesh.}
|
|
\label{fig:quad-triangle}
|
|
\end{figure}
|
|
|
|
A simple solution for implementing such a scheme is to use the
|
|
\italic{incremental builder} offered for the CGAL Polyhedron.
|
|
The polyhedron provides a backdoor access to the
|
|
underlying halfedge data structure with the \CodeFmt{CGAL::Modifier}
|
|
class and checks the
|
|
integrity of the data structure when this access finishes. The prime
|
|
example for this backdoor use is an alternative way of describing
|
|
meshes in the indexed-facet-set format that is common in file formats:
|
|
Points are defined with coordinates, then facets are
|
|
defined by the points on their boundary, but the points are given as
|
|
indices to the already given list of points.
|
|
|
|
In the example below we make use of the incremental builder to
|
|
assemble a subdivided polyhedron from an input polyhedron. Our implementation
|
|
requires enriched halfedge, vertex and facet primitives with an
|
|
integer tag that recovers the vertex indices of the subdivided model.
|
|
|
|
\begin{lstlisting}
|
|
#include "enriched_polyhedron.h"
|
|
#include "builder.h"
|
|
|
|
template <class HDS,class Polyhedron,class kernel>
|
|
class CModifierQuadTriangle : public CGAL::Modifier_base<HDS>
|
|
{
|
|
private:
|
|
|
|
typedef ...
|
|
|
|
Polyhedron *m_pMesh;
|
|
|
|
public:
|
|
|
|
// life cycle
|
|
CModifierQuadTriangle(Polyhedron *pMesh)
|
|
{
|
|
CGAL_assertion(pMesh != NULL);
|
|
m_pMesh = pMesh;
|
|
}
|
|
~CModifierQuadTriangle() {}
|
|
|
|
// subdivision
|
|
void operator()( HDS& hds)
|
|
{
|
|
builder B(hds,true);
|
|
B.begin_surface(3,1,6);
|
|
add_vertices(B);
|
|
add_facets(B);
|
|
B.end_surface();
|
|
}
|
|
|
|
private:
|
|
|
|
// ...
|
|
// for the complete implementation of the subdivision,
|
|
// readers should refer to the accompanied source codes of
|
|
// this tutorial.
|
|
|
|
};
|
|
|
|
template <class Polyhedron,class kernel>
|
|
class CSubdivider_quad_triangle
|
|
{
|
|
public:
|
|
typedef typename Polyhedron::HalfedgeDS HalfedgeDS;
|
|
|
|
public:
|
|
// life cycle
|
|
CSubdivider_quad_triangle() {}
|
|
~CSubdivider_quad_triangle() {}
|
|
|
|
public:
|
|
void subdivide(Polyhedron &OriginalMesh,
|
|
Polyhedron &NewMesh,
|
|
bool smooth_boundary = true)
|
|
{
|
|
CModifierQuadTriangle<HalfedgeDS,Polyhedron,kernel>
|
|
builder(&OriginalMesh);
|
|
|
|
// delegate construction
|
|
NewMesh.delegate(builder);
|
|
|
|
// smooth
|
|
builder.smooth(&NewMesh,smooth_boundary);
|
|
}
|
|
};
|
|
\end{lstlisting}
|
|
|