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, 8, 6, 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 }
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139
VertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Definition: PolyMeshT.hh:236
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115