mirror of https://github.com/CGAL/cgal
The user manual should be ok now
This commit is contained in:
parent
8af4f2b433
commit
b74b3b754e
|
|
@ -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) );
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,3 +5,4 @@ Algebraic_foundations
|
||||||
Circulator
|
Circulator
|
||||||
Stream_support
|
Stream_support
|
||||||
Polyhedron
|
Polyhedron
|
||||||
|
Surface_mesh
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue