Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
70 MeshCheckerT<Mesh>::
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 //=============================================================================
OpenMesh::Utils::MeshCheckerT::check
bool check(unsigned int _targets=CHECK_ALL, std::ostream &_os=omerr())
check it, return true iff ok
Definition: MeshCheckerT.cc:71
OpenMesh::PolyMeshT::ConstVertexOHalfedgeIter
Kernel::ConstVertexOHalfedgeIter ConstVertexOHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:176
OpenMesh
Definition: MeshItems.hh:64
OpenMesh::PolyMeshT::ConstFaceHalfedgeIter
Kernel::ConstFaceHalfedgeIter ConstFaceHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:181
Utils
Definition: NumberParsing.cc:54
OpenMesh::PolyMeshT::VertexHandle
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139