mirror of https://github.com/CGAL/cgal
Changes after Surface_reconstruction_points_3/Point_set_processing_3 submission review by AF (12):
Moved keep_largest_connected_components() to HalfedgeDS_decorator and Polyhedron_3 classes.
This commit is contained in:
parent
4a71c24908
commit
94690fd34f
|
|
@ -3,7 +3,7 @@
|
||||||
% +------------------------------------------------------------------------+
|
% +------------------------------------------------------------------------+
|
||||||
% | 22.03.1999 Lutz Kettner
|
% | 22.03.1999 Lutz Kettner
|
||||||
% | Package: HalfedgeDS
|
% | Package: HalfedgeDS
|
||||||
% |
|
% |
|
||||||
\RCSdef{\RCSHalfedgeDSdecoratorRev}{$Id$}
|
\RCSdef{\RCSHalfedgeDSdecoratorRev}{$Id$}
|
||||||
\RCSdefDate{\RCSHalfedgeDSdecoratorDate}{$Date$}
|
\RCSdefDate{\RCSHalfedgeDSdecoratorDate}{$Date$}
|
||||||
% +------------------------------------------------------------------------+
|
% +------------------------------------------------------------------------+
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
\begin{ccRefClass}{HalfedgeDS_decorator<HDS>}
|
\begin{ccRefClass}{HalfedgeDS_decorator<HDS>}
|
||||||
|
|
||||||
\ccDefinition
|
\ccDefinition
|
||||||
|
|
||||||
The classes \ccc{CGAL::HalfedgeDS_items_decorator<HDS>},
|
The classes \ccc{CGAL::HalfedgeDS_items_decorator<HDS>},
|
||||||
\ccc{CGAL::HalfedgeDS_decorator<HDS>}, and
|
\ccc{CGAL::HalfedgeDS_decorator<HDS>}, and
|
||||||
\ccc{CGAL::HalfedgeDS_const_decorator<HDS>} provide additional functions
|
\ccc{CGAL::HalfedgeDS_const_decorator<HDS>} provide additional functions
|
||||||
|
|
@ -90,7 +90,7 @@ incidence relations except if mentioned otherwise.
|
||||||
|
|
||||||
\ccMethod{void vertices_pop_front();}{
|
\ccMethod{void vertices_pop_front();}{
|
||||||
removes the first vertex if vertices are supported.
|
removes the first vertex if vertices are supported.
|
||||||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||||
\ccc{CGAL::Tag_true}.}
|
\ccc{CGAL::Tag_true}.}
|
||||||
\ccGlue
|
\ccGlue
|
||||||
\ccMethod{void vertices_pop_back();}{
|
\ccMethod{void vertices_pop_back();}{
|
||||||
|
|
@ -98,17 +98,17 @@ incidence relations except if mentioned otherwise.
|
||||||
\ccGlue
|
\ccGlue
|
||||||
\ccMethod{void vertices_erase( Vertex_handle v);}{
|
\ccMethod{void vertices_erase( Vertex_handle v);}{
|
||||||
removes the vertex $v$ if vertices are supported.
|
removes the vertex $v$ if vertices are supported.
|
||||||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||||
\ccc{CGAL::Tag_true}.}
|
\ccc{CGAL::Tag_true}.}
|
||||||
\ccGlue
|
\ccGlue
|
||||||
\ccMethod{void vertices_erase( Vertex_handle first, Vertex_handle last);}{
|
\ccMethod{void vertices_erase( Vertex_handle first, Vertex_handle last);}{
|
||||||
removes the range $[\ccc{first},\ccc{last})$ if vertices
|
removes the range $[\ccc{first},\ccc{last})$ if vertices
|
||||||
are supported. \ccCommentHeading{Requirement} \ccc{Supports_removal}
|
are supported. \ccCommentHeading{Requirement} \ccc{Supports_removal}
|
||||||
$\equiv$ \ccc{CGAL::Tag_true}.}
|
$\equiv$ \ccc{CGAL::Tag_true}.}
|
||||||
|
|
||||||
\ccMethod{void faces_pop_front();}{
|
\ccMethod{void faces_pop_front();}{
|
||||||
removes the first face if faces are supported.
|
removes the first face if faces are supported.
|
||||||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||||
\ccc{CGAL::Tag_true}.}
|
\ccc{CGAL::Tag_true}.}
|
||||||
\ccGlue
|
\ccGlue
|
||||||
\ccMethod{void faces_pop_back();}{
|
\ccMethod{void faces_pop_back();}{
|
||||||
|
|
@ -120,7 +120,7 @@ incidence relations except if mentioned otherwise.
|
||||||
\ccc{CGAL::Tag_true}.}
|
\ccc{CGAL::Tag_true}.}
|
||||||
\ccGlue
|
\ccGlue
|
||||||
\ccMethod{void faces_erase( Face_handle first, Face_handle last);}{
|
\ccMethod{void faces_erase( Face_handle first, Face_handle last);}{
|
||||||
removes the range $[\ccc{first},\ccc{last})$ if faces are
|
removes the range $[\ccc{first},\ccc{last})$ if faces are
|
||||||
supported. \ccCommentHeading{Requirement} \ccc{Supports_removal}
|
supported. \ccCommentHeading{Requirement} \ccc{Supports_removal}
|
||||||
$\equiv$ \ccc{CGAL::Tag_true}.}
|
$\equiv$ \ccc{CGAL::Tag_true}.}
|
||||||
|
|
||||||
|
|
@ -129,18 +129,24 @@ incidence relations except if mentioned otherwise.
|
||||||
incident to the face into border edges or removes them from the
|
incident to the face into border edges or removes them from the
|
||||||
halfedge data structure if they were already border edges. If this
|
halfedge data structure if they were already border edges. If this
|
||||||
creates isolated vertices they get removed as well. See
|
creates isolated vertices they get removed as well. See
|
||||||
\ccc{make_hole(h)} for a more specialized variant.
|
\ccc{make_hole(h)} for a more specialized variant.
|
||||||
\ccPrecond \ccc{h->is_border() == false}.
|
\ccPrecond \ccc{h->is_border() == false}.
|
||||||
\ccCommentHeading{Requirement} If faces are supported,
|
\ccCommentHeading{Requirement} If faces are supported,
|
||||||
\ccc{Supports_removal} $\equiv$ \ccc{CGAL::Tag_true}.}
|
\ccc{Supports_removal} $\equiv$ \ccc{CGAL::Tag_true}.}
|
||||||
|
|
||||||
\ccMethod{void erase_connected_component( Halfedge_handle h);}
|
\ccMethod{void erase_connected_component( Halfedge_handle h);}
|
||||||
{removes the vertices, halfedges, and faces that belong to the
|
{removes the vertices, halfedges, and faces that belong to the
|
||||||
connected component of $h$. \ccPrecond For all halfedges $g$ in the
|
connected component of $h$. \ccPrecond For all halfedges $g$ in the
|
||||||
connected component \ccc{g.next() != Halfedge_handle()}.
|
connected component \ccc{g.next() != Halfedge_handle()}.
|
||||||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||||
\ccc{CGAL::Tag_true}.}
|
\ccc{CGAL::Tag_true}.}
|
||||||
|
|
||||||
|
\ccMethod{unsigned int keep_largest_connected_components(unsigned int nb_components_to_keep);}
|
||||||
|
{Erases the small connected components and the isolated vertices.
|
||||||
|
Keep \ccc{nb_components_to_keep} largest connected components.
|
||||||
|
Returns the number of connected components erased (ignoring isolated vertices).
|
||||||
|
\ccCommentHeading{Requirement} supports vertices, halfedges, and removal operation.}
|
||||||
|
|
||||||
% -----------------------------------------
|
% -----------------------------------------
|
||||||
\ccHeading{Modifying Functions (For Border Halfedges)}
|
\ccHeading{Modifying Functions (For Border Halfedges)}
|
||||||
|
|
||||||
|
|
@ -148,8 +154,8 @@ incidence relations except if mentioned otherwise.
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle make_hole( Halfedge_handle h);}
|
\ccMethod{Halfedge_handle make_hole( Halfedge_handle h);}
|
||||||
{removes the face incident to \ccc{h} from \ccc{hds} and creates a hole.
|
{removes the face incident to \ccc{h} from \ccc{hds} and creates a hole.
|
||||||
\ccPrecond \ccc{h != Halfedge_handle()} and \ccc{!(h->is_border())}.
|
\ccPrecond \ccc{h != Halfedge_handle()} and \ccc{!(h->is_border())}.
|
||||||
\ccCommentHeading{Requirement} If faces are supported,
|
\ccCommentHeading{Requirement} If faces are supported,
|
||||||
\ccc{Supports_removal} $\equiv$ \ccc{CGAL::Tag_true}.}
|
\ccc{Supports_removal} $\equiv$ \ccc{CGAL::Tag_true}.}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle fill_hole( Halfedge_handle h);}
|
\ccMethod{Halfedge_handle fill_hole( Halfedge_handle h);}
|
||||||
|
|
@ -162,27 +168,27 @@ incidence relations except if mentioned otherwise.
|
||||||
Returns \ccc{h}.
|
Returns \ccc{h}.
|
||||||
\ccPrecond \ccc{h != Halfedge_handle()} and \ccc{h->is_border()}.}
|
\ccPrecond \ccc{h != Halfedge_handle()} and \ccc{h->is_border()}.}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle add_face_to_border( Halfedge_handle h,
|
\ccMethod{Halfedge_handle add_face_to_border( Halfedge_handle h,
|
||||||
Halfedge_handle g);}
|
Halfedge_handle g);}
|
||||||
{extends the surface with a new face from \ccc{hds} into the hole
|
{extends the surface with a new face from \ccc{hds} into the hole
|
||||||
incident to $h$ and $g$. It creates a new edge connecting the vertex
|
incident to $h$ and $g$. It creates a new edge connecting the vertex
|
||||||
denoted by $g$ with the vertex denoted by $h$ and fills this separated
|
denoted by $g$ with the vertex denoted by $h$ and fills this separated
|
||||||
part of the hole with a new face, such that the new face is incident
|
part of the hole with a new face, such that the new face is incident
|
||||||
to $g$. Returns the new halfedge that is incident to the new face.
|
to $g$. Returns the new halfedge that is incident to the new face.
|
||||||
\ccPrecond \ccc{h != Halfedge_handle()}, \ccc{g != Halfedge_handle()},
|
\ccPrecond \ccc{h != Halfedge_handle()}, \ccc{g != Halfedge_handle()},
|
||||||
\ccc{h->is_border()}, \ccc{g->is_border()} and $g$ can be reached
|
\ccc{h->is_border()}, \ccc{g->is_border()} and $g$ can be reached
|
||||||
along the hole starting with $h$.}
|
along the hole starting with $h$.}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle add_face_to_border( Halfedge_handle h,
|
\ccMethod{Halfedge_handle add_face_to_border( Halfedge_handle h,
|
||||||
Halfedge_handle g,
|
Halfedge_handle g,
|
||||||
const Face& f);}
|
const Face& f);}
|
||||||
{extends the surface with a copy of face $f$ into the hole
|
{extends the surface with a copy of face $f$ into the hole
|
||||||
incident to $h$ and $g$. It creates a new edge connecting the tip of
|
incident to $h$ and $g$. It creates a new edge connecting the tip of
|
||||||
$g$ with the tip of $h$ and fills this separated part of the hole with a
|
$g$ with the tip of $h$ and fills this separated part of the hole with a
|
||||||
copy of face $f$, such that the new face is incident to $g$. Returns
|
copy of face $f$, such that the new face is incident to $g$. Returns
|
||||||
the new halfedge that is incident to the new face.
|
the new halfedge that is incident to the new face.
|
||||||
\ccPrecond \ccc{h != Halfedge_handle()}, \ccc{g != Halfedge_handle()},
|
\ccPrecond \ccc{h != Halfedge_handle()}, \ccc{g != Halfedge_handle()},
|
||||||
\ccc{h->is_border()}, \ccc{g->is_border()} and $g$ can be reached
|
\ccc{h->is_border()}, \ccc{g->is_border()} and $g$ can be reached
|
||||||
along the hole starting with $h$.}
|
along the hole starting with $h$.}
|
||||||
|
|
||||||
% -----------------------------------------
|
% -----------------------------------------
|
||||||
|
|
@ -192,14 +198,14 @@ incidence relations except if mentioned otherwise.
|
||||||
|
|
||||||
The following Euler operations modify consistently the combinatorial
|
The following Euler operations modify consistently the combinatorial
|
||||||
structure of the halfedge data structure. The geometry remains unchanged.
|
structure of the halfedge data structure. The geometry remains unchanged.
|
||||||
Note that well known graph operations are also captured with these
|
Note that well known graph operations are also captured with these
|
||||||
Euler operators, for example an edge contraction is equal to a
|
Euler operators, for example an edge contraction is equal to a
|
||||||
\ccc{join_vertex()} operation, or an edge removal to \ccc{join_face()}.
|
\ccc{join_vertex()} operation, or an edge removal to \ccc{join_face()}.
|
||||||
|
|
||||||
Given a halfedge data structure \ccc{hds} and a halfedge handle $h$
|
Given a halfedge data structure \ccc{hds} and a halfedge handle $h$
|
||||||
four special applications of the Euler operators are worth mentioning:
|
four special applications of the Euler operators are worth mentioning:
|
||||||
\ccc{split_vertex(h,h)} results in an antenna emanating from the tip
|
\ccc{split_vertex(h,h)} results in an antenna emanating from the tip
|
||||||
of \ccc{h}; \ccc{split_vertex(h,h->next()->opposite())} results in an edge
|
of \ccc{h}; \ccc{split_vertex(h,h->next()->opposite())} results in an edge
|
||||||
split of the halfedge \ccc{h->next} with a new vertex in-between;
|
split of the halfedge \ccc{h->next} with a new vertex in-between;
|
||||||
\ccc{split_face(h,h)} results in a loop directly following \ccc{h};
|
\ccc{split_face(h,h)} results in a loop directly following \ccc{h};
|
||||||
and \ccc{split_face(h,h->next())} results in a bridge parallel to
|
and \ccc{split_face(h,h->next())} results in a bridge parallel to
|
||||||
|
|
@ -224,9 +230,9 @@ the halfedge \ccc{h->next} with a new face in-between.
|
||||||
with a new diagonal between the two vertices denoted by \ccc{h} and
|
with a new diagonal between the two vertices denoted by \ccc{h} and
|
||||||
\ccc{g} respectively. The second (new) face obtained from
|
\ccc{g} respectively. The second (new) face obtained from
|
||||||
\ccc{hds} is a copy of the first face. Returns \ccc{h->next()} after the
|
\ccc{hds} is a copy of the first face. Returns \ccc{h->next()} after the
|
||||||
operation, i.e., the new diagonal. The new face is to the right of the
|
operation, i.e., the new diagonal. The new face is to the right of the
|
||||||
new diagonal, the old face is to the left. The time is proportional
|
new diagonal, the old face is to the left. The time is proportional
|
||||||
to the distance from \ccc{h} to \ccc{g} around the face.}
|
to the distance from \ccc{h} to \ccc{g} around the face.}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle join_face( Halfedge_handle h);}
|
\ccMethod{Halfedge_handle join_face( Halfedge_handle h);}
|
||||||
{joins the two faces incident to $h$. The face incident to
|
{joins the two faces incident to $h$. The face incident to
|
||||||
|
|
@ -250,16 +256,16 @@ the halfedge \ccc{h->next} with a new face in-between.
|
||||||
and connects them with a new edge. The second (new) vertex
|
and connects them with a new edge. The second (new) vertex
|
||||||
obtained from \ccc{hds} is a copy of the first vertex. Returns
|
obtained from \ccc{hds} is a copy of the first vertex. Returns
|
||||||
\ccc{h->next()->opposite()} after the operation, i.e., the new edge
|
\ccc{h->next()->opposite()} after the operation, i.e., the new edge
|
||||||
in the orientation towards the new vertex. The time is proportional
|
in the orientation towards the new vertex. The time is proportional
|
||||||
to the distance from \ccc{h} to \ccc{g} around the vertex.}
|
to the distance from \ccc{h} to \ccc{g} around the vertex.}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle join_vertex( Halfedge_handle h);}
|
\ccMethod{Halfedge_handle join_vertex( Halfedge_handle h);}
|
||||||
{joins the two vertices incident to $h$. The vertex denoted by
|
{joins the two vertices incident to $h$. The vertex denoted by
|
||||||
\ccc{h->opposite()} gets removed by \ccc{hds}. Returns the predecessor of
|
\ccc{h->opposite()} gets removed by \ccc{hds}. Returns the predecessor of
|
||||||
$h$ around the vertex, i.e., \ccc{h->opposite()->prev()}. The invariant
|
$h$ around the vertex, i.e., \ccc{h->opposite()->prev()}. The invariant
|
||||||
\ccc{join_vertex( split_vertex( h, g))} returns $h$
|
\ccc{join_vertex( split_vertex( h, g))} returns $h$
|
||||||
and keeps the polyhedron unchanged.
|
and keeps the polyhedron unchanged.
|
||||||
The time is proportional to the degree of the vertex removed and
|
The time is proportional to the degree of the vertex removed and
|
||||||
the time to compute \ccc{h->prev()} and \ccc{h->opposite()->prev()}.
|
the time to compute \ccc{h->prev()} and \ccc{h->opposite()->prev()}.
|
||||||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||||
\ccc{CGAL::Tag_true}.}
|
\ccc{CGAL::Tag_true}.}
|
||||||
|
|
@ -281,30 +287,30 @@ the halfedge \ccc{h->next} with a new face in-between.
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle create_center_vertex( Halfedge_handle h);}
|
\ccMethod{Halfedge_handle create_center_vertex( Halfedge_handle h);}
|
||||||
{barycentric triangulation of \ccc{h->face()}. Creates a new vertex,
|
{barycentric triangulation of \ccc{h->face()}. Creates a new vertex,
|
||||||
a copy of \ccc{h->vertex()}, and connects it to each vertex incident
|
a copy of \ccc{h->vertex()}, and connects it to each vertex incident
|
||||||
to \ccc{h->face()} splitting \ccc{h->face()} into triangles.
|
to \ccc{h->face()} splitting \ccc{h->face()} into triangles.
|
||||||
\ccc{h} remains incident to the original face, all other triangles
|
\ccc{h} remains incident to the original face, all other triangles
|
||||||
are copies of this face. Returns the halfedge \ccc{h->next()}
|
are copies of this face. Returns the halfedge \ccc{h->next()}
|
||||||
after the operation, i.e., a halfedge pointing to the new vertex.
|
after the operation, i.e., a halfedge pointing to the new vertex.
|
||||||
The time is proportional to the size of the face.
|
The time is proportional to the size of the face.
|
||||||
\ccPrecond \ccc{h} is not a border halfedge.}
|
\ccPrecond \ccc{h} is not a border halfedge.}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle erase_center_vertex( Halfedge_handle g);}
|
\ccMethod{Halfedge_handle erase_center_vertex( Halfedge_handle g);}
|
||||||
{reverses \ccc{create_center_vertex}. Erases the
|
{reverses \ccc{create_center_vertex}. Erases the
|
||||||
vertex pointed to by \ccc{g} and all incident halfedges thereby
|
vertex pointed to by \ccc{g} and all incident halfedges thereby
|
||||||
merging all incident faces. Only \ccc{g->face()} remains.
|
merging all incident faces. Only \ccc{g->face()} remains.
|
||||||
The neighborhood of \ccc{g->vertex()} may not be triangulated,
|
The neighborhood of \ccc{g->vertex()} may not be triangulated,
|
||||||
it can have larger faces. Returns the halfedge \ccc{g->prev()}.
|
it can have larger faces. Returns the halfedge \ccc{g->prev()}.
|
||||||
Thus, the invariant \ccc{h == erase_center_vertex(
|
Thus, the invariant \ccc{h == erase_center_vertex(
|
||||||
create_center_vertex(h))} holds if \ccc{h} is not a border halfedge.
|
create_center_vertex(h))} holds if \ccc{h} is not a border halfedge.
|
||||||
The time is proportional to the sum of the size of all incident faces.
|
The time is proportional to the sum of the size of all incident faces.
|
||||||
\ccPrecond None of the incident faces of \ccc{g->vertex()} is
|
\ccPrecond None of the incident faces of \ccc{g->vertex()} is
|
||||||
a hole. There are at least two distinct faces incident
|
a hole. There are at least two distinct faces incident
|
||||||
to the faces that are incident to \ccc{g->vertex()}. (This
|
to the faces that are incident to \ccc{g->vertex()}. (This
|
||||||
prevents the operation from collapsing a volume into two faces
|
prevents the operation from collapsing a volume into two faces
|
||||||
glued together with opposite orientations, such as would
|
glued together with opposite orientations, such as would
|
||||||
happen with any vertex of a tetrahedron.)
|
happen with any vertex of a tetrahedron.)
|
||||||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||||
\ccc{CGAL::Tag_true}.}
|
\ccc{CGAL::Tag_true}.}
|
||||||
|
|
||||||
\newpage
|
\newpage
|
||||||
|
|
@ -324,14 +330,14 @@ the halfedge \ccc{h->next} with a new face in-between.
|
||||||
</CENTER>
|
</CENTER>
|
||||||
\end{ccHtmlOnly}
|
\end{ccHtmlOnly}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle split_loop( Halfedge_handle h,
|
\ccMethod{Halfedge_handle split_loop( Halfedge_handle h,
|
||||||
Halfedge_handle i,
|
Halfedge_handle i,
|
||||||
Halfedge_handle j);}
|
Halfedge_handle j);}
|
||||||
{cuts the halfedge data structure into two parts along the cycle $(h,i,j)$.
|
{cuts the halfedge data structure into two parts along the cycle $(h,i,j)$.
|
||||||
Three new vertices (one copy for each vertex in the cycle) and three
|
Three new vertices (one copy for each vertex in the cycle) and three
|
||||||
new halfedges (one copy for each halfedge in the cycle), and two new
|
new halfedges (one copy for each halfedge in the cycle), and two new
|
||||||
triangles are created. $h,i,j$ will be incident to the first new triangle.
|
triangles are created. $h,i,j$ will be incident to the first new triangle.
|
||||||
The return value will be the halfedge incident to the second new triangle
|
The return value will be the halfedge incident to the second new triangle
|
||||||
which is the copy of \ccc{h-opposite()}.
|
which is the copy of \ccc{h-opposite()}.
|
||||||
\ccPrecond $h,i,j$ denote distinct, consecutive vertices of the
|
\ccPrecond $h,i,j$ denote distinct, consecutive vertices of the
|
||||||
halfedge data structure and form a cycle: i.e., \ccc{h->vertex() ==
|
halfedge data structure and form a cycle: i.e., \ccc{h->vertex() ==
|
||||||
|
|
@ -339,22 +345,22 @@ the halfedge \ccc{h->next} with a new face in-between.
|
||||||
h->opposite()->vertex()}.}
|
h->opposite()->vertex()}.}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle join_loop( Halfedge_handle h, Halfedge_handle g);}
|
\ccMethod{Halfedge_handle join_loop( Halfedge_handle h, Halfedge_handle g);}
|
||||||
{glues the boundary of the two faces denoted by $h$ and $g$ together
|
{glues the boundary of the two faces denoted by $h$ and $g$ together
|
||||||
and returns $h$. Both faces and the vertices along the face denoted
|
and returns $h$. Both faces and the vertices along the face denoted
|
||||||
by $g$ gets removed. Both faces may be holes. The invariant
|
by $g$ gets removed. Both faces may be holes. The invariant
|
||||||
\ccc{join_loop( h, split_loop( h, i, j))} returns $h$ and keeps the
|
\ccc{join_loop( h, split_loop( h, i, j))} returns $h$ and keeps the
|
||||||
data structure unchanged.
|
data structure unchanged.
|
||||||
\ccPrecond The faces denoted by $h$ and $g$ are different and have
|
\ccPrecond The faces denoted by $h$ and $g$ are different and have
|
||||||
equal degree (i.e., number of edges).
|
equal degree (i.e., number of edges).
|
||||||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||||
\ccc{CGAL::Tag_true}.}
|
\ccc{CGAL::Tag_true}.}
|
||||||
|
|
||||||
|
|
||||||
% -----------------------------------------
|
% -----------------------------------------
|
||||||
\ccHeading{Validness Checks}
|
\ccHeading{Validness Checks}
|
||||||
\ccThree{Halfe}{dge_handlehds.split_f}{}
|
\ccThree{Halfe}{dge_handlehds.split_f}{}
|
||||||
|
|
||||||
These operations are the same as for
|
These operations are the same as for
|
||||||
\ccc{CGAL::HalfedgeDS_const_decorator<HDS>}.
|
\ccc{CGAL::HalfedgeDS_const_decorator<HDS>}.
|
||||||
\begin{ccTexOnly}
|
\begin{ccTexOnly}
|
||||||
See their documentation on page~\pageref{pageHalfedgeDSconstDecoratorRef}.
|
See their documentation on page~\pageref{pageHalfedgeDSconstDecoratorRef}.
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
//
|
//
|
||||||
// $URL$
|
// $URL$
|
||||||
// $Id$
|
// $Id$
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Author(s) : Lutz Kettner <kettner@mpi-sb.mpg.de>
|
// Author(s) : Lutz Kettner <kettner@mpi-sb.mpg.de>
|
||||||
|
|
||||||
|
|
@ -26,9 +26,13 @@
|
||||||
|
|
||||||
#include <CGAL/HalfedgeDS_items_decorator.h>
|
#include <CGAL/HalfedgeDS_items_decorator.h>
|
||||||
#include <CGAL/HalfedgeDS_const_decorator.h>
|
#include <CGAL/HalfedgeDS_const_decorator.h>
|
||||||
#include <vector>
|
#include <CGAL/HalfedgeDS_iterator.h>
|
||||||
#include <CGAL/IO/Verbose_ostream.h>
|
#include <CGAL/IO/Verbose_ostream.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
CGAL_BEGIN_NAMESPACE
|
CGAL_BEGIN_NAMESPACE
|
||||||
|
|
||||||
template < class p_HDS >
|
template < class p_HDS >
|
||||||
|
|
@ -761,6 +765,53 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Erases the small connected components and the isolated vertices.
|
||||||
|
///
|
||||||
|
/// @commentheading Preconditions:
|
||||||
|
/// supports vertices, halfedges, and removal operation.
|
||||||
|
///
|
||||||
|
/// @commentheading Template Parameters:
|
||||||
|
/// @param nb_components_to_keep the number of large connected components to keep.
|
||||||
|
///
|
||||||
|
/// @return the number of connected components erased (ignoring isolated vertices).
|
||||||
|
unsigned int keep_largest_connected_components(unsigned int nb_components_to_keep)
|
||||||
|
{
|
||||||
|
Assert_compile_time_tag(Supports_removal(), Tag_true());
|
||||||
|
Assert_compile_time_tag(Supports_vertex_halfedge(), Tag_true());
|
||||||
|
|
||||||
|
unsigned int nb_erased_components = 0,
|
||||||
|
nb_isolated_vertices = 0;
|
||||||
|
|
||||||
|
// Gets list of connected components, ordered by size (i.e. number of vertices)
|
||||||
|
std::vector<Vertex_handle> components;
|
||||||
|
get_connected_components(std::back_inserter(components));
|
||||||
|
|
||||||
|
// Erases all connected components but the largest
|
||||||
|
while (components.size() > nb_components_to_keep)
|
||||||
|
{
|
||||||
|
Vertex_handle vertex = *(components.begin());
|
||||||
|
|
||||||
|
// Removes component from list
|
||||||
|
components.erase(components.begin());
|
||||||
|
|
||||||
|
if (vertex->halfedge() != NULL) // if not isolated vertex
|
||||||
|
{
|
||||||
|
erase_connected_component(vertex->halfedge());
|
||||||
|
nb_erased_components++;
|
||||||
|
}
|
||||||
|
else // if isolated vertex
|
||||||
|
{
|
||||||
|
vertices_erase(vertex);
|
||||||
|
nb_isolated_vertices++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (nb_isolated_vertices > 0)
|
||||||
|
// std::cerr << " Erased " << nb_isolated_vertices << " isolated vertices\n";
|
||||||
|
|
||||||
|
return nb_erased_components;
|
||||||
|
}
|
||||||
|
|
||||||
// Implementing These Functions.
|
// Implementing These Functions.
|
||||||
// ====================================================
|
// ====================================================
|
||||||
// Creation of New Elements
|
// Creation of New Elements
|
||||||
|
|
@ -829,6 +880,123 @@ private:
|
||||||
hds->faces_pop_back();
|
hds->faces_pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper type for keep_largest_connected_components():
|
||||||
|
///
|
||||||
|
/// Possible values of a vertex tag.
|
||||||
|
enum { tag_free, tag_done };
|
||||||
|
|
||||||
|
/// Helper method for keep_largest_connected_components():
|
||||||
|
///
|
||||||
|
/// Gets any vertex with tag == tag_free.
|
||||||
|
///
|
||||||
|
/// @return a list of pairs (component's size (number of vertices), a vertex of the component),
|
||||||
|
/// ordered by size.
|
||||||
|
Vertex_handle get_any_free_vertex(
|
||||||
|
/*const*/ std::map<Vertex*, int>& tags) ///< container holding the tag of all vertices
|
||||||
|
{
|
||||||
|
for (Vertex_iterator it = hds->vertices_begin(); it != hds->vertices_end(); it++)
|
||||||
|
{
|
||||||
|
if (tags[&*it] == tag_free)
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper method for keep_largest_connected_components():
|
||||||
|
///
|
||||||
|
/// Tag a "free" connected component as "done".
|
||||||
|
///
|
||||||
|
/// @return the size (number of vertices) of the component.
|
||||||
|
unsigned int tag_component(
|
||||||
|
Vertex_handle pSeedVertex, ///< one vertex of the connected component
|
||||||
|
std::map<Vertex*, int>& tags) ///< container holding the tag of all vertices
|
||||||
|
{
|
||||||
|
// Circulator category.
|
||||||
|
typedef typename Halfedge::Supports_halfedge_prev Supports_prev;
|
||||||
|
typedef HalfedgeDS_circulator_traits<Supports_prev> Ctr;
|
||||||
|
typedef typename Ctr::iterator_category circulator_category;
|
||||||
|
|
||||||
|
// Circulator around a vertex
|
||||||
|
typedef I_HalfedgeDS_vertex_circ< Halfedge_handle, circulator_category>
|
||||||
|
Halfedge_around_vertex_circulator;
|
||||||
|
|
||||||
|
unsigned int number_of_vertices = 0; // size (number of vertices) of the component
|
||||||
|
|
||||||
|
std::list<Vertex_handle> vertices;
|
||||||
|
vertices.push_front(pSeedVertex);
|
||||||
|
while (!vertices.empty())
|
||||||
|
{
|
||||||
|
Vertex_handle pVertex = vertices.front();
|
||||||
|
vertices.pop_front();
|
||||||
|
|
||||||
|
// Skip vertex if already done
|
||||||
|
if (tags[&*pVertex] == tag_done)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Mark vertex done
|
||||||
|
tags[&*pVertex] = tag_done;
|
||||||
|
number_of_vertices++;
|
||||||
|
|
||||||
|
// Add vertex's "free" neighbors to the list
|
||||||
|
Halfedge_around_vertex_circulator neighbor_cir, neighbor_end;
|
||||||
|
neighbor_cir = pVertex->vertex_begin();
|
||||||
|
neighbor_end = neighbor_cir;
|
||||||
|
CGAL_For_all(neighbor_cir,neighbor_end)
|
||||||
|
{
|
||||||
|
Vertex_handle neighbor = neighbor_cir->opposite()->vertex();
|
||||||
|
if (tags[&*neighbor] == tag_free)
|
||||||
|
vertices.push_front(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return number_of_vertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper method for keep_largest_connected_components():
|
||||||
|
///
|
||||||
|
/// Computes the list of all connected components of the polyhedron.
|
||||||
|
/// Returns it as a list of components ordered by size.
|
||||||
|
///
|
||||||
|
/// @commentheading Template Parameters:
|
||||||
|
/// @param OutputIterator value_type must be Vertex_handle.
|
||||||
|
template<typename OutputIterator>
|
||||||
|
void get_connected_components(
|
||||||
|
OutputIterator output) ///< output iterator over vertex handles
|
||||||
|
{
|
||||||
|
// Implementation note:
|
||||||
|
// We tag vertices instead of halfedges to save a factor 6.
|
||||||
|
// The drawback is that we require the Polyhedron_3<Traits> to support vertices.
|
||||||
|
// TODO: replace std::map by a property map to tag vertices.
|
||||||
|
Assert_compile_time_tag(Supports_halfedge_vertex(), Tag_true());
|
||||||
|
std::map<Vertex*, int> tags;
|
||||||
|
|
||||||
|
// list of all connected components of a polyhedron, ordered by size.
|
||||||
|
std::multimap<unsigned int, Vertex_handle> components;
|
||||||
|
|
||||||
|
// Tag all mesh vertices as "free".
|
||||||
|
for (Vertex_iterator it = hds->vertices_begin(); it != hds->vertices_end(); it++)
|
||||||
|
{
|
||||||
|
tags[&*it] = tag_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record each component
|
||||||
|
Vertex_handle seed_vertex = NULL;
|
||||||
|
while((seed_vertex = get_any_free_vertex(tags)) != NULL)
|
||||||
|
{
|
||||||
|
// Tag it as "done" and compute its size (number of vertices)
|
||||||
|
unsigned int number_of_vertices = tag_component(seed_vertex, tags);
|
||||||
|
|
||||||
|
// Add component to ordered list
|
||||||
|
components.insert(std::make_pair(number_of_vertices, seed_vertex));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy ordered list to output iterator
|
||||||
|
typename std::multimap<unsigned int, Vertex_handle>::iterator src;
|
||||||
|
for (src = components.begin(); src != components.end(); ++src)
|
||||||
|
*output++ = src->second;
|
||||||
|
}
|
||||||
|
|
||||||
// Others
|
// Others
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
% +------------------------------------------------------------------------+
|
% +------------------------------------------------------------------------+
|
||||||
% | 17.03.1999 Lutz Kettner
|
% | 17.03.1999 Lutz Kettner
|
||||||
% | Package: Polyhedron
|
% | Package: Polyhedron
|
||||||
% |
|
% |
|
||||||
\RCSdef{\RCSPolyhedronRev}{$Id$}
|
\RCSdef{\RCSPolyhedronRev}{$Id$}
|
||||||
\RCSdefDate{\RCSPolyhedronDate}{$Date$}
|
\RCSdefDate{\RCSPolyhedronDate}{$Date$}
|
||||||
% +------------------------------------------------------------------------+
|
% +------------------------------------------------------------------------+
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
\begin{ccRefClass}{Polyhedron_3<Traits>}
|
\begin{ccRefClass}{Polyhedron_3<Traits>}
|
||||||
|
|
||||||
\ccDefinition
|
\ccDefinition
|
||||||
|
|
||||||
A polyhedral surface \ccClassTemplateName\ consists of vertices $V$,
|
A polyhedral surface \ccClassTemplateName\ consists of vertices $V$,
|
||||||
edges $E$, facets $F$ and an incidence relation on them. Each edge is
|
edges $E$, facets $F$ and an incidence relation on them. Each edge is
|
||||||
represented by two halfedges with opposite orientations.
|
represented by two halfedges with opposite orientations.
|
||||||
|
|
@ -105,7 +105,7 @@ template parameters:
|
||||||
\>\ccc{class Alloc = CGAL_ALLOCATOR(int)>}\\
|
\>\ccc{class Alloc = CGAL_ALLOCATOR(int)>}\\
|
||||||
\ccc{class Polyhedron_3;}
|
\ccc{class Polyhedron_3;}
|
||||||
\end{tabbing}
|
\end{tabbing}
|
||||||
|
|
||||||
The first parameter requires a model of the \ccc{PolyhedronTraits_3}
|
The first parameter requires a model of the \ccc{PolyhedronTraits_3}
|
||||||
concept as argument, for example \ccc{CGAL::Polyhedron_traits_3}. The
|
concept as argument, for example \ccc{CGAL::Polyhedron_traits_3}. The
|
||||||
second parameter expects a model of the \ccc{PolyhedronItems_3}
|
second parameter expects a model of the \ccc{PolyhedronItems_3}
|
||||||
|
|
@ -114,7 +114,7 @@ preselected. The third parameter is a class template. A model of the
|
||||||
\ccc{HalfedgeDS} concept is expected. By default, the class
|
\ccc{HalfedgeDS} concept is expected. By default, the class
|
||||||
\ccc{CGAL::HalfedgeDS_default} is preselected, which is a list based
|
\ccc{CGAL::HalfedgeDS_default} is preselected, which is a list based
|
||||||
implementation of the halfedge data structure.
|
implementation of the halfedge data structure.
|
||||||
The fourth parameter \ccc{Alloc} requires a standard allocator for
|
The fourth parameter \ccc{Alloc} requires a standard allocator for
|
||||||
\stl\ container classes. The \ccc{rebind} mechanism from \ccc{Alloc}
|
\stl\ container classes. The \ccc{rebind} mechanism from \ccc{Alloc}
|
||||||
will be used to create appropriate allocators internally. A default is
|
will be used to create appropriate allocators internally. A default is
|
||||||
provided with the macro \ccc{CGAL_ALLOCATOR(int)} from the
|
provided with the macro \ccc{CGAL_ALLOCATOR(int)} from the
|
||||||
|
|
@ -163,11 +163,11 @@ assignable to their non-mutable counterparts. Both circulators are
|
||||||
assignable to the \ccc{Halfedge_iterator}. The iterators are
|
assignable to the \ccc{Halfedge_iterator}. The iterators are
|
||||||
assignable to the respective handle types. Wherever the handles appear
|
assignable to the respective handle types. Wherever the handles appear
|
||||||
in function parameter lists, the corresponding iterators can be used as
|
in function parameter lists, the corresponding iterators can be used as
|
||||||
well. For convenience, the \ccc{Edge_iterator} enumerates every other
|
well. For convenience, the \ccc{Edge_iterator} enumerates every other
|
||||||
halfedge. It is based on the \ccc{CGAL::N_step_adaptor} class. For
|
halfedge. It is based on the \ccc{CGAL::N_step_adaptor} class. For
|
||||||
convenience, the \ccc{Point_iterator} enumerates all points in the polyhedral
|
convenience, the \ccc{Point_iterator} enumerates all points in the polyhedral
|
||||||
surface in the same order as the \ccc{Vertex_iterator}, but with the
|
surface in the same order as the \ccc{Vertex_iterator}, but with the
|
||||||
value type \ccc{Point}. It is based on the \ccc{CGAL::Iterator_project}
|
value type \ccc{Point}. It is based on the \ccc{CGAL::Iterator_project}
|
||||||
adaptor. Similarly, a \ccc{Plane_iterator} is provided.
|
adaptor. Similarly, a \ccc{Plane_iterator} is provided.
|
||||||
|
|
||||||
\ccNestedType{Vertex_handle}{handle to vertex.}
|
\ccNestedType{Vertex_handle}{handle to vertex.}
|
||||||
|
|
@ -249,12 +249,12 @@ supported or not.
|
||||||
\ccc{capacity} changes all iterators and circulators
|
\ccc{capacity} changes all iterators and circulators
|
||||||
might invalidate.}
|
might invalidate.}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle make_tetrahedron();}{a tetrahedron is added to the
|
\ccMethod{Halfedge_handle make_tetrahedron();}{a tetrahedron is added to the
|
||||||
polyhedral surface. Returns a halfedge of the tetrahedron.}
|
polyhedral surface. Returns a halfedge of the tetrahedron.}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle make_tetrahedron(const Point& p1,
|
\ccMethod{Halfedge_handle make_tetrahedron(const Point& p1,
|
||||||
const Point& p2,
|
const Point& p2,
|
||||||
const Point& p3,
|
const Point& p3,
|
||||||
const Point& p4);}{
|
const Point& p4);}{
|
||||||
a tetrahedron is added to the polyhedral surface with its
|
a tetrahedron is added to the polyhedral surface with its
|
||||||
vertices initialized to $p_1, p_2, p_3$, and $p_4$. Returns that
|
vertices initialized to $p_1, p_2, p_3$, and $p_4$. Returns that
|
||||||
|
|
@ -269,7 +269,7 @@ supported or not.
|
||||||
halfedge of the triangle.}
|
halfedge of the triangle.}
|
||||||
\vspace{-3mm}
|
\vspace{-3mm}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle make_triangle(const Point& p1,
|
\ccMethod{Halfedge_handle make_triangle(const Point& p1,
|
||||||
const Point& p2,
|
const Point& p2,
|
||||||
const Point& p3);}{
|
const Point& p3);}{
|
||||||
a triangle with border edges is added to the polyhedral surface with its
|
a triangle with border edges is added to the polyhedral surface with its
|
||||||
|
|
@ -356,7 +356,7 @@ supported or not.
|
||||||
\ccMethod{bool is_pure_triangle() const;}{returns \ccc{true} if all
|
\ccMethod{bool is_pure_triangle() const;}{returns \ccc{true} if all
|
||||||
facets are triangles.}
|
facets are triangles.}
|
||||||
|
|
||||||
\ccMethod{bool is_pure_quad() const;}{returns \ccc{true} if all
|
\ccMethod{bool is_pure_quad() const;}{returns \ccc{true} if all
|
||||||
facets are quadrilaterals.}
|
facets are quadrilaterals.}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -403,7 +403,7 @@ unchanged.
|
||||||
with a new diagonal between the two vertices denoted by \ccc{h} and
|
with a new diagonal between the two vertices denoted by \ccc{h} and
|
||||||
\ccc{g} respectively. The second (new) facet is a copy of the
|
\ccc{g} respectively. The second (new) facet is a copy of the
|
||||||
first facet. Returns \ccc{h->next()} after the
|
first facet. Returns \ccc{h->next()} after the
|
||||||
operation, i.e., the new diagonal. The new face is to the right of the
|
operation, i.e., the new diagonal. The new face is to the right of the
|
||||||
new diagonal, the old face is to the left. The time is
|
new diagonal, the old face is to the left. The time is
|
||||||
proportional to the distance from \ccc{h} to \ccc{g} around the facet.
|
proportional to the distance from \ccc{h} to \ccc{g} around the facet.
|
||||||
\ccPrecond \ccc{h} and \ccc{g} are incident to the same facet.
|
\ccPrecond \ccc{h} and \ccc{g} are incident to the same facet.
|
||||||
|
|
@ -419,7 +419,7 @@ unchanged.
|
||||||
facet removed and the time to compute \ccc{h->prev()}.
|
facet removed and the time to compute \ccc{h->prev()}.
|
||||||
\ccPrecond The degree of both vertices incident to $h$ is at least
|
\ccPrecond The degree of both vertices incident to $h$ is at least
|
||||||
three (no antennas).
|
three (no antennas).
|
||||||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||||
\ccc{CGAL::Tag_true}.}
|
\ccc{CGAL::Tag_true}.}
|
||||||
|
|
||||||
\begin{ccHtmlOnly}
|
\begin{ccHtmlOnly}
|
||||||
|
|
@ -432,35 +432,35 @@ unchanged.
|
||||||
Halfedge_handle g);}
|
Halfedge_handle g);}
|
||||||
{splits the vertex incident to \ccc{h} and \ccc{g} into two vertices,
|
{splits the vertex incident to \ccc{h} and \ccc{g} into two vertices,
|
||||||
the old vertex remains and a new copy is created,
|
the old vertex remains and a new copy is created,
|
||||||
and connects them with a new edge. Let \ccc{hnew} be
|
and connects them with a new edge. Let \ccc{hnew} be
|
||||||
\ccc{h->next()->opposite()} after the split, i.e., a halfedge
|
\ccc{h->next()->opposite()} after the split, i.e., a halfedge
|
||||||
of the new edge. The split regroups the halfedges around the two
|
of the new edge. The split regroups the halfedges around the two
|
||||||
vertices. The halfedge sequence \ccc{hnew}, \ccc{g->next()->opposite()},
|
vertices. The halfedge sequence \ccc{hnew}, \ccc{g->next()->opposite()},
|
||||||
\ldots, \ccc{h} remains around the old vertex, while the
|
\ldots, \ccc{h} remains around the old vertex, while the
|
||||||
halfedge sequence \ccc{hnew->opposite()}, \ccc{h->next()->opposite()}
|
halfedge sequence \ccc{hnew->opposite()}, \ccc{h->next()->opposite()}
|
||||||
(before the split), \ldots, \ccc{g} is regrouped around the new
|
(before the split), \ldots, \ccc{g} is regrouped around the new
|
||||||
vertex. The split returns \ccc{hnew}, i.e., the new halfedge incident
|
vertex. The split returns \ccc{hnew}, i.e., the new halfedge incident
|
||||||
to the old vertex. The time is proportional to the distance from
|
to the old vertex. The time is proportional to the distance from
|
||||||
\ccc{h} to \ccc{g} around the vertex.
|
\ccc{h} to \ccc{g} around the vertex.
|
||||||
\ccPrecond \ccc{h} and \ccc{g} are incident to the same vertex.
|
\ccPrecond \ccc{h} and \ccc{g} are incident to the same vertex.
|
||||||
\ccc{h != g} (antennas are not allowed).
|
\ccc{h != g} (antennas are not allowed).
|
||||||
\ccCommentHeading{Note} A special application of the split is
|
\ccCommentHeading{Note} A special application of the split is
|
||||||
\ccc{split_vertex(h,h->next()->opposite())} which is equivalent to an
|
\ccc{split_vertex(h,h->next()->opposite())} which is equivalent to an
|
||||||
edge split of the halfedge \ccc{h->next()} that creates a new
|
edge split of the halfedge \ccc{h->next()} that creates a new
|
||||||
vertex on the halfedge \ccc{h->next()}. See also \ccc{split_edge(h)}
|
vertex on the halfedge \ccc{h->next()}. See also \ccc{split_edge(h)}
|
||||||
below.}
|
below.}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle join_vertex( Halfedge_handle h);}
|
\ccMethod{Halfedge_handle join_vertex( Halfedge_handle h);}
|
||||||
{joins the two vertices incident to $h$. The vertex denoted by
|
{joins the two vertices incident to $h$. The vertex denoted by
|
||||||
\ccc{h->opposite()} gets removed. Returns the predecessor of
|
\ccc{h->opposite()} gets removed. Returns the predecessor of
|
||||||
$h$ around the vertex, i.e., \ccc{h->opposite()->prev()}.
|
$h$ around the vertex, i.e., \ccc{h->opposite()->prev()}.
|
||||||
The invariant \ccc{join_vertex( split_vertex( h, g))} returns
|
The invariant \ccc{join_vertex( split_vertex( h, g))} returns
|
||||||
$h$ and keeps the polyhedron unchanged.
|
$h$ and keeps the polyhedron unchanged.
|
||||||
The time is proportional to the degree of the vertex removed and
|
The time is proportional to the degree of the vertex removed and
|
||||||
the time to compute \ccc{h->prev()} and \ccc{h->opposite()->prev()}.
|
the time to compute \ccc{h->prev()} and \ccc{h->opposite()->prev()}.
|
||||||
\ccPrecond The size of both facets incident to $h$ is at least
|
\ccPrecond The size of both facets incident to $h$ is at least
|
||||||
four (no multi-edges).
|
four (no multi-edges).
|
||||||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||||
\ccc{CGAL::Tag_true}.}
|
\ccc{CGAL::Tag_true}.}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle split_edge( Halfedge_handle h);}{
|
\ccMethod{Halfedge_handle split_edge( Halfedge_handle h);}{
|
||||||
|
|
@ -468,7 +468,7 @@ unchanged.
|
||||||
that is a copy of \ccc{h->opposite()->vertex()}. Is equivalent to
|
that is a copy of \ccc{h->opposite()->vertex()}. Is equivalent to
|
||||||
\ccc{split_vertex( h->prev(), h->opposite())}. The call of \ccc{prev()}
|
\ccc{split_vertex( h->prev(), h->opposite())}. The call of \ccc{prev()}
|
||||||
can make this method slower than a direct call of \ccc{split_vertex()}
|
can make this method slower than a direct call of \ccc{split_vertex()}
|
||||||
if the previous halfedge is already known and computing it would be
|
if the previous halfedge is already known and computing it would be
|
||||||
costly when the halfedge data structure does not support the \ccc{prev()}
|
costly when the halfedge data structure does not support the \ccc{prev()}
|
||||||
member function. Returns the new halfedge \ccc{hnew} pointing to the
|
member function. Returns the new halfedge \ccc{hnew} pointing to the
|
||||||
inserted vertex. The new halfedge is followed by the old halfedge, i.e.,
|
inserted vertex. The new halfedge is followed by the old halfedge, i.e.,
|
||||||
|
|
@ -476,7 +476,7 @@ unchanged.
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle flip_edge( Halfedge_handle h);}
|
\ccMethod{Halfedge_handle flip_edge( Halfedge_handle h);}
|
||||||
{performs an edge flip. It returns $h$ after rotating the edge $h$ one
|
{performs an edge flip. It returns $h$ after rotating the edge $h$ one
|
||||||
vertex in the direction of the face orientation.
|
vertex in the direction of the face orientation.
|
||||||
\ccPrecond \ccc{h != Halfedge_handle()} and both facets incident
|
\ccPrecond \ccc{h != Halfedge_handle()} and both facets incident
|
||||||
to $h$ are triangles.}
|
to $h$ are triangles.}
|
||||||
|
|
||||||
|
|
@ -496,9 +496,9 @@ unchanged.
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle create_center_vertex( Halfedge_handle h);}
|
\ccMethod{Halfedge_handle create_center_vertex( Halfedge_handle h);}
|
||||||
{barycentric triangulation of \ccc{h->facet()}. Creates a new vertex,
|
{barycentric triangulation of \ccc{h->facet()}. Creates a new vertex,
|
||||||
a copy of \ccc{h->vertex()}, and connects it to each vertex incident
|
a copy of \ccc{h->vertex()}, and connects it to each vertex incident
|
||||||
to \ccc{h->facet()} splitting \ccc{h->facet()} into triangles.
|
to \ccc{h->facet()} splitting \ccc{h->facet()} into triangles.
|
||||||
\ccc{h} remains incident to the original facet, all other triangles
|
\ccc{h} remains incident to the original facet, all other triangles
|
||||||
are copies of this facet. Returns the halfedge \ccc{h->next()}
|
are copies of this facet. Returns the halfedge \ccc{h->next()}
|
||||||
after the operation, i.e., a halfedge pointing to the new vertex.
|
after the operation, i.e., a halfedge pointing to the new vertex.
|
||||||
The time is proportional to the size of the facet.
|
The time is proportional to the size of the facet.
|
||||||
|
|
@ -507,15 +507,15 @@ unchanged.
|
||||||
\ccMethod{Halfedge_handle erase_center_vertex( Halfedge_handle g);}
|
\ccMethod{Halfedge_handle erase_center_vertex( Halfedge_handle g);}
|
||||||
{reverses \ccc{create_center_vertex}. Erases the
|
{reverses \ccc{create_center_vertex}. Erases the
|
||||||
vertex pointed to by \ccc{g} and all incident halfedges thereby
|
vertex pointed to by \ccc{g} and all incident halfedges thereby
|
||||||
merging all incident facets. Only \ccc{g->facet()} remains.
|
merging all incident facets. Only \ccc{g->facet()} remains.
|
||||||
The neighborhood of \ccc{g->vertex()} may not be triangulated,
|
The neighborhood of \ccc{g->vertex()} may not be triangulated,
|
||||||
it can have larger facets. Returns the halfedge \ccc{g->prev()}.
|
it can have larger facets. Returns the halfedge \ccc{g->prev()}.
|
||||||
Thus, the invariant \ccc{h == erase_center_vertex(
|
Thus, the invariant \ccc{h == erase_center_vertex(
|
||||||
create_center_vertex(h))} holds if \ccc{h} is not a border halfedge.
|
create_center_vertex(h))} holds if \ccc{h} is not a border halfedge.
|
||||||
The time is proportional to the sum of the size of all incident facets.
|
The time is proportional to the sum of the size of all incident facets.
|
||||||
\ccPrecond None of the incident facets of \ccc{g->vertex()} is
|
\ccPrecond None of the incident facets of \ccc{g->vertex()} is
|
||||||
a hole. There are at least two distinct facets incident
|
a hole. There are at least two distinct facets incident
|
||||||
to the facets that are incident to \ccc{g->vertex()}. (This
|
to the facets that are incident to \ccc{g->vertex()}. (This
|
||||||
prevents the operation from collapsing a volume into two facets
|
prevents the operation from collapsing a volume into two facets
|
||||||
glued together with opposite orientations, such as would
|
glued together with opposite orientations, such as would
|
||||||
happen with any vertex of a tetrahedron.)
|
happen with any vertex of a tetrahedron.)
|
||||||
|
|
@ -546,10 +546,10 @@ unchanged.
|
||||||
Halfedge_handle j);}
|
Halfedge_handle j);}
|
||||||
{cuts the polyhedron into two parts along the cycle $(h,i,j)$ (edge \ccc{j}
|
{cuts the polyhedron into two parts along the cycle $(h,i,j)$ (edge \ccc{j}
|
||||||
runs on the backside of the three dimensional figure above).
|
runs on the backside of the three dimensional figure above).
|
||||||
Three new vertices (one copy for each vertex in the cycle) and three
|
Three new vertices (one copy for each vertex in the cycle) and three
|
||||||
new halfedges (one copy for each halfedge in the cycle), and two new
|
new halfedges (one copy for each halfedge in the cycle), and two new
|
||||||
triangles are created. $h,i,j$ will be incident to the first new triangle.
|
triangles are created. $h,i,j$ will be incident to the first new triangle.
|
||||||
The return value will be the halfedge incident to the second new triangle
|
The return value will be the halfedge incident to the second new triangle
|
||||||
which is the copy of \ccc{h-opposite()}.
|
which is the copy of \ccc{h-opposite()}.
|
||||||
\ccPrecond $h,i,j$ denote distinct, consecutive vertices of the
|
\ccPrecond $h,i,j$ denote distinct, consecutive vertices of the
|
||||||
polyhedron and form a cycle: i.e., \ccc{h->vertex() ==
|
polyhedron and form a cycle: i.e., \ccc{h->vertex() ==
|
||||||
|
|
@ -560,25 +560,25 @@ unchanged.
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle join_loop( Halfedge_handle h,
|
\ccMethod{Halfedge_handle join_loop( Halfedge_handle h,
|
||||||
Halfedge_handle g);}
|
Halfedge_handle g);}
|
||||||
{glues the boundary of the two facets denoted by $h$ and $g$ together
|
{glues the boundary of the two facets denoted by $h$ and $g$ together
|
||||||
and returns $h$. Both facets and the vertices along the facet denoted
|
and returns $h$. Both facets and the vertices along the facet denoted
|
||||||
by $g$ gets removed. Both facets may be holes. The invariant
|
by $g$ gets removed. Both facets may be holes. The invariant
|
||||||
\ccc{join_loop( h, split_loop( h, i, j))} returns $h$ and keeps the
|
\ccc{join_loop( h, split_loop( h, i, j))} returns $h$ and keeps the
|
||||||
polyhedron unchanged.
|
polyhedron unchanged.
|
||||||
\ccPrecond The facets denoted by $h$ and $g$ are different and have
|
\ccPrecond The facets denoted by $h$ and $g$ are different and have
|
||||||
equal degree (i.e., number of edges).
|
equal degree (i.e., number of edges).
|
||||||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||||
\ccc{CGAL::Tag_true}.}
|
\ccc{CGAL::Tag_true}.}
|
||||||
|
|
||||||
% +-----------------------------------+
|
% +-----------------------------------+
|
||||||
\ccHeading{Modifying Facets and Holes}
|
\ccHeading{Modifying Facets and Holes}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle make_hole( Halfedge_handle h);}
|
\ccMethod{Halfedge_handle make_hole( Halfedge_handle h);}
|
||||||
{removes the incident facet of $h$ and changes all halfedges incident
|
{removes the incident facet of $h$ and changes all halfedges incident
|
||||||
to the facet into border edges. Returns $h$.
|
to the facet into border edges. Returns $h$.
|
||||||
See \ccc{erase_facet(h)} for a more generalized variant.
|
See \ccc{erase_facet(h)} for a more generalized variant.
|
||||||
\ccPrecond None of the incident halfedges of the facet is a border edge.
|
\ccPrecond None of the incident halfedges of the facet is a border edge.
|
||||||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||||
\ccc{CGAL::Tag_true}.}
|
\ccc{CGAL::Tag_true}.}
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle fill_hole( Halfedge_handle h);}{
|
\ccMethod{Halfedge_handle fill_hole( Halfedge_handle h);}{
|
||||||
|
|
@ -596,26 +596,26 @@ unchanged.
|
||||||
|
|
||||||
\begin{ccHtmlOnly}
|
\begin{ccHtmlOnly}
|
||||||
<CENTER>
|
<CENTER>
|
||||||
<img src="fig/add_facet1.gif"
|
<img src="fig/add_facet1.gif"
|
||||||
alt="Modifying Facets and Holes: add_vertex_and_facet_to_border()"><P>
|
alt="Modifying Facets and Holes: add_vertex_and_facet_to_border()"><P>
|
||||||
</CENTER>
|
</CENTER>
|
||||||
\end{ccHtmlOnly}
|
\end{ccHtmlOnly}
|
||||||
|
|
||||||
|
|
||||||
\ccMethod{Halfedge_handle add_vertex_and_facet_to_border(
|
\ccMethod{Halfedge_handle add_vertex_and_facet_to_border(
|
||||||
Halfedge_handle h, Halfedge_handle g);}
|
Halfedge_handle h, Halfedge_handle g);}
|
||||||
{creates a new facet within the hole incident to $h$
|
{creates a new facet within the hole incident to $h$
|
||||||
and $g$ by connecting the tip of $g$ with the tip of $h$
|
and $g$ by connecting the tip of $g$ with the tip of $h$
|
||||||
with two new halfedges and a new vertex and filling this separated
|
with two new halfedges and a new vertex and filling this separated
|
||||||
part of the hole with a new facet, such that the new facet is
|
part of the hole with a new facet, such that the new facet is
|
||||||
incident to $g$. Returns the halfedge of the new edge that is
|
incident to $g$. Returns the halfedge of the new edge that is
|
||||||
incident to the new facet and the new vertex.
|
incident to the new facet and the new vertex.
|
||||||
\ccPrecond \ccc{h->is_border()}, \ccc{g->is_border()}, \ccc{h != g},
|
\ccPrecond \ccc{h->is_border()}, \ccc{g->is_border()}, \ccc{h != g},
|
||||||
and $g$ can be reached along the same hole starting with $h$.}
|
and $g$ can be reached along the same hole starting with $h$.}
|
||||||
|
|
||||||
\begin{ccHtmlOnly}
|
\begin{ccHtmlOnly}
|
||||||
<CENTER>
|
<CENTER>
|
||||||
<img src="./fig/add_facet2.gif"
|
<img src="./fig/add_facet2.gif"
|
||||||
alt="Modifying Facets and Holes: add_facet_to_border()"><P>
|
alt="Modifying Facets and Holes: add_facet_to_border()"><P>
|
||||||
</CENTER>
|
</CENTER>
|
||||||
\end{ccHtmlOnly}
|
\end{ccHtmlOnly}
|
||||||
|
|
@ -625,9 +625,9 @@ unchanged.
|
||||||
{creates a new facet within the hole incident to $h$ and $g$ by
|
{creates a new facet within the hole incident to $h$ and $g$ by
|
||||||
connecting the vertex denoted by $g$ with the vertex denoted by $h$
|
connecting the vertex denoted by $g$ with the vertex denoted by $h$
|
||||||
with a new halfedge and filling this separated part of the hole with
|
with a new halfedge and filling this separated part of the hole with
|
||||||
a new facet, such that the new facet is incident to $g$.
|
a new facet, such that the new facet is incident to $g$.
|
||||||
Returns the halfedge of the new edge that is incident to the new facet.
|
Returns the halfedge of the new edge that is incident to the new facet.
|
||||||
\ccPrecond \ccc{h->is_border()}, \ccc{g->is_border()}, \ccc{h != g},
|
\ccPrecond \ccc{h->is_border()}, \ccc{g->is_border()}, \ccc{h != g},
|
||||||
\ccc{h->next() != g}, and $g$ can be reached along the same hole
|
\ccc{h->next() != g}, and $g$ can be reached along the same hole
|
||||||
starting with $h$.}
|
starting with $h$.}
|
||||||
|
|
||||||
|
|
@ -636,20 +636,26 @@ unchanged.
|
||||||
\ccHeading{Erasing}
|
\ccHeading{Erasing}
|
||||||
|
|
||||||
\ccMethod{void erase_facet( Halfedge_handle h);}
|
\ccMethod{void erase_facet( Halfedge_handle h);}
|
||||||
{removes the incident facet of $h$ and changes all halfedges incident
|
{removes the incident facet of $h$ and changes all halfedges incident
|
||||||
to the facet into border edges or removes them from the
|
to the facet into border edges or removes them from the
|
||||||
polyhedral surface if they were already border edges.
|
polyhedral surface if they were already border edges.
|
||||||
If this creates isolated vertices they get removed as well.
|
If this creates isolated vertices they get removed as well.
|
||||||
See \ccc{make_hole(h)} for a more specialized variant.
|
See \ccc{make_hole(h)} for a more specialized variant.
|
||||||
\ccPrecond \ccc{h->is_border() == false}. \ccCommentHeading{Requirement}
|
\ccPrecond \ccc{h->is_border() == false}. \ccCommentHeading{Requirement}
|
||||||
\ccc{Supports_removal} $\equiv$ \ccc{CGAL::Tag_true}.}
|
\ccc{Supports_removal} $\equiv$ \ccc{CGAL::Tag_true}.}
|
||||||
|
|
||||||
\ccMethod{void erase_connected_component( Halfedge_handle h);}
|
\ccMethod{void erase_connected_component( Halfedge_handle h);}
|
||||||
{removes the vertices, halfedges, and facets that belong to the
|
{removes the vertices, halfedges, and facets that belong to the
|
||||||
connected component of $h$.
|
connected component of $h$.
|
||||||
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
\ccCommentHeading{Requirement} \ccc{Supports_removal} $\equiv$
|
||||||
\ccc{CGAL::Tag_true}.}
|
\ccc{CGAL::Tag_true}.}
|
||||||
|
|
||||||
|
\ccMethod{unsigned int keep_largest_connected_components(unsigned int nb_components_to_keep);}
|
||||||
|
{Erases the small connected components and the isolated vertices.
|
||||||
|
Keep \ccc{nb_components_to_keep} largest connected components.
|
||||||
|
Returns the number of connected components erased (ignoring isolated vertices).
|
||||||
|
\ccCommentHeading{Requirement} supports vertices, halfedges, and removal operation.}
|
||||||
|
|
||||||
\ccMethod{void clear();}
|
\ccMethod{void clear();}
|
||||||
{removes all vertices, halfedges, and facets.}
|
{removes all vertices, halfedges, and facets.}
|
||||||
|
|
||||||
|
|
@ -658,7 +664,7 @@ unchanged.
|
||||||
\ccHeading{Operations with Border Halfedges}
|
\ccHeading{Operations with Border Halfedges}
|
||||||
|
|
||||||
\begin{ccAdvanced}
|
\begin{ccAdvanced}
|
||||||
|
|
||||||
Halfedges incident to a hole are called {\em border halfedges}. An
|
Halfedges incident to a hole are called {\em border halfedges}. An
|
||||||
halfedge is a {\em border edge\/} if itself or its opposite halfedge
|
halfedge is a {\em border edge\/} if itself or its opposite halfedge
|
||||||
are border halfedges. The only requirement to work with border
|
are border halfedges. The only requirement to work with border
|
||||||
|
|
@ -684,7 +690,7 @@ automatically updated.
|
||||||
{sorts halfedges such that the non-border edges precede the
|
{sorts halfedges such that the non-border edges precede the
|
||||||
border edges. For each border edge the halfedge iterator will
|
border edges. For each border edge the halfedge iterator will
|
||||||
reference the halfedge incident to the facet right before the
|
reference the halfedge incident to the facet right before the
|
||||||
halfedge incident to the hole.}
|
halfedge incident to the hole.}
|
||||||
|
|
||||||
\ccMethod{size_type size_of_border_halfedges() const;}
|
\ccMethod{size_type size_of_border_halfedges() const;}
|
||||||
{number of border halfedges.
|
{number of border halfedges.
|
||||||
|
|
@ -721,7 +727,7 @@ automatically updated.
|
||||||
{reverses facet orientations (incl.\ plane equations if supported).}
|
{reverses facet orientations (incl.\ plane equations if supported).}
|
||||||
|
|
||||||
\ccMethod{bool is_valid( bool verbose = false, int level = 0) const;}
|
\ccMethod{bool is_valid( bool verbose = false, int level = 0) const;}
|
||||||
{returns \ccc{true} if the polyhedral surface is combinatorially
|
{returns \ccc{true} if the polyhedral surface is combinatorially
|
||||||
consistent. If \ccc{verbose} is \ccc{true}, statistics are
|
consistent. If \ccc{verbose} is \ccc{true}, statistics are
|
||||||
printed to \ccc{cerr}. For \ccc{level == 1} the normalization of the
|
printed to \ccc{cerr}. For \ccc{level == 1} the normalization of the
|
||||||
border edges is checked too. This method checks in particular level 3 of
|
border edges is checked too. This method checks in particular level 3 of
|
||||||
|
|
@ -731,7 +737,7 @@ automatically updated.
|
||||||
distinct.}
|
distinct.}
|
||||||
|
|
||||||
\ccMethod{bool normalized_border_is_valid( bool verbose = false) const;}{%
|
\ccMethod{bool normalized_border_is_valid( bool verbose = false) const;}{%
|
||||||
returns \ccc{true} if the border halfedges are in normalized
|
returns \ccc{true} if the border halfedges are in normalized
|
||||||
representation, which is when enumerating all halfedges with the
|
representation, which is when enumerating all halfedges with the
|
||||||
iterator: The non-border edges precede the border edges and for
|
iterator: The non-border edges precede the border edges and for
|
||||||
border edges, the second halfedge is the border halfedge. The halfedge
|
border edges, the second halfedge is the border halfedge. The halfedge
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
//
|
//
|
||||||
// $URL$
|
// $URL$
|
||||||
// $Id$
|
// $Id$
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Author(s) : Lutz Kettner <kettner@mpi-sb.mpg.de>)
|
// Author(s) : Lutz Kettner <kettner@mpi-sb.mpg.de>)
|
||||||
|
|
||||||
|
|
@ -111,9 +111,9 @@ public:
|
||||||
return Halfedge_around_vertex_const_circulator( this->halfedge());
|
return Halfedge_around_vertex_const_circulator( this->halfedge());
|
||||||
}
|
}
|
||||||
|
|
||||||
// the degree of the vertex, i.e., edges emanating from this vertex
|
// the degree of the vertex, i.e., edges emanating from this vertex
|
||||||
std::size_t vertex_degree() const {
|
std::size_t vertex_degree() const {
|
||||||
return this->halfedge()->vertex_degree();
|
return this->halfedge()->vertex_degree();
|
||||||
}
|
}
|
||||||
size_type degree() const { return vertex_degree(); } //backwards compatible
|
size_type degree() const { return vertex_degree(); } //backwards compatible
|
||||||
|
|
||||||
|
|
@ -286,20 +286,20 @@ public:
|
||||||
HDS::halfedge_handle(this));
|
HDS::halfedge_handle(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
// the degree of the incident vertex, i.e., edges emanating from this
|
// the degree of the incident vertex, i.e., edges emanating from this
|
||||||
// vertex
|
// vertex
|
||||||
std::size_t vertex_degree() const {
|
std::size_t vertex_degree() const {
|
||||||
return circulator_size( vertex_begin());
|
return circulator_size( vertex_begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
// the degree of the incident facet, i.e., edges on the boundary of this
|
// the degree of the incident facet, i.e., edges on the boundary of this
|
||||||
// facet
|
// facet
|
||||||
std::size_t facet_degree() const {
|
std::size_t facet_degree() const {
|
||||||
return circulator_size( facet_begin());
|
return circulator_size( facet_begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if the incident vertex has exactly two incident edges
|
// returns true if the incident vertex has exactly two incident edges
|
||||||
bool is_bivalent() const {
|
bool is_bivalent() const {
|
||||||
CGAL_precondition( this != &* (this->next()->opposite()));
|
CGAL_precondition( this != &* (this->next()->opposite()));
|
||||||
return (this == &* (this->next()->opposite()->next()->opposite()));
|
return (this == &* (this->next()->opposite()->next()->opposite()));
|
||||||
}
|
}
|
||||||
|
|
@ -410,7 +410,7 @@ public:
|
||||||
return Halfedge_around_facet_const_circulator( this->halfedge());
|
return Halfedge_around_facet_const_circulator( this->halfedge());
|
||||||
}
|
}
|
||||||
|
|
||||||
// the degree of the incident facet, i.e., edges on the boundary of this
|
// the degree of the incident facet, i.e., edges on the boundary of this
|
||||||
// facet
|
// facet
|
||||||
std::size_t facet_degree() const {return this->halfedge()->facet_degree();}
|
std::size_t facet_degree() const {return this->halfedge()->facet_degree();}
|
||||||
size_type size() const { return facet_degree(); } // backwards compatible
|
size_type size() const { return facet_degree(); } // backwards compatible
|
||||||
|
|
@ -463,7 +463,7 @@ template < class PolyhedronTraits_3,
|
||||||
#ifndef CGAL_CFG_NO_TMPL_IN_TMPL_PARAM
|
#ifndef CGAL_CFG_NO_TMPL_IN_TMPL_PARAM
|
||||||
template < class T, class I, class A>
|
template < class T, class I, class A>
|
||||||
#endif
|
#endif
|
||||||
class T_HDS = HalfedgeDS_default,
|
class T_HDS = HalfedgeDS_default,
|
||||||
class Alloc = CGAL_ALLOCATOR(int)>
|
class Alloc = CGAL_ALLOCATOR(int)>
|
||||||
class Polyhedron_3 {
|
class Polyhedron_3 {
|
||||||
//
|
//
|
||||||
|
|
@ -873,7 +873,7 @@ public:
|
||||||
|
|
||||||
// Combinatorial Predicates
|
// Combinatorial Predicates
|
||||||
|
|
||||||
bool is_closed() const {
|
bool is_closed() const {
|
||||||
for ( Halfedge_const_iterator i = halfedges_begin();
|
for ( Halfedge_const_iterator i = halfedges_begin();
|
||||||
i != halfedges_end(); ++i) {
|
i != halfedges_end(); ++i) {
|
||||||
if ( i->is_border())
|
if ( i->is_border())
|
||||||
|
|
@ -883,14 +883,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_pure_bivalent( Tag_true) const {
|
bool is_pure_bivalent( Tag_true) const {
|
||||||
for ( Vertex_const_iterator i = vertices_begin();
|
for ( Vertex_const_iterator i = vertices_begin();
|
||||||
i != vertices_end(); ++i)
|
i != vertices_end(); ++i)
|
||||||
if ( ! i->is_bivalent())
|
if ( ! i->is_bivalent())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool is_pure_bivalent( Tag_false) const {
|
bool is_pure_bivalent( Tag_false) const {
|
||||||
for ( Halfedge_const_iterator i = halfedges_begin();
|
for ( Halfedge_const_iterator i = halfedges_begin();
|
||||||
i != halfedges_end(); ++i)
|
i != halfedges_end(); ++i)
|
||||||
if ( ! i->is_bivalent())
|
if ( ! i->is_bivalent())
|
||||||
|
|
@ -900,19 +900,19 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// returns true if all vertices have exactly two incident edges
|
// returns true if all vertices have exactly two incident edges
|
||||||
bool is_pure_bivalent() const {
|
bool is_pure_bivalent() const {
|
||||||
return is_pure_bivalent( Supports_vertex_halfedge());
|
return is_pure_bivalent( Supports_vertex_halfedge());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_pure_trivalent( Tag_true) const {
|
bool is_pure_trivalent( Tag_true) const {
|
||||||
for ( Vertex_const_iterator i = vertices_begin();
|
for ( Vertex_const_iterator i = vertices_begin();
|
||||||
i != vertices_end(); ++i)
|
i != vertices_end(); ++i)
|
||||||
if ( ! i->is_trivalent())
|
if ( ! i->is_trivalent())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool is_pure_trivalent( Tag_false) const {
|
bool is_pure_trivalent( Tag_false) const {
|
||||||
for ( Halfedge_const_iterator i = halfedges_begin();
|
for ( Halfedge_const_iterator i = halfedges_begin();
|
||||||
i != halfedges_end(); ++i)
|
i != halfedges_end(); ++i)
|
||||||
if ( ! i->is_trivalent())
|
if ( ! i->is_trivalent())
|
||||||
|
|
@ -922,19 +922,19 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// returns true if all vertices have exactly three incident edges
|
// returns true if all vertices have exactly three incident edges
|
||||||
bool is_pure_trivalent() const {
|
bool is_pure_trivalent() const {
|
||||||
return is_pure_trivalent( Supports_vertex_halfedge());
|
return is_pure_trivalent( Supports_vertex_halfedge());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_pure_triangle( Tag_true) const {
|
bool is_pure_triangle( Tag_true) const {
|
||||||
for ( Facet_const_iterator i = facets_begin();
|
for ( Facet_const_iterator i = facets_begin();
|
||||||
i != facets_end(); ++i)
|
i != facets_end(); ++i)
|
||||||
if ( ! i->is_triangle())
|
if ( ! i->is_triangle())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool is_pure_triangle( Tag_false) const {
|
bool is_pure_triangle( Tag_false) const {
|
||||||
for ( Halfedge_const_iterator i = halfedges_begin();
|
for ( Halfedge_const_iterator i = halfedges_begin();
|
||||||
i != halfedges_end(); ++i)
|
i != halfedges_end(); ++i)
|
||||||
if ( ! i->is_border() && ! i->is_triangle())
|
if ( ! i->is_border() && ! i->is_triangle())
|
||||||
|
|
@ -944,19 +944,19 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// returns true if all facets are triangles
|
// returns true if all facets are triangles
|
||||||
bool is_pure_triangle() const {
|
bool is_pure_triangle() const {
|
||||||
return is_pure_triangle( Supports_facet_halfedge());
|
return is_pure_triangle( Supports_facet_halfedge());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_pure_quad( Tag_true) const {
|
bool is_pure_quad( Tag_true) const {
|
||||||
for ( Facet_const_iterator i = facets_begin();
|
for ( Facet_const_iterator i = facets_begin();
|
||||||
i != facets_end(); ++i)
|
i != facets_end(); ++i)
|
||||||
if ( ! i->is_quad())
|
if ( ! i->is_quad())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool is_pure_quad( Tag_false) const {
|
bool is_pure_quad( Tag_false) const {
|
||||||
for ( Halfedge_const_iterator i = halfedges_begin();
|
for ( Halfedge_const_iterator i = halfedges_begin();
|
||||||
i != halfedges_end(); ++i)
|
i != halfedges_end(); ++i)
|
||||||
if ( ! i->is_border() && ! i->is_quad())
|
if ( ! i->is_border() && ! i->is_quad())
|
||||||
|
|
@ -966,7 +966,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// returns true if all facets are quadrilaterals
|
// returns true if all facets are quadrilaterals
|
||||||
bool is_pure_quad() const {
|
bool is_pure_quad() const {
|
||||||
return is_pure_quad( Supports_facet_halfedge());
|
return is_pure_quad( Supports_facet_halfedge());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1376,6 +1376,21 @@ public:
|
||||||
D.erase_connected_component(h);
|
D.erase_connected_component(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Erases the small connected components and the isolated vertices.
|
||||||
|
///
|
||||||
|
/// @commentheading Preconditions:
|
||||||
|
/// supports vertices, halfedges, and removal operation.
|
||||||
|
///
|
||||||
|
/// @commentheading Template Parameters:
|
||||||
|
/// @param nb_components_to_keep the number of large connected components to keep.
|
||||||
|
///
|
||||||
|
/// @return the number of connected components erased (ignoring isolated vertices).
|
||||||
|
unsigned int keep_largest_connected_components(unsigned int nb_components_to_keep)
|
||||||
|
{
|
||||||
|
HalfedgeDS_decorator<HDS> D(hds);
|
||||||
|
return D.keep_largest_connected_components(nb_components_to_keep);
|
||||||
|
}
|
||||||
|
|
||||||
void clear() { hds.clear(); }
|
void clear() { hds.clear(); }
|
||||||
// removes all vertices, halfedges, and facets.
|
// removes all vertices, halfedges, and facets.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,7 @@ typename Poly::Halfedge_handle make_cube_3( Poly& P) {
|
||||||
h->next()->vertex()->point() = Point( 1, 0, 1);
|
h->next()->vertex()->point() = Point( 1, 0, 1);
|
||||||
g->next()->vertex()->point() = Point( 0, 1, 1);
|
g->next()->vertex()->point() = Point( 0, 1, 1);
|
||||||
g->opposite()->vertex()->point() = Point( 1, 1, 0); // Fig. (c)
|
g->opposite()->vertex()->point() = Point( 1, 1, 0); // Fig. (c)
|
||||||
Halfedge_handle f = P.split_facet( g->next(),
|
Halfedge_handle f = P.split_facet( g->next(),
|
||||||
g->next()->next()->next()); // Fig. (d)
|
g->next()->next()->next()); // Fig. (d)
|
||||||
Halfedge_handle e = P.split_edge( f);
|
Halfedge_handle e = P.split_edge( f);
|
||||||
e->vertex()->point() = Point( 1, 1, 1); // Fig. (e)
|
e->vertex()->point() = Point( 1, 1, 1); // Fig. (e)
|
||||||
|
|
@ -425,10 +425,10 @@ void test_Polyhedron() {
|
||||||
CGAL_assertion( h->facet_degree() == 3);
|
CGAL_assertion( h->facet_degree() == 3);
|
||||||
CGAL_assertion( h->facet()->facet_degree() == 3);
|
CGAL_assertion( h->facet()->facet_degree() == 3);
|
||||||
CGAL_assertion( P.is_pure_triangle());
|
CGAL_assertion( P.is_pure_triangle());
|
||||||
CGAL_assertion( 2 == halfedgeds_connected_components(P,
|
CGAL_assertion( 2 == halfedgeds_connected_components(P,
|
||||||
CGAL::Emptyset_iterator()));
|
CGAL::Emptyset_iterator()));
|
||||||
CGAL_assertion_code( const Polyhedron& Pq(P);)
|
CGAL_assertion_code( const Polyhedron& Pq(P);)
|
||||||
CGAL_assertion( 2 == halfedgeds_connected_components(Pq,
|
CGAL_assertion( 2 == halfedgeds_connected_components(Pq,
|
||||||
CGAL::Emptyset_iterator()));
|
CGAL::Emptyset_iterator()));
|
||||||
P.normalize_border();
|
P.normalize_border();
|
||||||
CGAL_assertion( P.is_valid( false, 1));
|
CGAL_assertion( P.is_valid( false, 1));
|
||||||
|
|
@ -594,7 +594,7 @@ void test_Polyhedron() {
|
||||||
CGAL_assertion( P.is_valid());
|
CGAL_assertion( P.is_valid());
|
||||||
CGAL_assertion( P.is_triangle( h));
|
CGAL_assertion( P.is_triangle( h));
|
||||||
|
|
||||||
CGAL_assertion_code( Halfedge_handle g =
|
CGAL_assertion_code( Halfedge_handle g =
|
||||||
P.add_vertex_and_facet_to_border(
|
P.add_vertex_and_facet_to_border(
|
||||||
h->next()->opposite(),
|
h->next()->opposite(),
|
||||||
h->opposite());)
|
h->opposite());)
|
||||||
|
|
@ -633,6 +633,14 @@ void test_Polyhedron() {
|
||||||
CGAL_assertion( P.size_of_vertices() == 4);
|
CGAL_assertion( P.size_of_vertices() == 4);
|
||||||
CGAL_assertion( P.size_of_halfedges() == 12);
|
CGAL_assertion( P.size_of_halfedges() == 12);
|
||||||
CGAL_assertion( P.size_of_facets() == 4);
|
CGAL_assertion( P.size_of_facets() == 4);
|
||||||
|
P.make_triangle();
|
||||||
|
unsigned int nb_erased_components = P.keep_largest_connected_components(1);
|
||||||
|
CGAL_assertion( nb_erased_components == 1 );
|
||||||
|
CGAL_assertion( P.is_valid());
|
||||||
|
CGAL_assertion( P.is_tetrahedron( g));
|
||||||
|
CGAL_assertion( P.size_of_vertices() == 4);
|
||||||
|
CGAL_assertion( P.size_of_halfedges() == 12);
|
||||||
|
CGAL_assertion( P.size_of_facets() == 4);
|
||||||
P.erase_facet( g);
|
P.erase_facet( g);
|
||||||
CGAL_assertion( P.is_valid());
|
CGAL_assertion( P.is_valid());
|
||||||
CGAL_assertion( P.size_of_vertices() == 4);
|
CGAL_assertion( P.size_of_vertices() == 4);
|
||||||
|
|
@ -1165,7 +1173,7 @@ void test_min_Polyhedron() {
|
||||||
CGAL_assertion( P.is_valid());
|
CGAL_assertion( P.is_valid());
|
||||||
CGAL_assertion( P.is_triangle( h));
|
CGAL_assertion( P.is_triangle( h));
|
||||||
|
|
||||||
CGAL_assertion_code( Halfedge_handle g =
|
CGAL_assertion_code( Halfedge_handle g =
|
||||||
P.add_vertex_and_facet_to_border(
|
P.add_vertex_and_facet_to_border(
|
||||||
h->next()->opposite(),
|
h->next()->opposite(),
|
||||||
h->opposite());)
|
h->opposite());)
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ endforeach()
|
||||||
# Require packages new or improved since CGAL 3.4
|
# Require packages new or improved since CGAL 3.4
|
||||||
include_directories (BEFORE ../../../../AABB_tree/include)
|
include_directories (BEFORE ../../../../AABB_tree/include)
|
||||||
include_directories (BEFORE ../../../../Surface_mesher/include)
|
include_directories (BEFORE ../../../../Surface_mesher/include)
|
||||||
|
include_directories (BEFORE ../../../../Polyhedron/include/)
|
||||||
|
include_directories (BEFORE ../../../../HalfedgeDS/include/)
|
||||||
include_directories (BEFORE ../../../../Point_set_processing_3/include)
|
include_directories (BEFORE ../../../../Point_set_processing_3/include)
|
||||||
|
|
||||||
# Include this package's headers first
|
# Include this package's headers first
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
// This package
|
// This package
|
||||||
#include <CGAL/APSS_reconstruction_function.h>
|
#include <CGAL/APSS_reconstruction_function.h>
|
||||||
#include <CGAL/IO/output_surface_facets_to_polyhedron.h>
|
#include <CGAL/IO/output_surface_facets_to_polyhedron.h>
|
||||||
#include <CGAL/keep_largest_connected_components.h>
|
|
||||||
|
|
||||||
|
|
||||||
// APSS implicit function
|
// APSS implicit function
|
||||||
|
|
@ -127,11 +126,11 @@ Polyhedron* APSS_reconstruct(const Point_set& points,
|
||||||
std::cerr << "Erases small connected components...\n";
|
std::cerr << "Erases small connected components...\n";
|
||||||
|
|
||||||
unsigned int nb_erased_components =
|
unsigned int nb_erased_components =
|
||||||
CGAL::keep_largest_connected_components(*output_mesh, 1/* keep largest component only*/);
|
output_mesh->keep_largest_connected_components( 1 /* keep largest component only*/ );
|
||||||
|
|
||||||
// Prints status
|
// Prints status
|
||||||
std::cerr << "Erases small connected components: " << task_timer.time() << " seconds, "
|
std::cerr << "Erases small connected components: " << task_timer.time() << " seconds, "
|
||||||
<< nb_erased_components << " components erased"
|
<< nb_erased_components << " component(s) erased"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
task_timer.reset();
|
task_timer.reset();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# This is the CMake script for compiling the Surface_reconstruction_points_3 MFC demo.
|
# This is the CMake script for compiling the Surface_reconstruction_points_3 MFC demo.
|
||||||
|
|
||||||
project( Poisson )
|
project( Poisson )
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.4.5)
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.4.5)
|
||||||
|
|
||||||
|
|
@ -13,6 +13,8 @@ endif(COMMAND cmake_policy)
|
||||||
# Require packages new or improved since CGAL 3.4
|
# Require packages new or improved since CGAL 3.4
|
||||||
include_directories (BEFORE ../../../../AABB_tree/include)
|
include_directories (BEFORE ../../../../AABB_tree/include)
|
||||||
include_directories (BEFORE ../../../../Surface_mesher/include)
|
include_directories (BEFORE ../../../../Surface_mesher/include)
|
||||||
|
include_directories (BEFORE ../../../../Polyhedron/include/)
|
||||||
|
include_directories (BEFORE ../../../../HalfedgeDS/include/)
|
||||||
include_directories (BEFORE ../../../../Point_set_processing_3/include)
|
include_directories (BEFORE ../../../../Point_set_processing_3/include)
|
||||||
|
|
||||||
# Include this package's headers first
|
# Include this package's headers first
|
||||||
|
|
@ -25,11 +27,11 @@ if ( CGAL_FOUND )
|
||||||
include( CGAL_CreateSingleSourceCGALProgram )
|
include( CGAL_CreateSingleSourceCGALProgram )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# This demo requires MFC
|
# This demo requires MFC
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
message( STATUS "MFC library found" )
|
message( STATUS "MFC library found" )
|
||||||
ADD_DEFINITIONS( "-D_AFXDLL" )
|
ADD_DEFINITIONS( "-D_AFXDLL" )
|
||||||
SET(CMAKE_MFC_FLAG 2)
|
SET(CMAKE_MFC_FLAG 2)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# This demo requires OpenGL
|
# This demo requires OpenGL
|
||||||
|
|
@ -45,7 +47,7 @@ if(OPENGL_FOUND)
|
||||||
link_libraries( ${OPENGL_LIBRARIES} )
|
link_libraries( ${OPENGL_LIBRARIES} )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# This demo requires TAUCS
|
# This demo requires TAUCS
|
||||||
find_package(TAUCS)
|
find_package(TAUCS)
|
||||||
if(TAUCS_FOUND)
|
if(TAUCS_FOUND)
|
||||||
include( ${TAUCS_USE_FILE} )
|
include( ${TAUCS_USE_FILE} )
|
||||||
|
|
@ -83,9 +85,9 @@ if(CGAL_FOUND AND MSVC AND OPENGL_FOUND AND TAUCS_FOUND)
|
||||||
|
|
||||||
# Creates Poisson executable
|
# Creates Poisson executable
|
||||||
ADD_EXECUTABLE(Poisson WIN32 ChildFrm.cpp DialogOptions.cpp director.cpp MainFrm.cpp Poisson.cpp PoissonDoc.cpp PoissonView.cpp Poisson.rc)
|
ADD_EXECUTABLE(Poisson WIN32 ChildFrm.cpp DialogOptions.cpp director.cpp MainFrm.cpp Poisson.cpp PoissonDoc.cpp PoissonView.cpp Poisson.rc)
|
||||||
|
|
||||||
# Link the executable to CGAL and third-party libraries
|
# Link the executable to CGAL and third-party libraries
|
||||||
if ( CGAL_AUTO_LINK_ENABLED )
|
if ( CGAL_AUTO_LINK_ENABLED )
|
||||||
target_link_libraries(Poisson ${CGAL_3RD_PARTY_LIBRARIES} )
|
target_link_libraries(Poisson ${CGAL_3RD_PARTY_LIBRARIES} )
|
||||||
else()
|
else()
|
||||||
target_link_libraries(Poisson ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} )
|
target_link_libraries(Poisson ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} )
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ The quality of the reconstruction highly depends on both the quality of input no
|
||||||
|
|
||||||
The radius property should correspond to the local point spacing which can be intuitively defined as the average distance to its {\em natural} one ring neighbors. It defines the {\em surface definition domain} as the union of these balls. Outside this union of balls, the surface is not defined. Therefore, if the balls do not overlap enough, then some holes might appear. If no radius is provided, then they are automatically computed from a basic estimate of the local density based on the 16 nearest neighbors.
|
The radius property should correspond to the local point spacing which can be intuitively defined as the average distance to its {\em natural} one ring neighbors. It defines the {\em surface definition domain} as the union of these balls. Outside this union of balls, the surface is not defined. Therefore, if the balls do not overlap enough, then some holes might appear. If no radius is provided, then they are automatically computed from a basic estimate of the local density based on the 16 nearest neighbors.
|
||||||
|
|
||||||
APSS reconstruction may create small {\em ghost} connected components close to the reconstructed surface that you should delete with e.g. \ccc{keep_largest_connected_components}().
|
APSS reconstruction may create small {\em ghost} connected components close to the reconstructed surface that you should delete with e.g. \ccc{Polyhedron_3::keep_largest_connected_components}().
|
||||||
|
|
||||||
%END-AUTO(\ccDefinition)
|
%END-AUTO(\ccDefinition)
|
||||||
|
|
||||||
|
|
@ -164,7 +164,6 @@ Returns a point located inside the inferred surface.
|
||||||
\ccSeeAlso
|
\ccSeeAlso
|
||||||
|
|
||||||
\ccRefIdfierPage{CGAL::Poisson_reconstruction_function<GeomTraits, ReconstructionTriangulation_3>} \\
|
\ccRefIdfierPage{CGAL::Poisson_reconstruction_function<GeomTraits, ReconstructionTriangulation_3>} \\
|
||||||
\ccRefIdfierPage{CGAL::keep_largest_connected_components<Polyhedron>} \\
|
|
||||||
|
|
||||||
\ccExample
|
\ccExample
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
% +------------------------------------------------------------------------+
|
% +------------------------------------------------------------------------+
|
||||||
% | Reference manual page: Surface_reconstruction_points_3/intro.tex
|
% | Reference manual page: Surface_reconstruction_points_3/intro.tex
|
||||||
% +------------------------------------------------------------------------+
|
% +------------------------------------------------------------------------+
|
||||||
% | 06.01.2009 Pierre Alliez, Laurent Saboret, Gael Guennebaud, Mariette Yvinec
|
% | 06.01.2009 Pierre Alliez, Laurent Saboret
|
||||||
% | Package: Surface_reconstruction_points_3
|
% | Package: Surface_reconstruction_points_3
|
||||||
% |
|
% |
|
||||||
% |
|
% |
|
||||||
|
|
@ -23,9 +23,3 @@ Note that since reconstruction methods often require pre-processing a point set
|
||||||
\ccRefIdfierPage{CGAL::Poisson_reconstruction_function<GeomTraits, ReconstructionTriangulation_3>} \\
|
\ccRefIdfierPage{CGAL::Poisson_reconstruction_function<GeomTraits, ReconstructionTriangulation_3>} \\
|
||||||
\ccRefIdfierPage{CGAL::APSS_reconstruction_function<GeomTraits>} \\
|
\ccRefIdfierPage{CGAL::APSS_reconstruction_function<GeomTraits>} \\
|
||||||
|
|
||||||
|
|
||||||
\subsection{Functions}
|
|
||||||
|
|
||||||
\ccRefIdfierPage{CGAL::output_surface_facets_to_polyhedron} \\
|
|
||||||
\ccRefIdfierPage{CGAL::keep_largest_connected_components<Polyhedron>} \\
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
% +------------------------------------------------------------------------+
|
|
||||||
% | Reference manual page: keep_largest_connected_components.tex
|
|
||||||
% +------------------------------------------------------------------------+
|
|
||||||
% | 16.04.2009 Pierre Alliez, Laurent Saboret, Gael Guennebaud
|
|
||||||
% | Package: Surface_reconstruction_points_3
|
|
||||||
% |
|
|
||||||
\RCSdef{\RCSerasesmallpolyhedronconnectedcomponentsRev}{$Id$}
|
|
||||||
\RCSdefDate{\RCSerasesmallpolyhedronconnectedcomponentsDate}{$Date$}
|
|
||||||
% |
|
|
||||||
\ccRefPageBegin
|
|
||||||
%%RefPage: end of header, begin of main body
|
|
||||||
% +------------------------------------------------------------------------+
|
|
||||||
|
|
||||||
|
|
||||||
\begin{ccRefFunction}{keep_largest_connected_components<Polyhedron>}
|
|
||||||
|
|
||||||
%% \ccHtmlCrossLink{} %% add further rules for cross referencing links
|
|
||||||
%% \ccHtmlIndexC[function]{} %% add further index entries
|
|
||||||
|
|
||||||
\ccDefinition
|
|
||||||
|
|
||||||
\ccc{keep_largest_connected_components<Polyhedron>} erases the small connected components of a polyhedron.
|
|
||||||
|
|
||||||
% The section below is automatically generated. Do not edit!
|
|
||||||
%START-AUTO(\ccDefinition)
|
|
||||||
|
|
||||||
% Reduce left margin
|
|
||||||
\ccThree{123456789012345}{6789012}{}
|
|
||||||
|
|
||||||
\ccFunction{template<class Polyhedron> unsigned int keep_largest_connected_components(Polyhedron& polyhedron, unsigned int nb_components_to_keep);}
|
|
||||||
{
|
|
||||||
Erases small connected components of a polyhedron.
|
|
||||||
\ccCommentHeading{Template Parameters} \\
|
|
||||||
\ccc{Polyhedron}: an instance of \ccc{Polyhedron_3<Traits>} that supports vertices and removal operation. \ccc{nb_components_to_keep}: the number of large connected components to keep.
|
|
||||||
\ccCommentHeading{Returns} the number of connected components erased.
|
|
||||||
}
|
|
||||||
\ccGlue
|
|
||||||
|
|
||||||
%END-AUTO(\ccDefinition)
|
|
||||||
|
|
||||||
\ccInclude{CGAL/keep_largest_connected_components.h}
|
|
||||||
|
|
||||||
\ccSeeAlso
|
|
||||||
|
|
||||||
\ccRefIdfierPage{CGAL::Polyhedron_3<Traits>} \\
|
|
||||||
|
|
||||||
\ccExample
|
|
||||||
|
|
||||||
See \ccc{APSS_reconstruction.cpp} example.
|
|
||||||
|
|
||||||
\end{ccRefFunction}
|
|
||||||
|
|
||||||
% +------------------------------------------------------------------------+
|
|
||||||
%%RefPage: end of main body, begin of footer
|
|
||||||
\ccRefPageEnd
|
|
||||||
% EOF
|
|
||||||
% +------------------------------------------------------------------------+
|
|
||||||
|
|
||||||
|
|
@ -8,8 +8,6 @@
|
||||||
\input{Surface_reconstruction_points_3_ref/intro.tex}
|
\input{Surface_reconstruction_points_3_ref/intro.tex}
|
||||||
|
|
||||||
\input{Surface_reconstruction_points_3_ref/APSS_reconstruction_function.tex}
|
\input{Surface_reconstruction_points_3_ref/APSS_reconstruction_function.tex}
|
||||||
\input{Surface_reconstruction_points_3_ref/keep_largest_connected_components.tex}
|
|
||||||
\input{Surface_reconstruction_points_3_ref/output_surface_facets_to_polyhedron.tex}
|
|
||||||
\input{Surface_reconstruction_points_3_ref/Poisson_reconstruction_function.tex}
|
\input{Surface_reconstruction_points_3_ref/Poisson_reconstruction_function.tex}
|
||||||
|
|
||||||
%% EOF
|
%% EOF
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
#include <CGAL/point_set_property_map.h>
|
#include <CGAL/point_set_property_map.h>
|
||||||
#include <CGAL/IO/read_xyz_points.h>
|
#include <CGAL/IO/read_xyz_points.h>
|
||||||
#include <CGAL/IO/output_surface_facets_to_polyhedron.h>
|
#include <CGAL/IO/output_surface_facets_to_polyhedron.h>
|
||||||
#include <CGAL/keep_largest_connected_components.h>
|
|
||||||
|
|
||||||
#include "compute_normal.h"
|
#include "compute_normal.h"
|
||||||
|
|
||||||
|
|
@ -273,11 +272,11 @@ int main(int argc, char * argv[])
|
||||||
std::cerr << "Erases small connected components...\n";
|
std::cerr << "Erases small connected components...\n";
|
||||||
|
|
||||||
unsigned int nb_erased_components =
|
unsigned int nb_erased_components =
|
||||||
CGAL::keep_largest_connected_components(output_mesh, 1/* keep largest component only*/);
|
output_mesh.keep_largest_connected_components( 1 /* keep largest component only*/ );
|
||||||
|
|
||||||
// Prints status
|
// Prints status
|
||||||
std::cerr << "Erases small connected components: " << task_timer.time() << " seconds, "
|
std::cerr << "Erases small connected components: " << task_timer.time() << " seconds, "
|
||||||
<< nb_erased_components << " components erased"
|
<< nb_erased_components << " component(s) erased"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
task_timer.reset();
|
task_timer.reset();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ endif(COMMAND cmake_policy)
|
||||||
|
|
||||||
# Require packages new or improved since CGAL 3.4
|
# Require packages new or improved since CGAL 3.4
|
||||||
include_directories (BEFORE ../../../Surface_mesher/include/)
|
include_directories (BEFORE ../../../Surface_mesher/include/)
|
||||||
|
include_directories (BEFORE ../../../Polyhedron/include/)
|
||||||
|
include_directories (BEFORE ../../../HalfedgeDS/include/)
|
||||||
include_directories (BEFORE ../../../Point_set_processing_3/include/)
|
include_directories (BEFORE ../../../Point_set_processing_3/include/)
|
||||||
|
|
||||||
# Include this package's headers first
|
# Include this package's headers first
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ CGAL_BEGIN_NAMESPACE
|
||||||
///
|
///
|
||||||
/// APSS reconstruction may create small "ghost" connected components
|
/// APSS reconstruction may create small "ghost" connected components
|
||||||
/// close to the reconstructed surface that you should delete with e.g.
|
/// close to the reconstructed surface that you should delete with e.g.
|
||||||
/// keep_largest_connected_components().
|
/// Polyhedron_3::keep_largest_connected_components().
|
||||||
///
|
///
|
||||||
/// @heading Is Model for the Concepts:
|
/// @heading Is Model for the Concepts:
|
||||||
/// Model of the ImplicitFunction concept.
|
/// Model of the ImplicitFunction concept.
|
||||||
|
|
|
||||||
|
|
@ -1,233 +0,0 @@
|
||||||
// Copyright (c) 2005-2009 INRIA (France).
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// This file is part of CGAL (www.cgal.org); you may redistribute it under
|
|
||||||
// the terms of the Q Public License version 1.0.
|
|
||||||
// See the file LICENSE.QPL distributed with CGAL.
|
|
||||||
//
|
|
||||||
// Licensees holding a valid commercial license may use this file in
|
|
||||||
// accordance with the commercial license agreement provided with the software.
|
|
||||||
//
|
|
||||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
||||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
//
|
|
||||||
// $URL$
|
|
||||||
// $Id$
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Author(s) : Laurent Saboret, Pierre Alliez
|
|
||||||
|
|
||||||
#ifndef CGAL_POLYHEDRON_CONNECTED_COMPONENTS_H
|
|
||||||
#define CGAL_POLYHEDRON_CONNECTED_COMPONENTS_H
|
|
||||||
|
|
||||||
#include <CGAL/Polyhedron_3.h>
|
|
||||||
#include <CGAL/point_set_processing_assertions.h>
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
CGAL_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Private section
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
namespace CGALi {
|
|
||||||
|
|
||||||
|
|
||||||
/// Possible values of a vertex tag.
|
|
||||||
enum { tag_free, tag_done };
|
|
||||||
|
|
||||||
|
|
||||||
/// Gets any vertex with tag == tag_free.
|
|
||||||
///
|
|
||||||
/// @commentheading Template Parameters:
|
|
||||||
/// @param Polyhedron an instance of CGAL::Polyhedron_3<Traits>.
|
|
||||||
///
|
|
||||||
/// @return a list of pairs (component's size (number of vertices), a vertex of the component),
|
|
||||||
/// ordered by size.
|
|
||||||
|
|
||||||
template<class Polyhedron>
|
|
||||||
typename Polyhedron::Vertex_handle
|
|
||||||
get_any_free_vertex(Polyhedron& polyhedron,
|
|
||||||
std::map<typename Polyhedron::Vertex*, int>& tags)
|
|
||||||
{
|
|
||||||
typedef typename Polyhedron::Vertex_handle Vertex_handle;
|
|
||||||
typedef typename Polyhedron::Vertex_iterator Vertex_iterator;
|
|
||||||
|
|
||||||
for (Vertex_iterator it = polyhedron.vertices_begin();
|
|
||||||
it != polyhedron.vertices_end();
|
|
||||||
it++)
|
|
||||||
{
|
|
||||||
if (tags[&*it] == tag_free)
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tag a "free" connected component as "done".
|
|
||||||
///
|
|
||||||
/// @commentheading Template Parameters:
|
|
||||||
/// @param Polyhedron an instance of CGAL::Polyhedron_3<Traits>.
|
|
||||||
///
|
|
||||||
/// @return the size (number of vertices) of the component.
|
|
||||||
template<class Polyhedron>
|
|
||||||
unsigned int tag_component(Polyhedron& polyhedron,
|
|
||||||
typename Polyhedron::Vertex_handle pSeedVertex,
|
|
||||||
std::map<typename Polyhedron::Vertex*, int>& tags)
|
|
||||||
{
|
|
||||||
typedef typename Polyhedron::Vertex_handle Vertex_handle;
|
|
||||||
typedef typename Polyhedron::Vertex_iterator Vertex_iterator;
|
|
||||||
typedef typename Polyhedron::Halfedge_around_vertex_circulator
|
|
||||||
Halfedge_around_vertex_circulator;
|
|
||||||
|
|
||||||
unsigned int number_of_vertices = 0; // size (number of vertices) of the component
|
|
||||||
|
|
||||||
std::list<Vertex_handle> vertices;
|
|
||||||
vertices.push_front(pSeedVertex);
|
|
||||||
while (!vertices.empty())
|
|
||||||
{
|
|
||||||
Vertex_handle pVertex = vertices.front();
|
|
||||||
vertices.pop_front();
|
|
||||||
|
|
||||||
// Skip vertex if already done
|
|
||||||
if (tags[&*pVertex] == tag_done)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Mark vertex done
|
|
||||||
tags[&*pVertex] = tag_done;
|
|
||||||
number_of_vertices++;
|
|
||||||
|
|
||||||
// Add vertex's "free" neighbors to the list
|
|
||||||
Halfedge_around_vertex_circulator neighbor_cir, neighbor_end;
|
|
||||||
neighbor_cir = pVertex->vertex_begin();
|
|
||||||
neighbor_end = neighbor_cir;
|
|
||||||
CGAL_For_all(neighbor_cir,neighbor_end)
|
|
||||||
{
|
|
||||||
Vertex_handle neighbor = neighbor_cir->opposite()->vertex();
|
|
||||||
if (tags[&*neighbor] == tag_free)
|
|
||||||
vertices.push_front(neighbor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return number_of_vertices;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace CGALi */
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Public section
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
/// Computes the list of all connected components of a polyhedron.
|
|
||||||
/// Returns it as a list of components ordered by size.
|
|
||||||
///
|
|
||||||
/// @commentheading Template Parameters:
|
|
||||||
/// @param Polyhedron an instance of CGAL::Polyhedron_3<Traits> that supports vertices.
|
|
||||||
/// @param OutputIterator value_type must be Polyhedron::Vertex_handle.
|
|
||||||
template<class Polyhedron,
|
|
||||||
typename OutputIterator>
|
|
||||||
void
|
|
||||||
get_polyhedron_connected_components(
|
|
||||||
Polyhedron& polyhedron, ///< input polyhedron
|
|
||||||
OutputIterator output) ///< output iterator over vertex handles
|
|
||||||
{
|
|
||||||
// Implementation note:
|
|
||||||
// We tag vertices instead of halfedges to save a factor 6.
|
|
||||||
// The drawback is that we require the Polyhedron_3<Traits> to support vertices.
|
|
||||||
// TODO: replace std::map by a property map to tag vertices.
|
|
||||||
Assert_compile_time_tag(typename Polyhedron::Supports_halfedge_vertex(), Tag_true());
|
|
||||||
std::map<typename Polyhedron::Vertex*, int> tags;
|
|
||||||
|
|
||||||
typedef typename Polyhedron::Vertex_handle Vertex_handle;
|
|
||||||
typedef typename Polyhedron::Vertex_iterator Vertex_iterator;
|
|
||||||
|
|
||||||
// list of all connected components of a polyhedron, ordered by size.
|
|
||||||
std::multimap<unsigned int, Vertex_handle> components;
|
|
||||||
|
|
||||||
// Tag all mesh vertices as "free".
|
|
||||||
for (Vertex_iterator it = polyhedron.vertices_begin();
|
|
||||||
it != polyhedron.vertices_end();
|
|
||||||
it++)
|
|
||||||
{
|
|
||||||
tags[&*it] = CGALi::tag_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Record each component
|
|
||||||
Vertex_handle seed_vertex = NULL;
|
|
||||||
while((seed_vertex = CGALi::get_any_free_vertex(polyhedron, tags)) != NULL)
|
|
||||||
{
|
|
||||||
// Tag it as "done" and compute its size (number of vertices)
|
|
||||||
unsigned int number_of_vertices = CGALi::tag_component(polyhedron, seed_vertex, tags);
|
|
||||||
|
|
||||||
// Add component to ordered list
|
|
||||||
components.insert(std::make_pair(number_of_vertices, seed_vertex));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy ordered list to output iterator
|
|
||||||
typename std::multimap<unsigned int, Vertex_handle>::iterator src;
|
|
||||||
for (src = components.begin(); src != components.end(); ++src)
|
|
||||||
*output++ = src->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Erases small connected components of a polyhedron.
|
|
||||||
///
|
|
||||||
/// @commentheading Template Parameters:
|
|
||||||
/// @param Polyhedron an instance of CGAL::Polyhedron_3<Traits> that supports
|
|
||||||
/// vertices and removal operation.
|
|
||||||
/// @param nb_components_to_keep the number of large connected components to keep.
|
|
||||||
///
|
|
||||||
/// @return the number of connected components erased.
|
|
||||||
template<class Polyhedron>
|
|
||||||
unsigned int
|
|
||||||
keep_largest_connected_components(Polyhedron& polyhedron, unsigned int nb_components_to_keep)
|
|
||||||
{
|
|
||||||
Assert_compile_time_tag(typename Polyhedron::Supports_removal(), Tag_true());
|
|
||||||
|
|
||||||
typedef typename Polyhedron::Vertex_handle Vertex_handle;
|
|
||||||
|
|
||||||
unsigned int nb_erased_components = 0,
|
|
||||||
nb_isolated_vertices = 0;
|
|
||||||
|
|
||||||
// Gets list of connected components, ordered by size (number of vertices)
|
|
||||||
std::vector<Vertex_handle> components;
|
|
||||||
CGAL::get_polyhedron_connected_components(polyhedron, std::back_inserter(components));
|
|
||||||
|
|
||||||
// Erases all connected components but the largest
|
|
||||||
while (components.size() > nb_components_to_keep)
|
|
||||||
{
|
|
||||||
Vertex_handle vertex = *(components.begin());
|
|
||||||
|
|
||||||
// Removes component from list
|
|
||||||
components.erase(components.begin());
|
|
||||||
|
|
||||||
if (vertex->halfedge() != NULL) // if not isolated vertex
|
|
||||||
{
|
|
||||||
CGAL_TRACE_STREAM << " Erases connected component\n";
|
|
||||||
polyhedron.erase_connected_component(vertex->halfedge());
|
|
||||||
nb_erased_components++;
|
|
||||||
}
|
|
||||||
else // if isolated vertex
|
|
||||||
{
|
|
||||||
// TODO: erase isolated vertices?
|
|
||||||
// Note: Polyhedron_3 does not export HalfedgeDS::vertices_erase(Vertex_handle v)
|
|
||||||
|
|
||||||
nb_isolated_vertices++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nb_isolated_vertices > 0)
|
|
||||||
CGAL_TRACE_STREAM << " Skipped " << nb_isolated_vertices << " isolated vertices\n";
|
|
||||||
|
|
||||||
return nb_erased_components;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CGAL_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // CGAL_POLYHEDRON_CONNECTED_COMPONENTS_H
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
#include <CGAL/point_set_property_map.h>
|
#include <CGAL/point_set_property_map.h>
|
||||||
#include <CGAL/IO/read_xyz_points.h>
|
#include <CGAL/IO/read_xyz_points.h>
|
||||||
#include <CGAL/IO/output_surface_facets_to_polyhedron.h>
|
#include <CGAL/IO/output_surface_facets_to_polyhedron.h>
|
||||||
#include <CGAL/keep_largest_connected_components.h>
|
|
||||||
|
|
||||||
#include "compute_normal.h"
|
#include "compute_normal.h"
|
||||||
|
|
||||||
|
|
@ -285,12 +284,12 @@ int main(int argc, char * argv[])
|
||||||
std::cerr << "Erases small connected components...\n";
|
std::cerr << "Erases small connected components...\n";
|
||||||
|
|
||||||
unsigned int nb_erased_components =
|
unsigned int nb_erased_components =
|
||||||
CGAL::keep_largest_connected_components(output_mesh, 1/* keep largest component only*/);
|
output_mesh.keep_largest_connected_components( 1 /* keep largest component only*/ );
|
||||||
|
|
||||||
// Prints status
|
// Prints status
|
||||||
/*long*/ memory = CGAL::Memory_sizer().virtual_size();
|
/*long*/ memory = CGAL::Memory_sizer().virtual_size();
|
||||||
std::cerr << "Erases small connected components: " << task_timer.time() << " seconds, "
|
std::cerr << "Erases small connected components: " << task_timer.time() << " seconds, "
|
||||||
<< nb_erased_components << " components erased, "
|
<< nb_erased_components << " component(s) erased, "
|
||||||
<< (memory>>20) << " Mb allocated"
|
<< (memory>>20) << " Mb allocated"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
task_timer.reset();
|
task_timer.reset();
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ endif(COMMAND cmake_policy)
|
||||||
|
|
||||||
# Require packages new or improved since CGAL 3.4
|
# Require packages new or improved since CGAL 3.4
|
||||||
include_directories (BEFORE ../../../Surface_mesher/include/)
|
include_directories (BEFORE ../../../Surface_mesher/include/)
|
||||||
|
include_directories (BEFORE ../../../Polyhedron/include/)
|
||||||
|
include_directories (BEFORE ../../../HalfedgeDS/include/)
|
||||||
include_directories (BEFORE ../../../Point_set_processing_3/include/)
|
include_directories (BEFORE ../../../Point_set_processing_3/include/)
|
||||||
|
|
||||||
# Include this package's headers first
|
# Include this package's headers first
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue