The user manual should be ok now

This commit is contained in:
Andreas Fabri 2017-01-04 15:29:33 +01:00 committed by Mael Rouxel-Labbé
parent 8af4f2b433
commit b74b3b754e
7 changed files with 186 additions and 153 deletions

View File

@ -9,7 +9,8 @@ whose points contribute to the position of a refined point.
The geometry mask of a stencil specifies The geometry mask of a stencil specifies
the computation on the nodes of the stencil. the computation on the nodes of the stencil.
`CatmullClark_mask_3` implements the geometry masks of `CatmullClark_mask_3` implements the geometry masks of
Catmull-Clark subdivision on a `CGAL::Polyhedron_3<Cartesian>`. Catmull-Clark subdivision on models of `MutableFaceGraph`,
such as `Polyhedron_3` and `Surface_mesh`.
\tparam PolygonMesh must be a model of the concept `MutableFaceGraph`. \tparam PolygonMesh must be a model of the concept `MutableFaceGraph`.
\tparam VertexPointMap must be a model of `WritablePropertyMap` with value type `Point_3` \tparam VertexPointMap must be a model of `WritablePropertyMap` with value type `Point_3`
@ -32,8 +33,8 @@ public:
/*! /*!
Constructor. Constructor.
*/ */
CatmullClark_mask_3(PolygonMesh& pm, CatmullClark_mask_3(PolygonMesh& pmesh,
VertexPointMap vpm = get(vertex_point,pm) ); VertexPointMap vpm = get(vertex_point, pmesh) );
/// @} /// @}
@ -84,7 +85,8 @@ whose points contribute to the position of a refined point.
The geometry mask of a stencil specifies The geometry mask of a stencil specifies
the computation on the nodes of the stencil. the computation on the nodes of the stencil.
`DooSabin_mask_3` implements the geometry masks of `DooSabin_mask_3` implements the geometry masks of
Doo-Sabin subdivision on a `Polyhedron_3<Cartesian>`. Doo-Sabin subdivision on models of `MutableFaceGraph`,
such as `Polyhedron_3` and `Surface_mesh`.
\tparam PolygonMesh must be a model of the concept `MutableFaceGraph`. \tparam PolygonMesh must be a model of the concept `MutableFaceGraph`.
\tparam VertexPointMap must be a model of `WritablePropertyMap` with value type `Point_3` \tparam VertexPointMap must be a model of `WritablePropertyMap` with value type `Point_3`
@ -107,8 +109,8 @@ public:
/*! /*!
Constructor. Constructor.
*/ */
DooSabin_mask_3(PolygonMesh& pm, DooSabin_mask_3(PolygonMesh& pmesh,
VertexPointMap vpm = get(vertex_point,pm) ); VertexPointMap vpm = get(vertex_point, pmesh) );
/// @} /// @}
@ -138,9 +140,10 @@ whose points contribute to the position of a refined point.
The geometry mask of a stencil specifies The geometry mask of a stencil specifies
the computation on the nodes of the stencil. the computation on the nodes of the stencil.
`Loop_mask_3` implements the geometry masks of `Loop_mask_3` implements the geometry masks of
Loop subdivision on a triangulated `Polyhedron_3<Cartesian>`. Loop subdivision on a triangulated model of `MutableFaceGraph`,
such as `Polyhedron_3` and `Surface_mesh`.
\tparam TriangleMesh must be a model of the concept `MutableFaceGraph`. \tparam PolygonMesh must be a model of the concept `MutableFaceGraph`. Additionally all faces must be triangles.
\tparam VertexPointMap must be a model of `WritablePropertyMap` with value type `Point_3` \tparam VertexPointMap must be a model of `WritablePropertyMap` with value type `Point_3`
\image html LoopBorderMask.png \image html LoopBorderMask.png
@ -151,7 +154,7 @@ Loop subdivision on a triangulated `Polyhedron_3<Cartesian>`.
\sa `CGAL::Subdivision_method_3` \sa `CGAL::Subdivision_method_3`
*/ */
template< typename TriangleMesh, typename VertexPointMap = typename boost::property_map<TriangleMesh, vertex_point_t>::type > template< typename PolygonMesh, typename VertexPointMap = typename boost::property_map<PolygonMesh, vertex_point_t>::type >
class Loop_mask_3 { class Loop_mask_3 {
public: public:
@ -161,8 +164,8 @@ public:
/*! /*!
Cnstructor. Cnstructor.
*/ */
Loop_mask_3(TriangleMesh& tm, Loop_mask_3(PolygonMesh& pmesh,
VertexPointMap vpm = get(vertex_point,tm) ); VertexPointMap vpm = get(vertex_point,pmesh) );
/// @} /// @}
@ -207,9 +210,10 @@ The geometry mask of a stencil specifies
the computation on the nodes of the stencil. the computation on the nodes of the stencil.
`Sqrt3_mask_3` implements the geometry masks of `Sqrt3_mask_3` implements the geometry masks of
\f$ \sqrt{3}\f$ subdivision on a triangulated \f$ \sqrt{3}\f$ subdivision on a triangulated
`CGAL::Polyhedron_3<Cartesian>`. model of `MutableFaceGraph`,
such as `Polyhedron_3` and `Surface_mesh`.
\tparam TriangleMesh must be a model of the concept `MutableFaceGraph`. \tparam PolygonMesh must be a model of the concept `MutableFaceGraph`. Additionally all faces must be triangles.
\tparam VertexPointMap must be a model of `WritablePropertyMap` with value type `Point_3` \tparam VertexPointMap must be a model of `WritablePropertyMap` with value type `Point_3`
\cgalModels `Sqrt3Mask_3` \cgalModels `Sqrt3Mask_3`
@ -217,7 +221,7 @@ the computation on the nodes of the stencil.
\sa `CGAL::Subdivision_method_3` \sa `CGAL::Subdivision_method_3`
*/ */
template< typename TriangleMesh, typename VertexPointMap = typename boost::property_map<TriangleMesh, vertex_point_t>::type > template< typename PolygonMesh, typename VertexPointMap = typename boost::property_map<PolygonMesh, vertex_point_t>::type >
class Sqrt3_mask_3 { class Sqrt3_mask_3 {
public: public:
@ -227,8 +231,8 @@ public:
/*! /*!
Constructor. Constructor.
*/ */
Sqrt3_mask_3(TriangleMesh& tm, Sqrt3_mask_3(PolygonMesh& pmesh,
VertexPointMap vpm = get(vertex_point,tm) ); VertexPointMap vpm = get(vertex_point,pmesh) );
/// @} /// @}

View File

@ -26,13 +26,13 @@ public:
/*! Constructor /*! Constructor
*/ */
DQQMask_3(PolygonMesh& pm); DQQMask_3(PolygonMesh& pmesh);
/*! /*!
computes the subdivided point `pt` based on the neighborhood computes the subdivided point `pt` based on the neighborhood
of the vertex pointed by the halfedge `he`. of the vertex pointed by the halfedge `hd`.
*/ */
void corner_node(halfedge_descriptor he, Point& pt); void corner_node(halfedge_descriptor hd, Point& pt);
/// @} /// @}

View File

@ -27,34 +27,34 @@ public:
/*! Constructor /*! Constructor
*/ */
PQQMask_3(PolygonMesh& pm); PQQMask_3(PolygonMesh& pmesh);
/*! /*!
computes the facet-point `pt` based on the neighborhood computes the facet-point `pt` based on the neighborhood
of the facet `f`. of the face `fd`.
*/ */
void facet_node(face_descriptor facet, Point_3& pt); void facet_node(face_descriptor fd, Point_3& pt);
/*! /*!
computes the edge-point `pt` based on the neighborhood computes the edge-point `pt` based on the neighborhood
of the edge `e`. of the edge `hd`.
*/ */
void edge_node(halfedge_descriptor e, Point_3& pt); void edge_node(halfedge_descriptor hd, Point_3& pt);
/*! /*!
computes the vertex-point `pt` based on the neighborhood computes the vertex-point `pt` based on the neighborhood
of the vertex `v`. of the vertex `vd`.
*/ */
void vertex_node(vertex_descriptor v, Point_3& pt); void vertex_node(vertex_descriptor vd, Point_3& pt);
/*! /*!
computes the edge-point `ept` and the vertex-point `vpt` computes the edge-point `ept` and the vertex-point `vpt`
based on the neighborhood of the border edge `e`. based on the neighborhood of the border edge `hd`.
*/ */
void border_node(halfedge_descriptor e, Point_3& ept, Point_3& vpt); void border_node(halfedge_descriptor hd, Point_3& ept, Point_3& vpt);
/// @} /// @}

View File

@ -18,33 +18,44 @@ policy concept of geometric computations is used in
class PTQMask_3 { class PTQMask_3 {
public: public:
/// \name Types
/// @{
/*! The polygon mesh must be triangulated.
*/
typedef unspecified_type PolygonMesh;
/// @}
/// \name Operations /// \name Operations
/// @{ /// @{
/*! Constructor /*! Constructor
*/ */
PTQMask_3(TriangleMesh& m); PTQMask_3(PolygonMesh& pmesh);
/*! /*!
computes the edge-point `pt` based on the neighborhood computes the edge-point `pt` based on the neighborhood
of the edge `e`. of the edge `hd`.
*/ */
void edge_node(Edge_handle e, Point_3& pt); void edge_node(halfedge_descriptor hd, Point_3& pt);
/*! /*!
computes the vertex-point `pt` based on the neighborhood computes the vertex-point `pt` based on the neighborhood
of the vertex `v`. of the vertex `vd`.
*/ */
void vertex_node(Vertex_handle v, Point_3& pt); void vertex_node(vertex_descriptor vd, Point_3& pt);
/*! /*!
computes the edge-point `ept` and the vertex-point `vpt` computes the edge-point `ept` and the vertex-point `vpt`
based on the neighborhood of the border edge `e`. based on the neighborhood of the border edge `hd`.
*/ */
void border_node(Halfedge_handle e, Point_3& ept, Point_3& vpt); void border_node(halfedge_descriptor hd, Point_3& ept, Point_3& vpt);
/// @} /// @}

View File

@ -17,25 +17,36 @@ policy concept of geometric computations is used in
class Sqrt3Mask_3 { class Sqrt3Mask_3 {
public: public:
/// \name Types
/// @{
/*! The polygon mesh must be triangulated.
*/
typedef unspecified_type PolygonMesh;
/// @}
/// \name Operations /// \name Operations
/// @{ /// @{
/*! Constructor /*! Constructor
*/ */
Sqrt3Mask_3(TriangleMesh& m); Sqrt3Mask_3(PolygonMesh& pmesh);
/*! /*!
computes the subdivided point `pt` based on the neighborhood computes the subdivided point `pt` based on the neighborhood
of the facet `f`. of the face `fd`.
*/ */
void facet_node(face_descriptor f, Point_3& pt); void facet_node(face_descriptor fd, Point_3& pt);
/*! /*!
computes the subdivided point `pt` based on the neighborhood computes the subdivided point `pt` based on the neighborhood
of the vertex `v`. of the vertex `vd`.
*/ */
void vertex_node(vertex_descriptor v, Point& pt); void vertex_node(vertex_descriptor vd, Point& pt);
/// @} /// @}

View File

@ -72,7 +72,7 @@ the subdivision surface.
\image latex RefSchemes.png \image latex RefSchemes.png
The figure demonstrates these four refinement patterns on The figure demonstrates these four refinement patterns on
the 1-disk of a valence-5 vertex/facet. the 1-disk of a valence-5 vertex/face.
Refined meshes are shown below the source meshes. Refined meshes are shown below the source meshes.
Points on the refined mesh are generated by averaging Points on the refined mesh are generated by averaging
neighbor points on the source mesh. A graph, called <I>stencil</I>, neighbor points on the source mesh. A graph, called <I>stencil</I>,
@ -82,8 +82,8 @@ more than one stencil.
For example, the PQQ For example, the PQQ
refinement has a vertex-node stencil, 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 vertex; an edge-node stencil,
which defines the 1-ring of an input edge; and a facet-node stencil, which defines the 1-ring of an input edge; and a face-node stencil,
which defines an input facet. The stencils of the PQQ refinement are which defines an input face. The stencils of the PQQ refinement are
shown in the following figure. The blue neighborhoods in the shown in the following figure. The blue neighborhoods in the
top row indicate the corresponding stencils of the refined nodes top row indicate the corresponding stencils of the refined nodes
in red. in red.
@ -104,11 +104,11 @@ below.
The weights shown here are unnormalized, and \f$ n\f$ is the valence 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 vertex. The generated point, in red, is computed by a summation
of the weighted points. For example, a Catmull-Clark facet-node is of the weighted points. For example, a Catmull-Clark face-node is
computed by the summation of \f$ 1/4\f$ of each point on its stencil. 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 stencil can have an unlimited number of geometry masks. For example,
a facet-node of PQQ refinement may be computed by a face-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$. 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 Although it is legal in `Subdivision_method_3` to have
any kind of geometry mask, the result surfaces may be odd, any kind of geometry mask, the result surfaces may be odd,
@ -144,21 +144,17 @@ subdivision function.
This example shows how to subdivide a simple `Polyhedron_3` This example shows how to subdivide a simple `Polyhedron_3`
with `Subdivision_method_3`. with `Subdivision_method_3`.
An application-defined polyhedron might use a specialized kernel and/or An application-defined polyhedron might use a specialized kernel and/or
a specialized internal container. There are two major restrictions on the a specialized internal container. There is one major restrictions on the
application-defined polyhedron to work with application-defined polyhedron to work with
`Subdivision_method_3`. `Subdivision_method_3`:
<UL> The primitives (such as vertices, halfedges and faces)
<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. in the internal container are sequentially ordered (e.g.
`std::vector` and `std::list`). `std::vector` and `std::list`).
This implies that the iterators traverse the primitives in This implies that the iterators traverse the primitives in
the order of their creations/insertions. the order of their creations/insertions.
</UL>
Section \ref secRefHost gives detailed explanations on those
Section \ref secRefHost gives detailed explanations on this
two restrictions. two restrictions.
\section secCC Catmull-Clark Subdivision \section secCC Catmull-Clark Subdivision
@ -219,7 +215,7 @@ for the PQQ refinement.
template <class PolygonMesh> template <class PolygonMesh>
class PQQMask_3 { class PQQMask_3 {
void face_node(boost::graph_traits<PolygonMesh>::face_descriptor facet, Point_3& pt); void face_node(boost::graph_traits<PolygonMesh>::face_descriptor face, Point_3& pt);
void edge_node(boost::graph_traits<PolygonMesh>::halfedge_descriptor edge, Point_3& pt); void edge_node(boost::graph_traits<PolygonMesh>::halfedge_descriptor edge, Point_3& pt);
void vertex_node(boost::graph_traits<PolygonMesh>::vertex_descriptor vertex, Point_3& pt); void vertex_node(boost::graph_traits<PolygonMesh>::vertex_descriptor vertex, Point_3& pt);
}; };
@ -237,65 +233,70 @@ Catmull-Clark subdivision.
template <class PolygonMesh> template <class PolygonMesh>
class CatmullClark_mask_3 { class CatmullClark_mask_3 {
void face_node(boost::graph_traits<PolygonMesh>::face_descriptor facet, Point_3& pt) {
Halfedge_around_facet_circulator hcir = facet->facet_begin(); typedef boost::graph_traits<PolygonMesh>::face_descriptor face_descriptor;
typedef boost::property_traits<VertexPointMap>::value_type Point;
Polygonmesh pmesh;
VertexPointMap vpm;
CatmullClark_mask_3(PolygonMesh &pmesh, VertexPointMap vpm)
: pmesh(pmesh, vpm(vpm)
{}
void face_node(face_descriptor face, Point& pt) {
int n = 0; int n = 0;
Point_3 p(0,0,0); Point_3 p(0,0,0);
do { for(halfedge_descriptor hd : halfedges_around_face(face,pmesh)){
p = p + (hcir->vertex()->point() - ORIGIN); p = p + get(vpm, (target(hd,pmesh)) - ORIGIN);
++n; ++n;
} while (++hcir != facet->facet_begin()); }
pt = ORIGIN + (p - ORIGIN)/FT(n); pt = ORIGIN + (p - ORIGIN)/FT(n);
} }
};
void edge_node(boost::graph_traits<PolygonMesh>::halfedge_descriptor edge, Point_3& pt) {
Point_3 p1 = edge->vertex()->point(); void edge_node(halfedge_descriptor edge, Point& pt) {
Point_3 p2 = edge->opposite()->vertex()->point(); Point p1 = get(vpm,target(edge, pmesh));
Point_3 f1, f2; Point p2 = get(vpm,source(edge, pmesh));
face_node(edge->facet(), f1); Point f1, f2;
face_node(edge->opposite()->facet(), f2); face_node(face(edge,pmesh), f1);
pt = Point_3((p1[0]+p2[0]+f1[0]+f2[0])/4, face_node(face(opposite(edge,pmesh),pmesh), f2);
(p1[1]+p2[1]+f1[1]+f2[1])/4, pt = Point((p1[0]+p2[0]+f1[0]+f2[0])/4,
(p1[2]+p2[2]+f1[2]+f2[2])/4 ); (p1[1]+p2[1]+f1[1]+f2[1])/4,
(p1[2]+p2[2]+f1[2]+f2[2])/4 );
} }
void vertex_node(boost::graph_traits<PolygonMesh>::vertex_descriptor vertex, Point_3& pt) { void vertex_node(vertex_descriptor vertex, Point& pt) {
Halfedge_around_vertex_circulator vcir = vertex->vertex_begin(); Halfedge_around_target_circulator<PolygonMesh> vcir(vertex,pmesh);
int n = circulator_size(vcir); typename boost::graph_traits<PolygonMesh>::degree_size_type n = degree(vertex,pmesh);
FT Q[] = {0.0, 0.0, 0.0}, R[] = {0.0, 0.0, 0.0}; FT Q[] = {0.0, 0.0, 0.0}, R[] = {0.0, 0.0, 0.0};
Point_3& S = vertex->point(); Point& S = get(vpm,vertex);
Point_3 q; Point q;
for (int i = 0; i < n; i++, ++vcir) { for (int i = 0; i < n; i++, ++vcir) {
Point_3& p2 = vcir->opposite()->vertex()->point(); Point& p2 = get(vpm, target(opposite(*vcir,pmesh),pmesh));
R[0] += (S[0]+p2[0])/2; R[0] += (S[0]+p2[0])/2;
R[1] += (S[1]+p2[1])/2; R[1] += (S[1]+p2[1])/2;
R[2] += (S[2]+p2[2])/2; R[2] += (S[2]+p2[2])/2;
face_node(vcir->facet(), q); face_node(face(*vcir,pmesh), q);
Q[0] += q[0]; Q[0] += q[0];
Q[1] += q[1]; Q[1] += q[1];
Q[2] += q[2]; Q[2] += q[2];
} }
R[0] /= n; R[1] /= n; R[2] /= n; R[0] /= n; R[1] /= n; R[2] /= n;
Q[0] /= n; Q[1] /= n; Q[2] /= n; Q[0] /= n; Q[1] /= n; Q[2] /= n;
pt = Point_3((Q[0] + 2*R[0] + S[0]*(n-3))/n, pt = Point((Q[0] + 2*R[0] + S[0]*(n-3))/n,
(Q[1] + 2*R[1] + S[1]*(n-3))/n, (Q[1] + 2*R[1] + S[1]*(n-3))/n,
(Q[2] + 2*R[2] + S[2]*(n-3))/n ); (Q[2] + 2*R[2] + S[2]*(n-3))/n );
} }
}; };
\endcode \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 `face_descriptor`) are defined
within `PolygonMesh`. `CatmullClark_mask_3`
is designed to work on a `PolygonMesh` 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 To invoke the Catmull-Clark subdivision method, we
call `PQQ()` with the Catmull-Clark masks we just defined. call `PQQ()` with the Catmull-Clark masks we just defined.
@ -331,22 +332,22 @@ and \f$ \sqrt{3}\f$ subdivision.
\code{.cpp} \code{.cpp}
namespace Subdivision_method_3 { namespace Subdivision_method_3 {
template <class PolygonMesh, template <typename> class Mask> template <class PolygonMesh, class Mask>
void PQQ(PolygonMesh& p, Mask<PolygonMesh> mask, int step); void PQQ(PolygonMesh& p, Mask mask, int step);
template <class TriangleMesh, template <typename> class Mask> template <class PolygonMesh, class Mask>
void PTQ(TriangleMesh& p, Mask<TriangleMesh> mask, int step); void PTQ(PolygonMesh& p, Mask mask, int step);
template <class PolygonMesh, template <typename> class Mask> template <class PolygonMesh, class Mask>
void DQQ(PolygonMesh& p, Mask<PolygonMesh> mask, int step) void DQQ(PolygonMesh& p, Mask mask, int step)
template <class TriangleMesh, template <typename> class Mask> template <class PolygonMesh, class Mask>
void Sqrt3(TriangleMesh& p, Mask<TriangleMesh> mask, int step) void Sqrt3(PolygonMesh& p, Mask mask, int step)
} }
\endcode \endcode
The mesh class is a specialization of The mesh class must be a model of
`MutableFaceGraph` and it must be a triangle mesh or a polygon mesh, `MutableFaceGraph` and it must be a triangle mesh or a polygon mesh,
and the mask is a policy class realizing the geometry masks of the and the mask is a policy class realizing the geometry masks of the
subdivision method. subdivision method.
@ -373,13 +374,10 @@ can not be used with `Subdivision_method_3`.
Although `Subdivision_method_3` does not require flags Although `Subdivision_method_3` does not require flags
to support the refinements and the stencils, it to support the refinements and the stencils, it
still needs to know how to compute and store the geometry still needs to know how to compute and store the geometry
data (i.e.\ the points). `Subdivision_method_3` data (i.e.\ the points). The classes of `Subdivision_method_3`
expects that the typename `Point_3` is have as optional template argument a vertex property map
defined in the geometry kernel of the polyhedron that provides a mapping between vertices and points.
(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 Refinement hosts `PQQ` and `DQQ` work on a general
polyhedron, and `PTQ` and `Sqrt3` work on a triangulated polyhedron, and `PTQ` and `Sqrt3` work on a triangulated
@ -416,22 +414,28 @@ of a Catmull-Clark geometry policy is in the Section \ref secCC.
\code{.cpp} \code{.cpp}
template <class PolygonMesh> template <class PolygonMesh, class VertexPointMap>
class CatmullClark_mask_3 { class CatmullClark_mask_3 {
void face_node(boost::graph_traits<PolygonMesh>::face_descriptor facet, Point_3& pt) {
Halfedge_around_facet_circulator hcir = facet->facet_begin(); typedef boost::graph_traits<PolygonMesh>::face_descriptor face_descriptor;
typedef boost::property_traits<VertexPointMap>::value_type Point;
CatmullClark_mask_3(PolygonMesh &pmesh, VertexPointMap vpm);
void face_node(face_descriptor face, Point& pt) {
int n = 0; int n = 0;
Point_3 p(0,0,0); Point_3 p(0,0,0);
do { for(halfedge_descriptor hd : halfedges_around_face(face,pmesh)){
p = p + (hcir->vertex()->point() - ORIGIN); p = p + get(vpm, (target(hd,pmesh)) - ORIGIN);
++n; ++n;
} while (++hcir != facet->facet_begin()); }
pt = ORIGIN + (p - ORIGIN)/FT(n); pt = ORIGIN + (p - ORIGIN)/FT(n);
} }
}; };
\endcode \endcode
In this example, the computation is based on the assumption that In this example, the computation is based on the assumption that
the `Point_3` is the `CGAL::Point_3`. It is an assumption, the `Point_3` is the `CGAL::Point_3`. It is an assumption,
but not a restriction. but not a restriction.
@ -454,19 +458,20 @@ is listed below, where `ept` returns the new point splitting
\code{.cpp} \code{.cpp}
void border_node(boost::graph_traits<PolygonMesh>::halfedge_descriptor edge, Point_3& ept, Point_3& vpt) { void border_node(halfedge_descriptor edge, Point& ept, Point& vpt) {
Point_3& ep1 = edge->vertex()->point(); Point& ep1 = get(vpm, target(edge, pmesh));
Point_3& ep2 = edge->opposite()->vertex()->point(); Point& ep2 = get(vpm, target(opposite(edge, pmesh), pmesh));
ept = Point_3((ep1[0]+ep2[0])/2, (ep1[1]+ep2[1])/2, (ep1[2]+ep2[2])/2); ept = Point((ep1[0]+ep2[0])/2, (ep1[1]+ep2[1])/2, (ep1[2]+ep2[2])/2);
Halfedge_around_vertex_circulator vcir = edge->vertex_begin(); Halfedge_around_target_circulator<Poly> vcir(edge, pmesh);
Point_3& vp1 = vcir->opposite()->vertex()->point(); Point& vp1 = get(vpm,target(opposite(*vcir, pmesh ), pmesh));
Point_3& vp0 = vcir->vertex()->point(); Point& vp0 = get(vpm, target(*vcir, pmesh));
Point_3& vp_1 = (--vcir)->opposite()->vertex()->point(); --vcir;
vpt = Point_3((vp_1[0] + 6*vp0[0] + vp1[0])/8, Point& vp_1 = get(vpm, target(opposite(*vcir, pmesh), pmesh));
(vp_1[1] + 6*vp0[1] + vp1[1])/8, vpt = Point((vp_1[0] + 6*vp0[0] + vp1[0])/8,
(vp_1[2] + 6*vp0[2] + vp1[2])/8 ); (vp_1[1] + 6*vp0[1] + vp1[1])/8,
} (vp_1[2] + 6*vp0[2] + vp1[2])/8 );
}
\endcode \endcode
@ -480,31 +485,31 @@ current release. This might be changed in the future releases.
template <class PolygonMesh> template <class PolygonMesh>
class PQQMask_3 { class PQQMask_3 {
void face_node(boost::graph_traits<PolygonMesh>::face_descriptor, Point_3&); void face_node(boost::graph_traits<PolygonMesh>::face_descriptor, Point&);
void edge_node(boost::graph_traits<PolygonMesh>::halfedge_descriptor, Point_3&); void edge_node(boost::graph_traits<PolygonMesh>::halfedge_descriptor, Point&);
void vertex_node(boost::graph_traits<PolygonMesh>::vertex_descriptor, Point_3&); void vertex_node(boost::graph_traits<PolygonMesh>::vertex_descriptor, Point&);
void border_node(boost::graph_traits<PolygonMesh>::halfedge_descriptor, Point_3&, Point_3&); void border_node(boost::graph_traits<PolygonMesh>::halfedge_descriptor, Point&, Point&);
}; };
template <class TriangleMesh> template <class PolygonMesh>
class PTQMask_3 { class PTQMask_3 {
void edge_node(boost::graph_traits<TriangleMesh>::halfedge_descriptor, Point_3&); void edge_node(boost::graph_traits<PolygonMesh>::halfedge_descriptor, Point&);
void vertex_node(boost::graph_traits<TriangleMesh>::vertex_descriptor, Point_3&); void vertex_node(boost::graph_traits<PolygonMesh>::vertex_descriptor, Point&);
void border_node(boost::graph_traits<TriangleMesh>::halfedge_descriptor, Point_3&, Point_&); void border_node(boost::graph_traits<PolygonMesh>::halfedge_descriptor, Point&, Point_&);
}; };
template <class PolygonMesh> template <class PolygonMesh>
class DQQMask_3 { class DQQMask_3 {
public: public:
void corner_node(boost::graph_traits<PolygonMesh>::halfedge_descriptor edge, Point_3& pt); void corner_node(boost::graph_traits<PolygonMesh>::halfedge_descriptor edge, Point& pt);
}; };
template <class TriangleMesh> template <class PolygonMesh>
class Sqrt3Mask_3 { class Sqrt3Mask_3 {
public: public:
void vertex_node(boost::graph_traits<TriangleMesh>::vertex_descriptor vertex, Point_3& pt); void vertex_node(boost::graph_traits<PolygonMesh>::vertex_descriptor vertex, Point& pt);
}; };
\endcode \endcode
@ -518,7 +523,8 @@ the best sources of learning these stencil interfaces.
`Subdivision_method_3` supports Catmull-Clark, Loop, `Subdivision_method_3` supports Catmull-Clark, Loop,
Doo-Sabin and \f$ \sqrt{3}\f$ subdivisions by specializing Doo-Sabin and \f$ \sqrt{3}\f$ subdivisions by specializing
their respective refinement hosts. their respective refinement hosts.
They are designed to work on a `Polyhedron_3`. If your application They are designed to work on any model of a `MutableFaceGraph`
such as `Polyhedron_3` and `Surface_mesh`. If your application
uses a polyhedron with a specialized geometry kernel, you need to uses a polyhedron with a specialized geometry kernel, you need to
specialize the refinement host with a geometry policy specialize the refinement host with a geometry policy
based on that kernel. based on that kernel.
@ -527,23 +533,23 @@ based on that kernel.
namespace Subdivision_method_3 { namespace Subdivision_method_3 {
template <class PolygonMesh> template <class PolygonMesh>
void CatmullClark_subdivision(PolygonMesh& p, int step = 1) { void CatmullClark_subdivision(PolygonMesh& pmesh, int step = 1) {
PQQ(p, CatmullClark_mask_3<PolygonMesh>(p), step); PQQ(pmesh, CatmullClark_mask_3<PolygonMesh>(pmesh), step);
}
template <class TriangleMesh>
void Loop_subdivision(TriangleMesh& p, int step = 1) {
PTQ(p, Loop_mask_3<TriangleMesh>(p) , step);
} }
template <class PolygonMesh> template <class PolygonMesh>
void DooSabin_subdivision(PolygonMesh& p, int step = 1) { void Loop_subdivision(PolygonMesh& pmesh, int step = 1) {
DQQ(p, DooSabin_mask_3<PolygonMesh>(p), step); PTQ(pmesh, Loop_mask_3<PolygonMesh>(pmesh) , step);
} }
template <class TriangleMesh> template <class PolygonMesh>
void Sqrt3_subdivision(TriangleMesh& p, int step = 1) { void DooSabin_subdivision(PolygonMesh& pmesh, int step = 1) {
Sqrt3(p, Sqrt3_mask_3<TriangleMesh>(p), step); DQQ(pmesh, DooSabin_mask_3<PolygonMesh>(pmesh), step);
}
template <class PolygonMesh>
void Sqrt3_subdivision(PolygonMesh& pmesh, int step = 1) {
Sqrt3(pmesh, Sqrt3_mask_3<PolygonMesh>(pmesh), step);
} }
} }

View File

@ -5,3 +5,4 @@ Algebraic_foundations
Circulator Circulator
Stream_support Stream_support
Polyhedron Polyhedron
Surface_mesh