Developer Documentation
MeshCheckerT_impl.hh
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 
45 #define OPENMESH_MESHCHECKER_C
46 
47 
48 //== INCLUDES =================================================================
49 
50 
51 #include <OpenMesh/Tools/Utils/MeshCheckerT.hh>
52 
53 
54 //== NAMESPACES ==============================================================
55 
56 
57 namespace OpenMesh {
58 namespace Utils {
59 
60 //== IMPLEMENTATION ==========================================================
61 
62 
63 template <class Mesh>
64 bool
66 check(unsigned int _targets, std::ostream& _os)
67 {
68  bool ok(true);
69 
70 
71 
72  //--- vertex checks ---
73 
74  if (_targets & CHECK_VERTICES)
75  {
76  typename Mesh::ConstVertexIter v_it(mesh_.vertices_begin()), v_end(mesh_.vertices_end());
77  typename Mesh::VertexHandle vh;
78  typename Mesh::ConstVertexVertexCWIter vv_it;
79  typename Mesh::HalfedgeHandle heh;
80  unsigned int count;
81  const unsigned int max_valence(10000);
82 
83 
84  for (; v_it != v_end; ++v_it)
85  {
86  if (!is_deleted(*v_it))
87  {
88  vh = *v_it;
89 
90 
91  /* The outgoing halfedge of a boundary vertex has to be a boundary halfedge */
92  heh = mesh_.halfedge_handle(vh);
93  if (heh.is_valid() && !mesh_.is_boundary(heh))
94  {
95  for (typename Mesh::ConstVertexOHalfedgeIter vh_it(mesh_, vh);
96  vh_it.is_valid(); ++vh_it)
97  {
98  if (mesh_.is_boundary(*vh_it))
99  {
100  _os << "MeshChecker: vertex " << vh
101  << ": outgoing halfedge not on boundary error\n";
102  ok = false;
103  }
104  }
105  }
106 
107 
108 
109  // outgoing halfedge has to refer back to vertex
110  if (mesh_.halfedge_handle(vh).is_valid() &&
111  mesh_.from_vertex_handle(mesh_.halfedge_handle(vh)) != vh)
112  {
113  _os << "MeshChecker: vertex " << vh
114  << ": outgoing halfedge does not reference vertex\n";
115  ok = false;
116  }
117 
118 
119  // check whether circulators are still in order
120  vv_it = mesh_.cvv_cwiter(vh);
121  for (count=0; vv_it.is_valid() && (count < max_valence); ++vv_it, ++count) {};
122  if (count == max_valence)
123  {
124  _os << "MeshChecker: vertex " << vh
125  << ": ++circulator problem, one ring corrupt\n";
126  ok = false;
127  }
128  vv_it = mesh_.cvv_cwiter(vh);
129  for (count=0; vv_it.is_valid() && (count < max_valence); --vv_it, ++count) {};
130  if (count == max_valence)
131  {
132  _os << "MeshChecker: vertex " << vh
133  << ": --circulator problem, one ring corrupt\n";
134  ok = false;
135  }
136  }
137  }
138  }
139 
140 
141 
142  //--- halfedge checks ---
143 
144  if (_targets & CHECK_EDGES)
145  {
146  typename Mesh::ConstHalfedgeIter h_it(mesh_.halfedges_begin()),
147  h_end(mesh_.halfedges_end());
148  typename Mesh::HalfedgeHandle hh, hstart, hhh;
149  size_t count, n_halfedges = 2*mesh_.n_edges();
150 
151  for (; h_it != h_end; ++h_it)
152  {
153  if (!is_deleted(mesh_.edge_handle(*h_it)))
154  {
155  hh = *h_it;
156 
157 
158  // degenerated halfedge ?
159  if (mesh_.from_vertex_handle(hh) == mesh_.to_vertex_handle(hh))
160  {
161  _os << "MeshChecker: halfedge " << hh
162  << ": to-vertex == from-vertex\n";
163  ok = false;
164  }
165 
166 
167  // next <-> prev check
168  if (mesh_.next_halfedge_handle(mesh_.prev_halfedge_handle(hh)) != hh)
169  {
170  _os << "MeshChecker: halfedge " << hh
171  << ": prev->next != this\n";
172  ok = false;
173  }
174 
175 
176  // halfedges should form a cycle
177  count=0; hstart=hhh=hh;
178  do
179  {
180  hhh = mesh_.next_halfedge_handle(hhh);
181  ++count;
182  } while (hhh != hstart && count < n_halfedges);
183 
184  if (count == n_halfedges)
185  {
186  _os << "MeshChecker: halfedges starting from " << hh
187  << " do not form a cycle\n";
188  ok = false;
189  }
190  }
191  }
192  }
193 
194 
195 
196  //--- face checks ---
197 
198  if (_targets & CHECK_FACES)
199  {
200  typename Mesh::ConstFaceIter f_it(mesh_.faces_begin()),
201  f_end(mesh_.faces_end());
202  typename Mesh::FaceHandle fh;
203  typename Mesh::ConstFaceHalfedgeIter fh_it;
204 
205  for (; f_it != f_end; ++f_it)
206  {
207  if (!is_deleted(*f_it))
208  {
209  fh = *f_it;
210 
211  for (fh_it=mesh_.cfh_iter(fh); fh_it.is_valid(); ++fh_it)
212  {
213  if (mesh_.face_handle(*fh_it) != fh)
214  {
215  _os << "MeshChecker: face " << fh
216  << ": its halfedge does not reference face\n";
217  ok = false;
218  }
219  }
220  }
221  }
222  }
223 
224 
225 
226  return ok;
227 }
228 
229 
230 //=============================================================================
231 } // naespace Utils
232 } // namespace OpenMesh
233 //=============================================================================
bool check(unsigned int _targets=CHECK_ALL, std::ostream &_os=omerr())
check it, return true iff ok
Kernel::ConstFaceHalfedgeIter ConstFaceHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:178
Kernel::ConstVertexOHalfedgeIter ConstVertexOHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:173
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136