Developer Documentation

unittests_trimesh_circulator_halfedge_loop.cc
1 #include <gtest/gtest.h>
2 #include <Unittests/unittests_common.hh>
3
4 #include <iostream>
5
6 namespace {
7
8 class OpenMeshTrimeshCirculatorHalfedgeLoop : public OpenMeshBase {
9
10 protected:
11
12 // This function is called before each test is run
13 virtual void SetUp() {
14 }
15
16 // This function is called after all tests are through
17 virtual void TearDown() {
18
19 // Do some final stuff with the member data here...
20 }
21
22
23 // Member already defined in OpenMeshBase
24 //Mesh mesh_;
25 };
26
27 /*
28 * ====================================================================
29 * Define tests below
30 * ====================================================================
31 */
32
33 /*
34 * Small HalfedgeLoop Test without holes in it
35 */
36 TEST_F(OpenMeshTrimeshCirculatorHalfedgeLoop, HalfedgeLoopWithFace) {
37
38 mesh_.clear();
39
40 // Add some vertices
41 Mesh::VertexHandle vhandle[6];
42
43 vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
44 vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
45 vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0));
46 vhandle[3] = mesh_.add_vertex(Mesh::Point(3, 0, 0));
47 vhandle[4] = mesh_.add_vertex(Mesh::Point(4, 1, 0));
48 vhandle[5] = mesh_.add_vertex(Mesh::Point(2,-1, 0));
49
50 // Add three faces
51 std::vector<Mesh::VertexHandle> face_vhandles;
52
53 face_vhandles.push_back(vhandle[0]);
54 face_vhandles.push_back(vhandle[1]);
55 face_vhandles.push_back(vhandle[2]);
56 mesh_.add_face(face_vhandles);
57
58 face_vhandles.clear();
59
60 face_vhandles.push_back(vhandle[2]);
61 face_vhandles.push_back(vhandle[1]);
62 face_vhandles.push_back(vhandle[3]);
63 mesh_.add_face(face_vhandles);
64
65 face_vhandles.clear();
66
67 face_vhandles.push_back(vhandle[2]);
68 face_vhandles.push_back(vhandle[3]);
69 face_vhandles.push_back(vhandle[4]);
70 mesh_.add_face(face_vhandles);
71
72 face_vhandles.clear();
73
74 face_vhandles.push_back(vhandle[1]);
75 face_vhandles.push_back(vhandle[5]);
76 face_vhandles.push_back(vhandle[3]);
77 mesh_.add_face(face_vhandles);
78
79 /* Test setup:
80 *
81 * edge x => halfedge x/x+1
82 * i.e. edge 0 => halfedge 0/1
83 *
84 * 0 --4--- 2 ------ 4
85 * \ / \ /
86 * 0 0 2 6 2 /
87 * \ / 1 \ /
88 * 1 ---8--- 3
89 * \ /
90 * \ 3 /
91 * \ /
92 * \ /
93 * 5
94 */
95
96 //circle around face 1
97 Mesh::HalfedgeLoopIter hl_it = mesh_.hl_begin(mesh_.halfedge_handle(3));
98 Mesh::HalfedgeLoopIter hl_end = mesh_.hl_end(mesh_.halfedge_handle(3));
99
100 EXPECT_EQ(3, hl_it->idx() ) << "Index wrong in HalfedgeLoopIter at initialization";
101 EXPECT_TRUE(hl_it.is_valid()) << "Iterator invalid in HalfedgeLoopIter at initialization";
102 ++hl_it;
103 EXPECT_EQ(6, hl_it->idx() ) << "Index wrong in HalfedgeLoopIter at step 1";
104 EXPECT_TRUE(hl_it.is_valid()) << "Iterator invalid in HalfedgeLoopIter at step 1";
105 ++hl_it;
106 EXPECT_EQ(8, hl_it->idx() ) << "Index wrong in HalfedgeLoopIter at step 2";
107 EXPECT_TRUE(hl_it.is_valid()) << "Iterator invalid in HalfedgeLoopIter at step 2";
108 ++hl_it;
109 EXPECT_EQ(3, hl_it->idx() ) << "Index wrong in HalfedgeLoopIter at step 3";
110 EXPECT_FALSE( hl_it.is_valid() ) << "Iterator invalid in HalfedgeLoopIter at end";
111 EXPECT_TRUE( hl_it == hl_end ) << "End iterator for HalfedgeLoopIter not matching";
112
113
114 //check const iterators
115 Mesh::HalfedgeLoopIter chl_it = mesh_.chl_begin(mesh_.halfedge_handle(3));
116 Mesh::HalfedgeLoopIter chl_end = mesh_.chl_end(mesh_.halfedge_handle(3));
117
118 EXPECT_EQ(3, chl_it->idx() ) << "Index wrong in ConstHalfedgeLoopIter at initialization";
119 EXPECT_TRUE(chl_it.is_valid()) << "Iterator invalid in ConstHalfedgeLoopIter at initialization";
120 ++chl_it;
121 EXPECT_EQ(6, chl_it->idx() ) << "Index wrong in ConstHalfedgeLoopIter at step 1";
122 EXPECT_TRUE(chl_it.is_valid()) << "Iterator invalid in ConstHalfedgeLoopIter at step 1";
123 ++chl_it;
124 EXPECT_EQ(8, chl_it->idx() ) << "Index wrong in ConstHalfedgeLoopIter at step 2";
125 EXPECT_TRUE(chl_it.is_valid()) << "Iterator invalid in ConstHalfedgeLoopIter at step 2";
126 ++chl_it;
127 EXPECT_EQ(3, chl_it->idx() ) << "Index wrong in ConstHalfedgeLoopIter at step 3";
128 EXPECT_FALSE( chl_it.is_valid() ) << "Iterator invalid in ConstHalfedgeLoopIter at end";
129 EXPECT_TRUE( chl_it == chl_end ) << "End iterator for ConstHalfedgeLoopIter not matching";
130
131 }
132
133
134 /*
135 * Small HalfedgeLoop Test around a boundary
136 */
137 TEST_F(OpenMeshTrimeshCirculatorHalfedgeLoop, HalfedgeLoopWithoutFace) {
138
139 mesh_.clear();
140
141 // Add some vertices
142 Mesh::VertexHandle vhandle[6];
143
144 vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
145 vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
146 vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0));
147 vhandle[3] = mesh_.add_vertex(Mesh::Point(3, 0, 0));
148 vhandle[4] = mesh_.add_vertex(Mesh::Point(4, 1, 0));
149 vhandle[5] = mesh_.add_vertex(Mesh::Point(2,-1, 0));
150
151 // Add three faces
152 std::vector<Mesh::VertexHandle> face_vhandles;
153
154 face_vhandles.push_back(vhandle[0]);
155 face_vhandles.push_back(vhandle[1]);
156 face_vhandles.push_back(vhandle[2]);
157 mesh_.add_face(face_vhandles);
158
159 face_vhandles.clear();
160
161
162 face_vhandles.push_back(vhandle[2]);
163 face_vhandles.push_back(vhandle[3]);
164 face_vhandles.push_back(vhandle[4]);
165 mesh_.add_face(face_vhandles);
166
167 face_vhandles.clear();
168
169 face_vhandles.push_back(vhandle[1]);
170 face_vhandles.push_back(vhandle[5]);
171 face_vhandles.push_back(vhandle[3]);
172 mesh_.add_face(face_vhandles);
173
174 /* Test setup:
175 *
176 * H => hole (no face)
177 * fx => face #x
178 * edge 0 => halfedge 0/1
179 *
180 * 0 --4--- 2 -10--- 4
181 * \ / \ /
182 * 0 f0 2 6 f2 8
183 * \ / H \ /
184 * 1 ---16---3
185 * \ /
186 * 12 f3 14
187 * \ /
188 * \ /
189 * 5
190 */
191
192 //circle around the hole
193 Mesh::HalfedgeLoopIter hl_it = mesh_.hl_begin(mesh_.halfedge_handle(3));
194 Mesh::HalfedgeLoopIter hl_end = mesh_.hl_end(mesh_.halfedge_handle(3));
195
196 EXPECT_EQ(3, hl_it->idx() ) << "Index wrong in HalfedgeLoopIter at initialization";
197 EXPECT_TRUE(hl_it.is_valid()) << "Iterator invalid in HalfedgeLoopIter at initialization";
198 ++hl_it;
199 EXPECT_EQ(17, hl_it->idx() ) << "Index wrong in HalfedgeLoopIter at step 1";
200 EXPECT_TRUE(hl_it.is_valid()) << "Iterator invalid in HalfedgeLoopIter at step 1";
201 ++hl_it;
202 EXPECT_EQ(7, hl_it->idx() ) << "Index wrong in HalfedgeLoopIter at step 2";
203 EXPECT_TRUE(hl_it.is_valid()) << "Iterator invalid in HalfedgeLoopIter at step 2";
204 ++hl_it;
205 EXPECT_EQ(3, hl_it->idx() ) << "Index wrong in HalfedgeLoopIter at step 3";
206 EXPECT_FALSE( hl_it.is_valid() ) << "Iterator invalid in HalfedgeLoopIter at end";
207 EXPECT_TRUE( hl_it == hl_end ) << "End iterator for HalfedgeLoopIter not matching";
208
209
210 //check const iterators
211 Mesh::HalfedgeLoopIter chl_it = mesh_.chl_begin(mesh_.halfedge_handle(3));
212 Mesh::HalfedgeLoopIter chl_end = mesh_.chl_end(mesh_.halfedge_handle(3));
213
214 EXPECT_EQ(3, chl_it->idx() ) << "Index wrong in ConstHalfedgeLoopIter at initialization";
215 EXPECT_TRUE(chl_it.is_valid()) << "Iterator invalid in ConstHalfedgeLoopIter at initialization";
216 ++chl_it;
217 EXPECT_EQ(17, chl_it->idx() ) << "Index wrong in ConstHalfedgeLoopIter at step 1";
218 EXPECT_TRUE(chl_it.is_valid()) << "Iterator invalid in ConstHalfedgeLoopIter at step 1";
219 ++chl_it;
220 EXPECT_EQ(7, chl_it->idx() ) << "Index wrong in ConstHalfedgeLoopIter at step 2";
221 EXPECT_TRUE(chl_it.is_valid()) << "Iterator invalid in ConstHalfedgeLoopIter at step 2";
222 ++chl_it;
223 EXPECT_EQ(3, chl_it->idx() ) << "Index wrong in ConstHalfedgeLoopIter at step 3";
224 EXPECT_FALSE( chl_it.is_valid() ) << "Iterator invalid in ConstHalfedgeLoopIter at end";
225 EXPECT_TRUE( chl_it == chl_end ) << "End iterator for ConstHalfedgeLoopIter not matching";
226
227 }
228
229 /*
230 * Test CW and CCW iterators
231 */
232 TEST_F(OpenMeshTrimeshCirculatorHalfedgeLoop, CWAndCCWCheck) {
233
234 mesh_.clear();
235
236 // Add some vertices
237 Mesh::VertexHandle vhandle[6];
238
239 vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
240 vhandle[1] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
241 vhandle[2] = mesh_.add_vertex(Mesh::Point(2, 1, 0));
242 vhandle[3] = mesh_.add_vertex(Mesh::Point(3, 0, 0));
243 vhandle[4] = mesh_.add_vertex(Mesh::Point(4, 1, 0));
244 vhandle[5] = mesh_.add_vertex(Mesh::Point(2,-1, 0));
245
246 // Add three faces
247 std::vector<Mesh::VertexHandle> face_vhandles;
248
249 face_vhandles.push_back(vhandle[0]);
250 face_vhandles.push_back(vhandle[1]);
251 face_vhandles.push_back(vhandle[2]);
252 mesh_.add_face(face_vhandles);
253
254 face_vhandles.clear();
255
256 face_vhandles.push_back(vhandle[2]);
257 face_vhandles.push_back(vhandle[1]);
258 face_vhandles.push_back(vhandle[3]);
259 mesh_.add_face(face_vhandles);
260
261 face_vhandles.clear();
262
263 face_vhandles.push_back(vhandle[2]);
264 face_vhandles.push_back(vhandle[3]);
265 face_vhandles.push_back(vhandle[4]);
266 mesh_.add_face(face_vhandles);
267
268 face_vhandles.clear();
269
270 face_vhandles.push_back(vhandle[1]);
271 face_vhandles.push_back(vhandle[5]);
272 face_vhandles.push_back(vhandle[3]);
273 mesh_.add_face(face_vhandles);
274
275 /* Test setup:
276 *
277 * 0 ------ 2 ------ 4
278 * \ / \ /
279 * \ 0 / \ 2 /
280 * \ / 1 \ /
281 * 1 ------- 3
282 * \ /
283 * \ 3 /
284 * \ /
285 * \ /
286 * 5
287 */
288
289
290 int indices[4] = {3, 6, 8, 3};
291 int rev_indices[4];
292 std::reverse_copy(indices,indices+4,rev_indices);
293
294 //CCW
295 Mesh::HalfedgeLoopCCWIter hl_ccwit = mesh_.hl_ccwbegin(mesh_.halfedge_handle(3));
296 Mesh::HalfedgeLoopCCWIter hl_ccwend = mesh_.hl_ccwend(mesh_.halfedge_handle(3));
297 size_t i = 0;
298 for (;hl_ccwit != hl_ccwend; ++hl_ccwit, ++i)
299 {
300 EXPECT_EQ(indices[i], hl_ccwit->idx()) << "Index wrong in HalfedgeLoopCCWIter";
301 }
302
303 EXPECT_FALSE(hl_ccwit.is_valid()) << "Iterator invalid in HalfedgeLoopCCWIter at end";
304 EXPECT_TRUE( hl_ccwit == hl_ccwend ) << "End iterator for HalfedgeLoopCCWIter not matching";
305
306 //constant CCW
307 Mesh::ConstHalfedgeLoopCCWIter chl_ccwit = mesh_.chl_ccwbegin(mesh_.halfedge_handle(3));
308 Mesh::ConstHalfedgeLoopCCWIter chl_ccwend = mesh_.chl_ccwend(mesh_.halfedge_handle(3));
309 i = 0;
310 for (;chl_ccwit != chl_ccwend; ++chl_ccwit, ++i)
311 {
312 EXPECT_EQ(indices[i], chl_ccwit->idx()) << "Index wrong in ConstHalfedgeLoopCCWIter";
313 }
314
315 EXPECT_FALSE(chl_ccwit.is_valid()) << "Iterator invalid in ConstHalfedgeLoopCCWIter at end";
316 EXPECT_TRUE( chl_ccwit == chl_ccwend ) << "End iterator for ConstHalfedgeLoopCCWIter not matching";
317
318 //CW
319 Mesh::HalfedgeLoopCWIter hl_cwit = mesh_.hl_cwbegin(mesh_.halfedge_handle(3));
320 Mesh::HalfedgeLoopCWIter hl_cwend = mesh_.hl_cwend(mesh_.halfedge_handle(3));
321 i = 0;
322 for (;hl_cwit != hl_cwend; ++hl_cwit, ++i)
323 {
324 EXPECT_EQ(rev_indices[i], hl_cwit->idx()) << "Index wrong in HalfedgeLoopCWIter";
325 }
326 EXPECT_FALSE(hl_cwit.is_valid()) << "Iterator invalid in HalfedgeLoopCWIter at end";
327 EXPECT_TRUE( hl_cwit == hl_cwend ) << "End iterator for HalfedgeLoopCWIter not matching";
328
329 //constant CW
330 Mesh::ConstHalfedgeLoopCWIter chl_cwit = mesh_.chl_cwbegin(mesh_.halfedge_handle(3));
331 Mesh::ConstHalfedgeLoopCWIter chl_cwend = mesh_.chl_cwend(mesh_.halfedge_handle(3));
332 i = 0;
333 for (;chl_cwit != chl_cwend; ++chl_cwit, ++i)
334 {
335 EXPECT_EQ(rev_indices[i], chl_cwit->idx()) << "Index wrong in ConstHalfedgeLoopCWIter";
336 }
337 EXPECT_FALSE(chl_cwit.is_valid()) << "Iterator invalid in ConstHalfedgeLoopCWIter at end";
338 EXPECT_TRUE( chl_cwit == chl_cwend ) << "End iterator for ConstHalfedgeLoopCWIter not matching";
339
340 /*
341 * conversion properties:
342 * a) cw_begin == CWIter(ccw_begin())
343 * b) cw_iter->idx() == CCWIter(cw_iter)->idx() for valid iterators
344 * c) --cw_iter == CWIter(++ccwIter) for valid iterators
345 * d) cw_end == CWIter(ccw_end()) => --cw_end != CWIter(++ccw_end()) *
346 */
347 Mesh::HalfedgeLoopCWIter hl_cwIter = mesh_.hl_cwbegin(mesh_.halfedge_handle(3));
348 // a)
349 EXPECT_TRUE( hl_cwIter == Mesh::HalfedgeLoopCWIter(mesh_.hl_ccwbegin(mesh_.halfedge_handle(3))) ) << "ccw to cw conversion failed";
350 EXPECT_TRUE( Mesh::HalfedgeLoopCCWIter(hl_cwIter) == mesh_.hl_ccwbegin(mesh_.halfedge_handle(3)) ) << "cw to ccw conversion failed";
351 // b)
352 EXPECT_EQ( hl_cwIter->idx(), Mesh::HalfedgeLoopCCWIter(hl_cwIter)->idx()) << "iterators doesnt point on the same element";
353 // c)
354 ++hl_cwIter;
355 hl_ccwend = mesh_.hl_ccwend(mesh_.halfedge_handle(3));
356 --hl_ccwend;
357 EXPECT_EQ(hl_cwIter->idx(),hl_ccwend->idx()) << "iteratoes are not equal after inc/dec";
358 // additional conversion check
359 hl_ccwend = Mesh::HalfedgeLoopCCWIter(hl_cwIter);
360 EXPECT_EQ(hl_cwIter->idx(),hl_ccwend->idx())<< "iterators doesnt point on the same element";
361 // d)
362 hl_cwIter = Mesh::HalfedgeLoopCWIter(mesh_.hl_ccwend(mesh_.halfedge_handle(3)));
363 EXPECT_FALSE(hl_cwIter.is_valid()) << "end iterator is not invalid";
364 EXPECT_TRUE(Mesh::HalfedgeLoopCCWIter(mesh_.hl_cwend(mesh_.halfedge_handle(3))) == mesh_.hl_ccwend(mesh_.halfedge_handle(3))) << "end iterators are not equal";
365
366
367 }
368
369 }
OpenMesh::PolyMeshT::Point
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
OpenMesh::PolyMeshT::add_vertex
SmartVertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Definition: PolyMeshT.hh:235
OpenMeshBase
Definition: unittests_common.hh:29
OpenMesh::PolyMeshT::VertexHandle
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136