Developer Documentation
MeshCheckerT.cc
1 /* ========================================================================= *
2  * *
3  * OpenMesh *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openmesh.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenMesh. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40  * ========================================================================= */
41 
42 /*===========================================================================*\
43  * *
44  * $Revision$ *
45  * $Date$ *
46  * *
47 \*===========================================================================*/
48 
49 
50 #define OPENMESH_MESHCHECKER_C
51 
52 
53 //== INCLUDES =================================================================
54 
55 
56 #include <OpenMesh/Tools/Utils/MeshCheckerT.hh>
57 
58 
59 //== NAMESPACES ==============================================================
60 
61 
62 namespace OpenMesh {
63 namespace Utils {
64 
65 //== IMPLEMENTATION ==========================================================
66 
67 
68 template <class Mesh>
69 bool
71 check(unsigned int _targets, std::ostream& _os)
72 {
73  bool ok(true);
74 
75 
76 
77  //--- vertex checks ---
78 
79  if (_targets & CHECK_VERTICES)
80  {
81  typename Mesh::ConstVertexIter v_it(mesh_.vertices_begin()), v_end(mesh_.vertices_end());
82  typename Mesh::VertexHandle vh;
83  typename Mesh::ConstVertexVertexCWIter vv_it;
84  typename Mesh::HalfedgeHandle heh;
85  unsigned int count;
86  const unsigned int max_valence(10000);
87 
88 
89  for (; v_it != v_end; ++v_it)
90  {
91  if (!is_deleted(*v_it))
92  {
93  vh = *v_it;
94 
95 
96  /* The outgoing halfedge of a boundary vertex has to be a boundary halfedge */
97  heh = mesh_.halfedge_handle(vh);
98  if (heh.is_valid() && !mesh_.is_boundary(heh))
99  {
100  for (typename Mesh::ConstVertexOHalfedgeIter vh_it(mesh_, vh);
101  vh_it.is_valid(); ++vh_it)
102  {
103  if (mesh_.is_boundary(*vh_it))
104  {
105  _os << "MeshChecker: vertex " << vh
106  << ": outgoing halfedge not on boundary error\n";
107  ok = false;
108  }
109  }
110  }
111 
112 
113 
114  // outgoing halfedge has to refer back to vertex
115  if (mesh_.halfedge_handle(vh).is_valid() &&
116  mesh_.from_vertex_handle(mesh_.halfedge_handle(vh)) != vh)
117  {
118  _os << "MeshChecker: vertex " << vh
119  << ": outgoing halfedge does not reference vertex\n";
120  ok = false;
121  }
122 
123 
124  // check whether circulators are still in order
125  vv_it = mesh_.cvv_cwiter(vh);
126  for (count=0; vv_it.is_valid() && (count < max_valence); ++vv_it, ++count) {};
127  if (count == max_valence)
128  {
129  _os << "MeshChecker: vertex " << vh
130  << ": ++circulator problem, one ring corrupt\n";
131  ok = false;
132  }
133  vv_it = mesh_.cvv_cwiter(vh);
134  for (count=0; vv_it.is_valid() && (count < max_valence); --vv_it, ++count) {};
135  if (count == max_valence)
136  {
137  _os << "MeshChecker: vertex " << vh
138  << ": --circulator problem, one ring corrupt\n";
139  ok = false;
140  }
141  }
142  }
143  }
144 
145 
146 
147  //--- halfedge checks ---
148 
149  if (_targets & CHECK_EDGES)
150  {
151  typename Mesh::ConstHalfedgeIter h_it(mesh_.halfedges_begin()),
152  h_end(mesh_.halfedges_end());
153  typename Mesh::HalfedgeHandle hh, hstart, hhh;
154  size_t count, n_halfedges = 2*mesh_.n_edges();
155 
156  for (; h_it != h_end; ++h_it)
157  {
158  if (!is_deleted(mesh_.edge_handle(*h_it)))
159  {
160  hh = *h_it;
161 
162 
163  // degenerated halfedge ?
164  if (mesh_.from_vertex_handle(hh) == mesh_.to_vertex_handle(hh))
165  {
166  _os << "MeshChecker: halfedge " << hh
167  << ": to-vertex == from-vertex\n";
168  ok = false;
169  }
170 
171 
172  // next <-> prev check
173  if (mesh_.next_halfedge_handle(mesh_.prev_halfedge_handle(hh)) != hh)
174  {
175  _os << "MeshChecker: halfedge " << hh
176  << ": prev->next != this\n";
177  ok = false;
178  }
179 
180 
181  // halfedges should form a cycle
182  count=0; hstart=hhh=hh;
183  do
184  {
185  hhh = mesh_.next_halfedge_handle(hhh);
186  ++count;
187  } while (hhh != hstart && count < n_halfedges);
188 
189  if (count == n_halfedges)
190  {
191  _os << "MeshChecker: halfedges starting from " << hh
192  << " do not form a cycle\n";
193  ok = false;
194  }
195  }
196  }
197  }
198 
199 
200 
201  //--- face checks ---
202 
203  if (_targets & CHECK_FACES)
204  {
205  typename Mesh::ConstFaceIter f_it(mesh_.faces_begin()),
206  f_end(mesh_.faces_end());
207  typename Mesh::FaceHandle fh;
208  typename Mesh::ConstFaceHalfedgeIter fh_it;
209 
210  for (; f_it != f_end; ++f_it)
211  {
212  if (!is_deleted(*f_it))
213  {
214  fh = *f_it;
215 
216  for (fh_it=mesh_.cfh_iter(fh); fh_it.is_valid(); ++fh_it)
217  {
218  if (mesh_.face_handle(*fh_it) != fh)
219  {
220  _os << "MeshChecker: face " << fh
221  << ": its halfedge does not reference face\n";
222  ok = false;
223  }
224  }
225  }
226  }
227  }
228 
229 
230 
231  return ok;
232 }
233 
234 
235 //=============================================================================
236 } // naespace Utils
237 } // namespace OpenMesh
238 //=============================================================================
Kernel::ConstFaceHalfedgeIter ConstFaceHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:181
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139
bool check(unsigned int _targets=CHECK_ALL, std::ostream &_os=omerr())
check it, return true iff ok
Definition: MeshCheckerT.cc:71
Kernel::ConstVertexOHalfedgeIter ConstVertexOHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:176