cgal/Tutorial/tutorial/Polyhedron/sgp2004/paper/subtempl.tex

184 lines
8.1 KiB
TeX

% subtempl.tex
% -------------------------------------------
Policy-based design \cite{Alexandrescu:2001:MCD} assembles a class
(called \emph{host}) with complex behavior out of many small behaviors
(called \emph{policies}). Each policy defines an interface for a
specific behavior. Following this design principle, we implement a
generic subdivision solution as a \emph{refinement function\/}
parameterized with the \emph{stencils}. The host, i.e., the refinement
function, conducts the \tr\ and applies the stencils provided by the
policies for the \gm s. We provide different hosts and different
policies that can be combined to form subdivision schemes. We
demonstrate the principle with the Catmull-Clark and the Doo-Sabin
subdivision. A Catmull-Clark subdivision is structured as a
primal quadralization function parameterized with a corresponding
stencil policy.
\begin{lstlisting}
void CatmullClark_subdivision(Polyhedron& p) {
quadralize_polyhedron<CatmullClark_rule<Polyhedron>>(p);
}
class CatmullClark_rule {
public:
void facet_rule( Facet_handle facet, Point& pt);
void edge_rule(Halfedge_handle edge, Point& pt);
void vertex_rule(Vertex_handle vertex, Point& pt);
};
\end{lstlisting}\vspace*{-3mm}
\noindent
The \CodeFmt{quadralize\_polyhedron<>()} is the host function
refining the input mesh
and the \CodeFmt{CatmullClark\_rule} is the policy class applying the
Catmull-Clark stencils. The \CodeFmt{quadralize\_polyhedron<>()}
refines the control mesh while maintaining the
correspondence with the stencil, i.e., the submesh centered
around the given facet, edge, or
vertex, and the smoothing point. The smoothing point
is calculated by calling the policies, i.e.,
the \CodeFmt{facet\_rule()}, the \CodeFmt{edge\_rule()},
and the \CodeFmt{vertex\_rule()} respectively.
%Different refinement scheme may require a
%different set of stencils. A PQQ scheme needs the
%facet-, edge- and vertex-stencils whereas a DQQ scheme
%only needs the corner-stencils (Fig.\ref{fig:RefMap}).
\noindent\textbf{Geometry Policies}.
Inside a policy, applying the stencil is simplified to
the mesh traversal of a 1-ring neighborhood. We can use circulators
again, as in the following example for the policy of the facet-stencil
in the Catmull-Clark subdivision.
\begin{lstlisting}
void facet_rule(Facet_handle facet, Point& point) {
Halfedge_around_facet_circulator hcir = facet->facet_begin();
Vector vec = hcir->vertex()->point() - ORIGIN;
++hcir;
do {
vec = vec + hcir->vertex()->point();
} while (++hcir != facet->facet_begin());
point = ORIGIN + vec/circulator_size(hcir);
}
\end{lstlisting}\vspace*{-3mm}
\noindent
The \CodeFmt{facet} points to the center facet of the stencil and the
\CodeFmt{point} specifies the smoothing point. We compute the centroid
with a circulator loop over the halfedges surrounding a facet. The
\cgal\ geometric kernel is used here, but special computations may be
done in user-defined policies.
%with point and vector arithmetic.
%However, for a specialized kernel, special computations may be
%done in user-defined policies.
\noindent\textbf{The refinement host based on Euler operations}.
Implementing the topology refinement is a complex task. One
approach is to encode the refinement into \emph{a sequence of Euler
operations}. For Catmull-Clark subdivision, the refinement is encoded
as edge-vertex insertions, an edge insertion between two neighboring
edge-vertices, a facet-vertex insertion on the inserted edge, and
edge insertions between the facet-vertex and the edge-vertices
(Fig~.\ref{fig:CCRefinement}). These are Euler operations supported
by \cgalpoly.
\begin{figure}
\centering
\epsfig{file=figs/CCRefinement.eps, width=7cm}
\caption{A PQQ refinement of a facet is encoded into a sequence of
vertex insertions and edge insertions. Red indicates the inserted
vertices and edges in each step.}
\label{fig:CCRefinement}\vspace*{-2mm}
\end{figure}
The correspondence between stencil and control mesh is assured in the
refinement with a consistent \emph{traversal sequence\/} on the mesh.
The refinement host has a two pass algorithm, hence two traversals.
The first pass generates the points by calling the policies. The
second pass refines the mesh with a sequence of the Euler operations.
The points generated in the first pass are stored in a point buffer in
the order of the stencil traversal. The sequence of the vertex
insertions is consistent to match the stencil traversal, i.e.\ the
storage order of the point buffer.
% It assures the stencil correspondence of the refinement.
\noindent\textbf{Refinement host based on the modifier callback mechanism}.
Most primal refinement schemes are easy to express in Euler
operations. But dual schemes, e.g.\ Doo-Sabin subdivision, are
different. A sequence of Euler operations for a DQQ scheme consists of
twice the midedge refinement \cite{Peters:1997:SSS} and results
an inefficient implementation. The separation of a
subdivision scheme into multipass refinement is
called subdivision factorization \cite{Joe:2003:FASS, Denis:2001:UFPDQ}.
To support such schemes efficiently, we use
the modifier callback mechanism and the incremental builder of
\cgalpoly\ to rebuild the mesh connectivity. In addition to the point
buffer, we also create a facet list based on the source mesh. Note
that in a DQQ scheme, every new facet corresponds to a vertex, edge or
facet. The combination of the points buffer and facet list represent a
facet-vertex index list which indexes the vertices and enumerates each
facet as an index sequence. A modifier creating a polyhedron from such
a representation is straightforward, here a sketch using the
incremental builder \CodeFmt{pb}.
\begin{lstlisting}
pb.begin_surface(num_point, num_facet);
for (int i = 0; i < num_point; ++i)
pb.add_vertex(Point(point_buffer[i*3+0],
point_buffer[i*3+1],
point_buffer[i*3+2]));
for (int i = 0; i < num_facet; ++i) {
pb.begin_facet();
for (int n = 0; n < facet_buffer[i][0]; ++n)
pb.add_vertex_to_facet(facet_buffer[i][n+1]);
pb.end_facet();
}
pb.end_surface();
\end{lstlisting}\vspace*{-3mm}
\begin{figure}
\centering
\epsfig{file=figs/plane0.eps, width=2.35cm} \\
\epsfig{file=figs/planeCC1.eps, width=2.35cm}
\epsfig{file=figs/planeCC2.eps, width=2.35cm}
\epsfig{file=figs/planeCC.eps, width=2.35cm}\\
\epsfig{file=figs/planeDS1.eps, width=2.35cm}
\epsfig{file=figs/planeDS2.eps, width=2.35cm}
\epsfig{file=figs/planeDS.eps, width=2.35cm}
\caption{Catmull-Clark subdivision surfaces ({\itshape second row}) and
Doo-Sabin subdivision surfaces ({\itshape third row})
of an aircraft polyhedron ({\itshape first row}).
}
\label{fig:SubExample}\vspace*{-2mm}
\end{figure}
\noindent\textbf{The subdivision library.}
Our subdivision design solution, decoupling the geometry rules from
the refinement, grants users flexible control of the stencils.
Variants of subdivisions can be devised by simply combining different
refinement hosts and geometric policies. A combinatorial subdivision
set is provided within our subdivision library. It includes
Catmull-Clark subdivision, Doo-Sabin subdivision, Loop subdivision,
Quad-Triangle subdivision and $\sqrt{3}$ subdivision. Since \cgalpoly\
supports non-uniform meshes (in contrast to the quad-tree or
patch-based implementation), chains of different refinements are
naturally supported.
%\begin{lstlisting}
%void MySubdivision(Polyhedron& p) {
% quadralize_polyhedron<Myrule_1<Polyhedron>>(p);
% dualize_polyhedron<Myrule_2<Polyhedron>>(p);
%}
%\end{lstlisting}
Furthermore, our solution is parameterized with the mesh structure and
can thus be applied to user-specialized versions of \cgalpoly. Note
that no special flag or attribute is required to assist the \tr . This
generality makes our solution naturally fit in a modeling pipeline or a
multipass modeling environment.
%In some applications, efficiency is more
%important than flexibility. An efficient implementation
%of $\sqrt{3}$ based on \cgalpoly\ is introduced in next
%section.
%TODO: since the writing memory is not overlapped, multi-threaded
%supporting is easily done.
%TODO: trade-off between generic and efficient.