Developer Documentation
unittests_read_write_OM.cc
1 #include <gtest/gtest.h>
2 #include <Unittests/unittests_common.hh>
3 
4 
5 namespace {
6 
7 class OpenMeshReadWriteOM : public OpenMeshBase {
8 
9  protected:
10 
11  // This function is called before each test is run
12  virtual void SetUp() {
13 
14  // Do some initial stuff with the member data here...
15  }
16 
17  // This function is called after all tests are through
18  virtual void TearDown() {
19 
20  // Do some final stuff with the member data here...
21  }
22 
23  // Member already defined in OpenMeshBase
24  //Mesh mesh_;
25 };
26 
27 /*
28  * ====================================================================
29  * Define tests below
30  * ====================================================================
31  */
32 
33 /*
34  * Just load an om file and set vertex color option before loading
35  */
36 TEST_F(OpenMeshReadWriteOM, LoadSimpleOMForceVertexColorsAlthoughNotAvailable) {
37 
38  mesh_.clear();
39 
40  mesh_.request_vertex_colors();
41 
42  std::string file_name = "cube-minimal.om";
43 
44  OpenMesh::IO::Options options;
46 
47  bool ok = OpenMesh::IO::read_mesh(mesh_, file_name,options);
48 
49  EXPECT_TRUE(ok) << file_name;
50 
51  EXPECT_EQ(8u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
52  EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
53  EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
54  EXPECT_EQ(36u , mesh_.n_halfedges()) << "The number of loaded halfedges is not correct!";
55 
56  EXPECT_FALSE(options.vertex_has_normal()) << "Wrong user options are returned!";
57  EXPECT_FALSE(options.vertex_has_texcoord()) << "Wrong user options are returned!";
58  EXPECT_FALSE(options.vertex_has_color()) << "Wrong user options are returned!";
59 }
60 
61 /*
62  * Just load an om file of a cube with vertex texCoords
63  */
64 TEST_F(OpenMeshReadWriteOM, LoadSimpleOMWithTexCoords) {
65 
66  mesh_.clear();
67 
68  mesh_.request_vertex_texcoords2D();
69 
70  OpenMesh::IO::Options options;
72 
73  bool ok = OpenMesh::IO::read_mesh(mesh_, "cube-minimal-texCoords.om",options);
74 
75  ASSERT_TRUE(ok) << "Unable to load cube-minimal-texCoords.om";
76 
77  EXPECT_EQ(8u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
78  EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
79  EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
80 
81  EXPECT_EQ(10, mesh_.texcoord2D(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
82  EXPECT_EQ(10, mesh_.texcoord2D(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
83 
84  EXPECT_EQ(6, mesh_.texcoord2D(mesh_.vertex_handle(2))[0] ) << "Wrong vertex color at vertex 2 component 0";
85  EXPECT_EQ(6, mesh_.texcoord2D(mesh_.vertex_handle(2))[1] ) << "Wrong vertex color at vertex 2 component 1";
86 
87  EXPECT_EQ(9, mesh_.texcoord2D(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
88  EXPECT_EQ(9, mesh_.texcoord2D(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
89 
90  EXPECT_EQ(12, mesh_.texcoord2D(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
91  EXPECT_EQ(12, mesh_.texcoord2D(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
92 
93 
94  EXPECT_FALSE(options.vertex_has_normal()) << "Wrong user options are returned!";
95  EXPECT_TRUE(options.vertex_has_texcoord()) << "Wrong user options are returned!";
96  EXPECT_FALSE(options.vertex_has_color()) << "Wrong user options are returned!";
97 
98  mesh_.release_vertex_texcoords2D();
99 }
100 
101 /*
102  * Just load an om file of a cube with vertex colors
103  */
104 TEST_F(OpenMeshReadWriteOM, LoadSimpleOMWithVertexColors) {
105 
106  mesh_.clear();
107 
108  mesh_.request_vertex_colors();
109 
110  OpenMesh::IO::Options options;
112 
113  bool ok = OpenMesh::IO::read_mesh(mesh_, "cube-minimal-vertexColors.om",options);
114 
115  EXPECT_TRUE(ok) << "Unable to load cube-minimal-vertexColors.om";
116 
117  EXPECT_EQ(8u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
118  EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
119  EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
120 
121  EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
122  EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
123  EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";
124 
125  EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
126  EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
127  EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";
128 
129  EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
130  EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
131  EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";
132 
133  EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
134  EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
135  EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";
136 
137  EXPECT_FALSE(options.vertex_has_normal()) << "Wrong user options are returned!";
138  EXPECT_FALSE(options.vertex_has_texcoord()) << "Wrong user options are returned!";
139  EXPECT_TRUE(options.vertex_has_color()) << "Wrong user options are returned!";
140 
141  mesh_.release_vertex_colors();
142 }
143 
144 /*
145  * Save and load simple mesh
146  */
147 TEST_F(OpenMeshReadWriteOM, WriteTriangle) {
148 
149  Mesh mesh;
150  mesh.clear();
151 
152  const std::string filename = "triangle-minimal.om";
153 
154  // generate data
155  Mesh::VertexHandle v1 = mesh.add_vertex(Mesh::Point(1.0,0.0,0.0));
156  Mesh::VertexHandle v2 = mesh.add_vertex(Mesh::Point(0.0,1.0,0.0));
157  Mesh::VertexHandle v3 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
158  mesh.add_face(v1,v2,v3);
159 
160  // save
161  bool ok = OpenMesh::IO::write_mesh(mesh,filename);
162  EXPECT_TRUE(ok) << "Unable to write " << filename;
163 
164  // reset
165  mesh.clear();
166 
167  // load
168  ok = OpenMesh::IO::read_mesh(mesh,filename);
169  EXPECT_TRUE(ok) << "Unable to read " << filename;
170 
171  // compare
172  EXPECT_EQ(3u , mesh.n_vertices()) << "The number of loaded vertices is not correct!";
173  EXPECT_EQ(3u , mesh.n_edges()) << "The number of loaded edges is not correct!";
174  EXPECT_EQ(1u , mesh.n_faces()) << "The number of loaded faces is not correct!";
175 
176  EXPECT_EQ(Mesh::Point(1.0,0.0,0.0) , mesh.point(v1)) << "Wrong coordinates at vertex 0";
177  EXPECT_EQ(Mesh::Point(0.0,1.0,0.0) , mesh.point(v2)) << "Wrong coordinates at vertex 1";
178  EXPECT_EQ(Mesh::Point(0.0,0.0,1.0) , mesh.point(v3)) << "Wrong coordinates at vertex 2";
179 
180  // cleanup
181  remove(filename.c_str());
182 
183 }
184 
185 /*
186  * Save and load simple mesh with integer colors per vertex
187  */
188 TEST_F(OpenMeshReadWriteOM, WriteTriangleVertexIntegerColor) {
189 
190  Mesh mesh;
191 
192  mesh.request_vertex_colors();
193 
194  OpenMesh::IO::Options options;
197 
198  const std::string filename = "triangle-minimal-ColorsPerVertex.om";
199 
200  // generate data
201  Mesh::VertexHandle v1 = mesh.add_vertex(Mesh::Point(1.0,0.0,0.0));
202  Mesh::VertexHandle v2 = mesh.add_vertex(Mesh::Point(0.0,1.0,0.0));
203  Mesh::VertexHandle v3 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
204  mesh.add_face(v1,v2,v3);
205 
206  Mesh::Color c1 = Mesh::Color(0,0,123),
207  c2 = Mesh::Color(21,0,0),
208  c3 = Mesh::Color(0,222,0);
209 
210  mesh.set_color(v1,c1);
211  mesh.set_color(v2,c2);
212  mesh.set_color(v3,c3);
213 
214  // save
215  bool ok = OpenMesh::IO::write_mesh(mesh,filename,options);
216  EXPECT_TRUE(ok) << "Unable to write "<<filename;
217 
218  mesh.release_vertex_colors();
219 
220  // load
221  Mesh cmpMesh;
222  cmpMesh.request_vertex_colors();
223  ok = OpenMesh::IO::read_mesh(cmpMesh,filename,options);
224  EXPECT_TRUE(ok) << "Unable to read "<<filename;
225 
226  EXPECT_TRUE(cmpMesh.has_vertex_colors()) << "Loaded mesh has no vertex colors.";
227 
228  // compare
229  EXPECT_EQ(3u , cmpMesh.n_vertices()) << "The number of loaded vertices is not correct!";
230  EXPECT_EQ(3u , cmpMesh.n_edges()) << "The number of loaded edges is not correct!";
231  EXPECT_EQ(1u , cmpMesh.n_faces()) << "The number of loaded faces is not correct!";
232 
233  EXPECT_EQ(Mesh::Point(1.0,0.0,0.0) , cmpMesh.point(v1)) << "Wrong coordinates at vertex 0";
234  EXPECT_EQ(Mesh::Point(0.0,1.0,0.0) , cmpMesh.point(v2)) << "Wrong coordinates at vertex 1";
235  EXPECT_EQ(Mesh::Point(0.0,0.0,1.0) , cmpMesh.point(v3)) << "Wrong coordinates at vertex 2";
236 
237  EXPECT_EQ(c1 , cmpMesh.color(v1)) << "Wrong colors at vertex 0";
238  EXPECT_EQ(c2 , cmpMesh.color(v2)) << "Wrong colors at vertex 1";
239  EXPECT_EQ(c3 , cmpMesh.color(v3)) << "Wrong colors at vertex 2";
240 
241  //clean up
242  cmpMesh.release_vertex_colors();
243  remove(filename.c_str());
244 
245 }
246 
247 /*
248  * Save and load simple mesh with custom property
249  */
250 TEST_F(OpenMeshReadWriteOM, WriteTriangleVertexBoolProperty) {
251 
252  Mesh mesh;
253 
254  const std::string filename = "triangle-minimal-VBProp.om";
255 
256  // generate data
257  Mesh::VertexHandle v1 = mesh.add_vertex(Mesh::Point(1.0,0.0,0.0));
258  Mesh::VertexHandle v2 = mesh.add_vertex(Mesh::Point(0.0,1.0,0.0));
259  Mesh::VertexHandle v3 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
260  mesh.add_face(v1,v2,v3);
261 
263  mesh.add_property(prop,"VBProp");
264  mesh.property(prop).set_persistent(true);
265 
266  mesh.property(prop,v1) = true;
267  mesh.property(prop,v2) = false;
268  mesh.property(prop,v3) = true;
269 
270  // save
271  bool ok = OpenMesh::IO::write_mesh(mesh,filename);
272  EXPECT_TRUE(ok) << "Unable to write "<<filename;
273 
274  // load
275  Mesh cmpMesh;
276 
277 
278  cmpMesh.add_property(prop,"VBProp");
279  cmpMesh.property(prop).set_persistent(true);
280 
281  ok = OpenMesh::IO::read_mesh(cmpMesh,filename);
282  EXPECT_TRUE(ok) << "Unable to read "<<filename;
283 
284  // compare
285  EXPECT_EQ(3u , cmpMesh.n_vertices()) << "The number of loaded vertices is not correct!";
286  EXPECT_EQ(3u , cmpMesh.n_edges()) << "The number of loaded edges is not correct!";
287  EXPECT_EQ(1u , cmpMesh.n_faces()) << "The number of loaded faces is not correct!";
288 
289  EXPECT_EQ(Mesh::Point(1.0,0.0,0.0) , cmpMesh.point(v1)) << "Wrong coordinates at vertex 0";
290  EXPECT_EQ(Mesh::Point(0.0,1.0,0.0) , cmpMesh.point(v2)) << "Wrong coordinates at vertex 1";
291  EXPECT_EQ(Mesh::Point(0.0,0.0,1.0) , cmpMesh.point(v3)) << "Wrong coordinates at vertex 2";
292 
293  EXPECT_TRUE(cmpMesh.property(prop,v1)) << "Wrong Property value at vertex 0";
294  EXPECT_FALSE(cmpMesh.property(prop,v2)) << "Wrong Property value at vertex 1";
295  EXPECT_TRUE(cmpMesh.property(prop,v3)) << "Wrong Property value at vertex 2";
296 
297  // cleanup
298  remove(filename.c_str());
299 
300 }
301 
302 /*
303  * Save and load simple mesh with custom property
304  */
305 TEST_F(OpenMeshReadWriteOM, WriteTriangleVertexBoolPropertySpaceEquivalent) {
306 
307  Mesh mesh;
308 
309  const std::string filename = "triangle-minimal-VBProp-pattern-test.om";
310 
311  // generate data
312  Mesh::VertexHandle v1 = mesh.add_vertex(Mesh::Point(1.0,0.0,0.0));
313  Mesh::VertexHandle v2 = mesh.add_vertex(Mesh::Point(0.0,1.0,0.0));
314  Mesh::VertexHandle v3 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
315  mesh.add_face(v1,v2,v3);
316 
317  Mesh::VertexHandle v4 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
318  Mesh::VertexHandle v5 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
319  Mesh::VertexHandle v6 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
320  mesh.add_face(v4,v5,v6);
321 
322  Mesh::VertexHandle v7 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
323  Mesh::VertexHandle v8 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
324  Mesh::VertexHandle v9 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
325 
327  mesh.add_property(prop,"VBProp");
328  mesh.property(prop).set_persistent(true);
329 
330  // Create a 0x20 hex pattern in the bitset
331  mesh.property(prop,v1) = false;
332  mesh.property(prop,v2) = false;
333  mesh.property(prop,v3) = false;
334  mesh.property(prop,v4) = false;
335  mesh.property(prop,v5) = false;
336  mesh.property(prop,v6) = true;
337  mesh.property(prop,v7) = false;
338  mesh.property(prop,v8) = false;
339  mesh.property(prop,v9) = true;
340 
341  // save
342  bool ok = OpenMesh::IO::write_mesh(mesh,filename);
343  EXPECT_TRUE(ok) << "Unable to write "<<filename;
344 
345  // load
346  Mesh cmpMesh;
347 
348  cmpMesh.add_property(prop,"VBProp");
349  cmpMesh.property(prop).set_persistent(true);
350 
351  ok = OpenMesh::IO::read_mesh(cmpMesh,filename);
352  EXPECT_TRUE(ok) << "Unable to read "<<filename;
353 
354  // compare
355  EXPECT_EQ(9u , cmpMesh.n_vertices()) << "The number of loaded vertices is not correct!";
356  EXPECT_EQ(6u , cmpMesh.n_edges()) << "The number of loaded edges is not correct!";
357  EXPECT_EQ(2u , cmpMesh.n_faces()) << "The number of loaded faces is not correct!";
358 
359  EXPECT_FALSE(cmpMesh.property(prop,v1)) << "Wrong Property value at vertex 0";
360  EXPECT_FALSE(cmpMesh.property(prop,v2)) << "Wrong Property value at vertex 1";
361  EXPECT_FALSE(cmpMesh.property(prop,v3)) << "Wrong Property value at vertex 2";
362  EXPECT_FALSE(cmpMesh.property(prop,v4)) << "Wrong Property value at vertex 3";
363  EXPECT_FALSE(cmpMesh.property(prop,v5)) << "Wrong Property value at vertex 4";
364  EXPECT_TRUE(cmpMesh.property(prop,v6)) << "Wrong Property value at vertex 5";
365  EXPECT_FALSE(cmpMesh.property(prop,v7)) << "Wrong Property value at vertex 6";
366  EXPECT_FALSE(cmpMesh.property(prop,v8)) << "Wrong Property value at vertex 7";
367  EXPECT_TRUE(cmpMesh.property(prop,v9)) << "Wrong Property value at vertex 8";
368 
369  // cleanup
370  remove(filename.c_str());
371 
372 }
373 
374 /*
375  * Save and load simple mesh with multiple custom property
376  */
377 TEST_F(OpenMeshReadWriteOM, WriteTriangleTwoVertexBoolProperty) {
378 
379  Mesh mesh;
380 
381  const std::string filename = "triangle-minimal-VBProp.om";
382 
383  // generate data
384  Mesh::VertexHandle v1 = mesh.add_vertex(Mesh::Point(1.0,0.0,0.0));
385  Mesh::VertexHandle v2 = mesh.add_vertex(Mesh::Point(0.0,1.0,0.0));
386  Mesh::VertexHandle v3 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
387  mesh.add_face(v1,v2,v3);
388 
390  mesh.add_property(prop,"VBProp");
391  mesh.property(prop).set_persistent(true);
392 
393  mesh.property(prop,v1) = true;
394  mesh.property(prop,v2) = false;
395  mesh.property(prop,v3) = true;
396 
398  mesh.add_property(prop2,"VBProp2");
399  mesh.property(prop2).set_persistent(true);
400 
401  mesh.property(prop2,v1) = false;
402  mesh.property(prop2,v2) = false;
403  mesh.property(prop2,v3) = false;
404 
405  // save
406  bool ok = OpenMesh::IO::write_mesh(mesh,filename);
407  EXPECT_TRUE(ok) << "Unable to write "<<filename;
408 
409 
410  // load
411  Mesh cmpMesh;
412  cmpMesh.add_property(prop,"VBProp");
413  cmpMesh.property(prop).set_persistent(true);
414 
415  cmpMesh.add_property(prop2,"VBProp2");
416  cmpMesh.property(prop2).set_persistent(true);
417 
418  ok = OpenMesh::IO::read_mesh(cmpMesh,filename);
419  EXPECT_TRUE(ok) << "Unable to read "<<filename;
420 
421  // compare
422  EXPECT_EQ(3u , cmpMesh.n_vertices()) << "The number of loaded vertices is not correct!";
423  EXPECT_EQ(3u , cmpMesh.n_edges()) << "The number of loaded edges is not correct!";
424  EXPECT_EQ(1u , cmpMesh.n_faces()) << "The number of loaded faces is not correct!";
425 
426  EXPECT_EQ(Mesh::Point(1.0,0.0,0.0) , cmpMesh.point(v1)) << "Wrong coordinates at vertex 0";
427  EXPECT_EQ(Mesh::Point(0.0,1.0,0.0) , cmpMesh.point(v2)) << "Wrong coordinates at vertex 1";
428  EXPECT_EQ(Mesh::Point(0.0,0.0,1.0) , cmpMesh.point(v3)) << "Wrong coordinates at vertex 2";
429 
430  EXPECT_TRUE(cmpMesh.property(prop,v1)) << "Wrong Property value at vertex 0";
431  EXPECT_FALSE(cmpMesh.property(prop,v2)) << "Wrong Property value at vertex 1";
432  EXPECT_TRUE(cmpMesh.property(prop,v3)) << "Wrong Property value at vertex 2";
433 
434  EXPECT_FALSE(cmpMesh.property(prop2,v1)) << "Wrong second Property value at vertex 0";
435  EXPECT_FALSE(cmpMesh.property(prop2,v2)) << "Wrong second Property value at vertex 1";
436  EXPECT_FALSE(cmpMesh.property(prop2,v3)) << "Wrong second Property value at vertex 2";
437 
438  // cleanup
439  remove(filename.c_str());
440 
441 }
442 
443 /*
444  * Save and load simple mesh with custom property
445  */
446 TEST_F(OpenMeshReadWriteOM, WriteTriangleEdgeIntProperty) {
447 
448  Mesh mesh;
449 
450  const std::string propName = "EIProp";
451  const std::string filename = std::string("triangle-minimal-")+propName+".om";
452 
453  // generate data
454  Mesh::VertexHandle v1 = mesh.add_vertex(Mesh::Point(1.0,0.0,0.0));
455  Mesh::VertexHandle v2 = mesh.add_vertex(Mesh::Point(0.0,1.0,0.0));
456  Mesh::VertexHandle v3 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
457  mesh.add_face(v1,v2,v3);
458 
460  mesh.add_property(prop,propName);
461  mesh.property(prop).set_persistent(true);
462 
463  Mesh::EdgeHandle e1 = Mesh::EdgeHandle(0);
464  Mesh::EdgeHandle e2 = Mesh::EdgeHandle(1);
465  Mesh::EdgeHandle e3 = Mesh::EdgeHandle(2);
466 
467  int value1 = 10,
468  value2 = 21,
469  value3 = 32;
470 
471  mesh.property(prop,e1) = value1;
472  mesh.property(prop,e2) = value2;
473  mesh.property(prop,e3) = value3;
474 
475  // save
476  bool ok = OpenMesh::IO::write_mesh(mesh,filename);
477  EXPECT_TRUE(ok) << "Unable to write "<<filename;
478 
479  // load
480  Mesh cmpMesh;
481 
482  cmpMesh.add_property(prop,propName);
483  cmpMesh.property(prop).set_persistent(true);
484 
485  ok = OpenMesh::IO::read_mesh(cmpMesh,filename);
486  EXPECT_TRUE(ok) << "Unable to read "<<filename;
487 
488  // compare
489  EXPECT_EQ(3u , cmpMesh.n_vertices()) << "The number of loaded vertices is not correct!";
490  EXPECT_EQ(3u , cmpMesh.n_edges()) << "The number of loaded edges is not correct!";
491  EXPECT_EQ(1u , cmpMesh.n_faces()) << "The number of loaded faces is not correct!";
492 
493  EXPECT_EQ(Mesh::Point(1.0,0.0,0.0) , cmpMesh.point(v1)) << "Wrong coordinates at vertex 0";
494  EXPECT_EQ(Mesh::Point(0.0,1.0,0.0) , cmpMesh.point(v2)) << "Wrong coordinates at vertex 1";
495  EXPECT_EQ(Mesh::Point(0.0,0.0,1.0) , cmpMesh.point(v3)) << "Wrong coordinates at vertex 2";
496 
497  EXPECT_EQ(value1 , cmpMesh.property(prop,e1)) << "Wrong property at edge 0";
498  EXPECT_EQ(value2 , cmpMesh.property(prop,e2)) << "Wrong property at edge 1";
499  EXPECT_EQ(value3 , cmpMesh.property(prop,e3)) << "Wrong property at edge 2";
500 
501  // cleanup
502  remove(filename.c_str());
503 
504 }
505 
506 /*
507  * Save and load simple mesh with custom property
508  */
509 TEST_F(OpenMeshReadWriteOM, WriteSplitTriangleEdgeIntProperty) {
510 
511  Mesh mesh;
512 
513  const std::string propName = "EIProp";
514  const std::string filename = std::string("triangle-minimal-")+propName+".om";
515 
516  // generate data
517  Mesh::VertexHandle v1 = mesh.add_vertex(Mesh::Point(1.0,0.0,0.0));
518  Mesh::VertexHandle v2 = mesh.add_vertex(Mesh::Point(0.0,1.0,0.0));
519  Mesh::VertexHandle v3 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
520  auto fh0 = mesh.add_face(v1,v2,v3);
521  auto c = mesh.calc_face_centroid(fh0);
522  Mesh::VertexHandle v4 = mesh.add_vertex(c);
523  mesh.split(fh0, v4);
524 
525 
527  mesh.add_property(prop,propName);
528  mesh.property(prop).set_persistent(true);
529 
530  Mesh::EdgeHandle e1 = Mesh::EdgeHandle(0);
531  Mesh::EdgeHandle e2 = Mesh::EdgeHandle(1);
532  Mesh::EdgeHandle e3 = Mesh::EdgeHandle(2);
533  Mesh::EdgeHandle e4 = Mesh::EdgeHandle(3);
534  Mesh::EdgeHandle e5 = Mesh::EdgeHandle(4);
535  Mesh::EdgeHandle e6 = Mesh::EdgeHandle(5);
536 
537  int value1 = 10,
538  value2 = 21,
539  value3 = 32,
540  value4 = 43,
541  value5 = 54,
542  value6 = 65;
543 
544  mesh.property(prop,e1) = value1;
545  mesh.property(prop,e2) = value2;
546  mesh.property(prop,e3) = value3;
547  mesh.property(prop,e4) = value4;
548  mesh.property(prop,e5) = value5;
549  mesh.property(prop,e6) = value6;
550 
551  // save
552  OpenMesh::IO::Options options;
553  bool ok = OpenMesh::IO::write_mesh(mesh,filename);
554  EXPECT_TRUE(ok) << "Unable to write "<<filename;
555 
556  // load
557  Mesh cmpMesh;
558 
559  cmpMesh.add_property(prop,propName);
560  cmpMesh.property(prop).set_persistent(true);
561 
562  ok = OpenMesh::IO::read_mesh(cmpMesh,filename);
563  EXPECT_TRUE(ok) << "Unable to read "<<filename;
564 
565  // compare
566  EXPECT_EQ(4u , cmpMesh.n_vertices()) << "The number of loaded vertices is not correct!";
567  EXPECT_EQ(6u , cmpMesh.n_edges()) << "The number of loaded edges is not correct!";
568  EXPECT_EQ(3u , cmpMesh.n_faces()) << "The number of loaded faces is not correct!";
569 
570  EXPECT_EQ(Mesh::Point(1.0,0.0,0.0) , cmpMesh.point(v1)) << "Wrong coordinates at vertex 0";
571  EXPECT_EQ(Mesh::Point(0.0,1.0,0.0) , cmpMesh.point(v2)) << "Wrong coordinates at vertex 1";
572  EXPECT_EQ(Mesh::Point(0.0,0.0,1.0) , cmpMesh.point(v3)) << "Wrong coordinates at vertex 2";
573  EXPECT_EQ(c , cmpMesh.point(v4)) << "Wrong coordinates at vertex 3";
574 
575  EXPECT_EQ(value1 , cmpMesh.property(prop,e1)) << "Wrong property at edge 0";
576  EXPECT_EQ(value2 , cmpMesh.property(prop,e2)) << "Wrong property at edge 1";
577  EXPECT_EQ(value3 , cmpMesh.property(prop,e3)) << "Wrong property at edge 2";
578  EXPECT_EQ(value4 , cmpMesh.property(prop,e4)) << "Wrong property at edge 3";
579  EXPECT_EQ(value5 , cmpMesh.property(prop,e5)) << "Wrong property at edge 4";
580  EXPECT_EQ(value6 , cmpMesh.property(prop,e6)) << "Wrong property at edge 5";
581  // The above only shows that the edge properties are stored in the same order which is not what we want if the edges are different
582 
583  // Check edge properties based on edges defined by from and to vertex
584  for (auto eh : mesh.edges())
585  {
586  auto heh = mesh.halfedge_handle(eh, 0);
587  auto from_vh = mesh.from_vertex_handle(heh);
588  auto to_vh = mesh.to_vertex_handle(heh);
589 
590  // find corresponding halfedge in loaded mesh
591  auto cmpHeh = cmpMesh.find_halfedge(from_vh, to_vh);
592  auto cmpEh = cmpMesh.edge_handle(cmpHeh);
593 
594  EXPECT_EQ(mesh.property(prop, eh), cmpMesh.property(prop, cmpEh)) << "Wrong property at input edge " << eh.idx()
595  << " corresponding to edge " << cmpEh.idx() << " in the loaded Mesh";
596  }
597 
598 
599 
600  // cleanup
601  remove(filename.c_str());
602 
603 }
604 
605 /*
606  * Save and load simple mesh with status property
607  */
608 TEST_F(OpenMeshReadWriteOM, WriteSplitTriangleStatusProperties) {
609 
610  Mesh mesh;
611 
612  mesh.request_vertex_status();
613  mesh.request_edge_status();
614  mesh.request_halfedge_status();
615  mesh.request_face_status();
616 
617  const std::string filename = std::string("triangle-minimal-status.om");
618 
619  // generate data
620  Mesh::VertexHandle v0 = mesh.add_vertex(Mesh::Point(1.0,0.0,0.0));
621  Mesh::VertexHandle v1 = mesh.add_vertex(Mesh::Point(0.0,1.0,0.0));
622  Mesh::VertexHandle v2 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
623  auto fh0 = mesh.add_face(v0,v1,v2);
624  auto c = mesh.calc_face_centroid(fh0);
625  Mesh::VertexHandle v3 = mesh.add_vertex(c);
626  mesh.split(fh0, v3);
627 
628  mesh.delete_vertex(v0);
629  mesh.status(v1).set_selected(true);
630  mesh.status(v2).set_feature(true);
631  mesh.status(v3).set_tagged(true);
632  mesh.status(v2).set_tagged2(true);
633 
634  std::vector<bool> vertex_deleted;
635  std::vector<bool> vertex_selected;
636  std::vector<bool> vertex_feature;
637  std::vector<bool> vertex_tagged;
638  std::vector<bool> vertex_tagged2;
639 
640  for (auto vh : mesh.all_vertices())
641  {
642  vertex_deleted.push_back(mesh.status(vh).deleted());
643  vertex_selected.push_back(mesh.status(vh).selected());
644  vertex_feature.push_back(mesh.status(vh).feature());
645  vertex_tagged.push_back(mesh.status(vh).tagged());
646  vertex_tagged2.push_back(mesh.status(vh).tagged2());
647  }
648 
649  Mesh::EdgeHandle e1 = Mesh::EdgeHandle(0);
650  Mesh::EdgeHandle e2 = Mesh::EdgeHandle(1);
651  Mesh::EdgeHandle e3 = Mesh::EdgeHandle(2);
652  Mesh::EdgeHandle e4 = Mesh::EdgeHandle(3);
653 
654  mesh.status(e1).set_selected(true);
655  mesh.status(e2).set_feature(true);
656  mesh.status(e3).set_tagged(true);
657  mesh.status(e4).set_tagged2(true);
658 
659  std::vector<bool> edge_deleted;
660  std::vector<bool> edge_selected;
661  std::vector<bool> edge_feature;
662  std::vector<bool> edge_tagged;
663  std::vector<bool> edge_tagged2;
664 
665  for (auto eh : mesh.all_edges())
666  {
667  edge_deleted.push_back(mesh.status(eh).deleted());
668  edge_selected.push_back(mesh.status(eh).selected());
669  edge_feature.push_back(mesh.status(eh).feature());
670  edge_tagged.push_back(mesh.status(eh).tagged());
671  edge_tagged2.push_back(mesh.status(eh).tagged2());
672  }
673 
674 
675  Mesh::HalfedgeHandle he1 = Mesh::HalfedgeHandle(0);
676  Mesh::HalfedgeHandle he2 = Mesh::HalfedgeHandle(3);
677  Mesh::HalfedgeHandle he3 = Mesh::HalfedgeHandle(5);
678  Mesh::HalfedgeHandle he4 = Mesh::HalfedgeHandle(1);
679 
680  mesh.status(he1).set_selected(true);
681  mesh.status(he2).set_feature(true);
682  mesh.status(he3).set_tagged(true);
683  mesh.status(he4).set_tagged2(true);
684 
685  std::vector<bool> halfedge_deleted;
686  std::vector<bool> halfedge_selected;
687  std::vector<bool> halfedge_feature;
688  std::vector<bool> halfedge_tagged;
689  std::vector<bool> halfedge_tagged2;
690 
691  for (auto heh : mesh.all_halfedges())
692  {
693  halfedge_deleted.push_back(mesh.status(heh).deleted());
694  halfedge_selected.push_back(mesh.status(heh).selected());
695  halfedge_feature.push_back(mesh.status(heh).feature());
696  halfedge_tagged.push_back(mesh.status(heh).tagged());
697  halfedge_tagged2.push_back(mesh.status(heh).tagged2());
698  }
699 
700  Mesh::FaceHandle f1 = Mesh::FaceHandle(0);
701  Mesh::FaceHandle f2 = Mesh::FaceHandle(2);
702  Mesh::FaceHandle f3 = Mesh::FaceHandle(1);
703  Mesh::FaceHandle f4 = Mesh::FaceHandle(2);
704 
705  mesh.status(f1).set_selected(true);
706  mesh.status(f2).set_feature(true);
707  mesh.status(f3).set_tagged(true);
708  mesh.status(f4).set_tagged2(true);
709 
710  std::vector<bool> face_deleted;
711  std::vector<bool> face_selected;
712  std::vector<bool> face_feature;
713  std::vector<bool> face_tagged;
714  std::vector<bool> face_tagged2;
715 
716  for (auto fh : mesh.all_faces())
717  {
718  face_deleted.push_back(mesh.status(fh).deleted());
719  face_selected.push_back(mesh.status(fh).selected());
720  face_feature.push_back(mesh.status(fh).feature());
721  face_tagged.push_back(mesh.status(fh).tagged());
722  face_tagged2.push_back(mesh.status(fh).tagged2());
723  }
724 
725  // save
727  bool ok = OpenMesh::IO::write_mesh(mesh,filename, options);
728  EXPECT_TRUE(ok) << "Unable to write "<<filename;
729 
730  // load
731  Mesh cmpMesh;
732 
733  cmpMesh.request_vertex_status();
734  cmpMesh.request_edge_status();
735  cmpMesh.request_halfedge_status();
736  cmpMesh.request_face_status();
737 
738  ok = OpenMesh::IO::read_mesh(cmpMesh,filename, options);
739  EXPECT_TRUE(ok) << "Unable to read "<<filename;
740 
741  // compare
742  EXPECT_EQ(4u , cmpMesh.n_vertices()) << "The number of loaded vertices is not correct!";
743  EXPECT_EQ(6u , cmpMesh.n_edges()) << "The number of loaded edges is not correct!";
744  EXPECT_EQ(3u , cmpMesh.n_faces()) << "The number of loaded faces is not correct!";
745 
746  EXPECT_EQ(Mesh::Point(1.0,0.0,0.0) , cmpMesh.point(v0)) << "Wrong coordinates at vertex 0";
747  EXPECT_EQ(Mesh::Point(0.0,1.0,0.0) , cmpMesh.point(v1)) << "Wrong coordinates at vertex 1";
748  EXPECT_EQ(Mesh::Point(0.0,0.0,1.0) , cmpMesh.point(v2)) << "Wrong coordinates at vertex 2";
749  EXPECT_EQ(c , cmpMesh.point(v3)) << "Wrong coordinates at vertex 3";
750 
751  for (auto vh : cmpMesh.all_vertices())
752  {
753  EXPECT_EQ(cmpMesh.status(vh).deleted(), vertex_deleted [vh.idx()]) << "Wrong deleted status at vertex " << vh.idx();
754  EXPECT_EQ(cmpMesh.status(vh).selected(), vertex_selected[vh.idx()]) << "Wrong selected status at vertex " << vh.idx();
755  EXPECT_EQ(cmpMesh.status(vh).feature(), vertex_feature [vh.idx()]) << "Wrong feature status at vertex " << vh.idx();
756  EXPECT_EQ(cmpMesh.status(vh).tagged(), vertex_tagged [vh.idx()]) << "Wrong tagged status at vertex " << vh.idx();
757  EXPECT_EQ(cmpMesh.status(vh).tagged2(), vertex_tagged2 [vh.idx()]) << "Wrong tagged2 status at vertex " << vh.idx();
758  }
759 
760  for (auto eh : cmpMesh.all_edges())
761  {
762  EXPECT_EQ(cmpMesh.status(eh).deleted(), edge_deleted [eh.idx()]) << "Wrong deleted status at edge " << eh.idx();
763  EXPECT_EQ(cmpMesh.status(eh).selected(), edge_selected[eh.idx()]) << "Wrong selected status at edge " << eh.idx();
764  EXPECT_EQ(cmpMesh.status(eh).feature(), edge_feature [eh.idx()]) << "Wrong feature status at edge " << eh.idx();
765  EXPECT_EQ(cmpMesh.status(eh).tagged(), edge_tagged [eh.idx()]) << "Wrong tagged status at edge " << eh.idx();
766  EXPECT_EQ(cmpMesh.status(eh).tagged2(), edge_tagged2 [eh.idx()]) << "Wrong tagged2 status at edge " << eh.idx();
767  }
768 
769  for (auto heh : cmpMesh.all_halfedges())
770  {
771  EXPECT_EQ(cmpMesh.status(heh).deleted(), halfedge_deleted [heh.idx()]) << "Wrong deleted status at halfedge " << heh.idx();
772  EXPECT_EQ(cmpMesh.status(heh).selected(), halfedge_selected[heh.idx()]) << "Wrong selected status at halfedge " << heh.idx();
773  EXPECT_EQ(cmpMesh.status(heh).feature(), halfedge_feature [heh.idx()]) << "Wrong feature status at halfedge " << heh.idx();
774  EXPECT_EQ(cmpMesh.status(heh).tagged(), halfedge_tagged [heh.idx()]) << "Wrong tagged status at halfedge " << heh.idx();
775  EXPECT_EQ(cmpMesh.status(heh).tagged2(), halfedge_tagged2 [heh.idx()]) << "Wrong tagged2 status at halfedge " << heh.idx();
776  }
777 
778  for (auto fh : cmpMesh.all_faces())
779  {
780  EXPECT_EQ(cmpMesh.status(fh).deleted(), face_deleted [fh.idx()]) << "Wrong deleted status at face " << fh.idx();
781  EXPECT_EQ(cmpMesh.status(fh).selected(), face_selected[fh.idx()]) << "Wrong selected status at face " << fh.idx();
782  EXPECT_EQ(cmpMesh.status(fh).feature(), face_feature [fh.idx()]) << "Wrong feature status at face " << fh.idx();
783  EXPECT_EQ(cmpMesh.status(fh).tagged(), face_tagged [fh.idx()]) << "Wrong tagged status at face " << fh.idx();
784  EXPECT_EQ(cmpMesh.status(fh).tagged2(), face_tagged2 [fh.idx()]) << "Wrong tagged2 status at face " << fh.idx();
785  }
786 
787 
788  // cleanup
789  remove(filename.c_str());
790 }
791 
792 /*
793  * Save and load simple mesh with custom property
794  */
795 TEST_F(OpenMeshReadWriteOM, WriteTriangleFaceDoubleProperty) {
796 
797  Mesh mesh;
798 
799  const std::string propName = "FDProp";
800  const std::string filename = std::string("triangle-minimal-")+propName+".om";
801 
802  // generate data
803  Mesh::VertexHandle v1 = mesh.add_vertex(Mesh::Point(1.0,0.0,0.0));
804  Mesh::VertexHandle v2 = mesh.add_vertex(Mesh::Point(0.0,1.0,0.0));
805  Mesh::VertexHandle v3 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
806  mesh.add_face(v1,v2,v3);
807 
809  mesh.add_property(prop,propName);
810  mesh.property(prop).set_persistent(true);
811 
812  Mesh::FaceHandle f1 = Mesh::FaceHandle(0);
813 
814  double va1ue1 = 0.5;
815 
816  mesh.property(prop,f1) = va1ue1;
817 
818  // save
819  bool ok = OpenMesh::IO::write_mesh(mesh,filename);
820  EXPECT_TRUE(ok) << "Unable to write "<<filename;
821 
822  // load
823  Mesh cmpMesh;
824 
825  cmpMesh.add_property(prop,propName);
826  cmpMesh.property(prop).set_persistent(true);
827 
828  ok = OpenMesh::IO::read_mesh(cmpMesh,filename);
829  EXPECT_TRUE(ok) << "Unable to read "<<filename;
830 
831  // compare
832  EXPECT_EQ(3u , cmpMesh.n_vertices()) << "The number of loaded vertices is not correct!";
833  EXPECT_EQ(3u , cmpMesh.n_edges()) << "The number of loaded edges is not correct!";
834  EXPECT_EQ(1u , cmpMesh.n_faces()) << "The number of loaded faces is not correct!";
835 
836  EXPECT_EQ(Mesh::Point(1.0,0.0,0.0) , cmpMesh.point(v1)) << "Wrong coordinates at vertex 0";
837  EXPECT_EQ(Mesh::Point(0.0,1.0,0.0) , cmpMesh.point(v2)) << "Wrong coordinates at vertex 1";
838  EXPECT_EQ(Mesh::Point(0.0,0.0,1.0) , cmpMesh.point(v3)) << "Wrong coordinates at vertex 2";
839 
840  EXPECT_EQ(va1ue1 , cmpMesh.property(prop,f1)) << "Wrong property at edge 0";
841 
842  // cleanup
843  remove(filename.c_str());
844 
845 }
846 
847 /*
848  * Save and load simple mesh with custom property
849  */
850 TEST_F(OpenMeshReadWriteOM, WriteTriangleFaceFloatProperty) {
851 
852  const std::string propName = "FFProp";
853  const std::string filename = std::string("triangle-minimal-")+propName+".om";
854 
855  // generate data
856  Mesh mesh;
857  Mesh::VertexHandle v1 = mesh.add_vertex(Mesh::Point(1.0,0.0,0.0));
858  Mesh::VertexHandle v2 = mesh.add_vertex(Mesh::Point(0.0,1.0,0.0));
859  Mesh::VertexHandle v3 = mesh.add_vertex(Mesh::Point(0.0,0.0,1.0));
860  mesh.add_face(v1,v2,v3);
861 
863  mesh.add_property(prop,propName);
864  mesh.property(prop).set_persistent(true);
865 
866  Mesh::FaceHandle f1 = Mesh::FaceHandle(0);
867 
868  float va1ue1 = 3.1f;
869 
870  mesh.property(prop,f1) = va1ue1;
871 
872  // save
873  bool ok = OpenMesh::IO::write_mesh(mesh,filename);
874  EXPECT_TRUE(ok) << "Unable to write "<<filename;
875 
876 
877  // load
878  Mesh cmpMesh;
879  cmpMesh.add_property(prop,propName);
880  cmpMesh.property(prop).set_persistent(true);
881 
882  ok = OpenMesh::IO::read_mesh(cmpMesh,filename);
883  EXPECT_TRUE(ok) << "Unable to read "<<filename;
884 
885  // compare
886  EXPECT_EQ(3u , cmpMesh.n_vertices()) << "The number of loaded vertices is not correct!";
887  EXPECT_EQ(3u , cmpMesh.n_edges()) << "The number of loaded edges is not correct!";
888  EXPECT_EQ(1u , cmpMesh.n_faces()) << "The number of loaded faces is not correct!";
889 
890  EXPECT_EQ(Mesh::Point(1.0,0.0,0.0) , cmpMesh.point(v1)) << "Wrong coordinates at vertex 0";
891  EXPECT_EQ(Mesh::Point(0.0,1.0,0.0) , cmpMesh.point(v2)) << "Wrong coordinates at vertex 1";
892  EXPECT_EQ(Mesh::Point(0.0,0.0,1.0) , cmpMesh.point(v3)) << "Wrong coordinates at vertex 2";
893 
894  EXPECT_EQ(va1ue1 , cmpMesh.property(prop,f1)) << "Wrong property at edge 0";
895 
896  // cleanup
897  remove(filename.c_str());
898 
899 }
900 
901 /*
902  * Save and load simple mesh with custom property
903  */
904 TEST_F(OpenMeshReadWriteOM, ReadBigMeshWithCustomProperty) {
905 
907  OpenMesh::VPropHandleT<int> vertexProp;
908  bool ok;
909 
910  //generate file
911  /* mesh_.clear();
912  ok = OpenMesh::IO::read_mesh(mesh_,"cube1.off");
913 
914  mesh_.add_property(faceProp,"DFProp");
915  mesh_.property(faceProp).set_persistent(true);
916 
917  mesh_.add_property(vertexProp, "IVProp");
918  mesh_.property(vertexProp).set_persistent(true);
919 
920 
921  for (Mesh::FaceIter fIter = mesh_.faces_begin(); fIter != mesh_.faces_end(); ++fIter)
922  mesh_.property(faceProp,*fIter) = 0.3;
923 
924  for (Mesh::VertexIter vIter = mesh_.vertices_begin(); vIter != mesh_.vertices_end(); ++vIter)
925  mesh_.property(vertexProp,*vIter) = vIter->idx();
926 
927  OpenMesh::IO::write_mesh(mesh_,"cube1_customProps.om");
928 
929 
930  mesh_.clear();
931 */
932  //read file
933  Mesh mesh;
934  mesh.add_property(faceProp,"DFProp");
935  mesh.property(faceProp).set_persistent(true);
936 
937  mesh.add_property(vertexProp, "IVProp");
938  mesh.property(vertexProp).set_persistent(true);
939 
940  ok = OpenMesh::IO::read_mesh(mesh,"cube1_customProps.om");
941  EXPECT_TRUE(ok) << "Unable to read cube1_customProps.om";
942 
944  EXPECT_EQ(7526u , mesh.n_vertices()) << "The number of loaded vertices is not correct!";
945  EXPECT_EQ(22572u, mesh.n_edges()) << "The number of loaded edges is not correct!";
946  EXPECT_EQ(15048u, mesh.n_faces()) << "The number of loaded faces is not correct!";
947 
948  bool wrong = false;
949  for (Mesh::FaceIter fIter = mesh.faces_begin(); fIter != mesh.faces_end() && !wrong; ++fIter)
950  wrong = (0.3 != mesh.property(faceProp,*fIter));
951  EXPECT_FALSE(wrong) << "min one face has wrong face property";
952 
953  wrong = false;
954  for (Mesh::VertexIter vIter = mesh.vertices_begin(); vIter != mesh.vertices_end() && !wrong; ++vIter)
955  wrong = (vIter->idx() != mesh.property(vertexProp,*vIter));
956  EXPECT_FALSE(wrong) << "min one vertex has worng vertex property";
957 }
958 
959 
960 /*
961  * Save and load simple mesh with vertex status
962  */
963 TEST_F(OpenMeshReadWriteOM, WriteReadStatusPropertyVertexOnly) {
964 
965  //read file
966  Mesh mesh;
967  auto vh0 = mesh.add_vertex(Mesh::Point(0,0,0));
968  auto vh1 = mesh.add_vertex(Mesh::Point(1,0,0));
969  auto vh2 = mesh.add_vertex(Mesh::Point(0,1,0));
970  mesh.add_face(vh0, vh1, vh2);
971 
972  mesh.request_vertex_status();
973 
974  mesh.status(vh0).set_selected(true);
975  mesh.status(vh1).set_feature(true);
976  mesh.status(vh2).set_tagged(true);
977  mesh.status(vh0).set_locked(true);
978  mesh.status(vh1).set_deleted(true);
979  mesh.status(vh2).set_hidden(true);
980  mesh.status(vh0).set_fixed_nonmanifold(true);
981 
982 
983  std::string filename_without_status = "no_vertex_status_test.om";
984  std::string filename_with_status = "vertex_status_test.om";
985 
987  OpenMesh::IO::write_mesh(mesh, filename_without_status);
988  OpenMesh::IO::write_mesh(mesh, filename_with_status, opt_with_status);
989 
990  // Load no status from file with status
991  {
992  Mesh loaded_mesh;
993  OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
994 
995  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should not have been loaded";
996  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
997  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
998  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
999  }
1000 
1001  // Load status from file with status
1002  {
1003  Mesh loaded_mesh;
1004  OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status, opt_with_status);
1005 
1006  EXPECT_TRUE (loaded_mesh.has_vertex_status()) << "Mesh has no vertex status even though they should have been loaded";
1007  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
1008  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
1009  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
1010 
1011  if (loaded_mesh.has_vertex_status())
1012  {
1013  for (auto vh : mesh.vertices())
1014  {
1015  EXPECT_EQ(mesh.status(vh).bits(), loaded_mesh.status(vh).bits());
1016  }
1017  }
1018  }
1019 
1020  // Load no status from file with status
1021  {
1022  Mesh loaded_mesh;
1023  loaded_mesh.request_vertex_status();
1024  OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
1025 
1026  EXPECT_TRUE (loaded_mesh.has_vertex_status()) << "Mesh vertex status was removed by reading";
1027  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
1028  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
1029  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
1030 
1031  for (auto vh : loaded_mesh.vertices())
1032  {
1033  EXPECT_EQ(loaded_mesh.status(vh).bits(), 0u) << "Vertex status was modified even though it should not have been loaded";
1034  }
1035  }
1036 
1037  // Try to load status from file without status
1038  {
1039  Mesh loaded_mesh;
1040  OpenMesh::IO::read_mesh(loaded_mesh, filename_without_status, opt_with_status);
1041 
1042  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
1043  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
1044  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though they file should not have a stored status";
1045  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though they file should not have a stored status";
1046  }
1047 }
1048 
1049 
1050 /*
1051  * Save and load simple mesh with halfedge status
1052  */
1053 TEST_F(OpenMeshReadWriteOM, WriteReadStatusPropertyHalfedgeOnly) {
1054 
1055  //read file
1056  Mesh mesh;
1057  auto vh0 = mesh.add_vertex(Mesh::Point(0,0,0));
1058  auto vh1 = mesh.add_vertex(Mesh::Point(1,0,0));
1059  auto vh2 = mesh.add_vertex(Mesh::Point(0,1,0));
1060  mesh.add_face(vh0, vh1, vh2);
1061 
1062  mesh.request_halfedge_status();
1063 
1064  auto heh0 = OpenMesh::HalfedgeHandle(0);
1065  auto heh1 = OpenMesh::HalfedgeHandle(1);
1066  auto heh2 = OpenMesh::HalfedgeHandle(2);
1067  auto heh3 = OpenMesh::HalfedgeHandle(3);
1068  auto heh4 = OpenMesh::HalfedgeHandle(4);
1069  auto heh5 = OpenMesh::HalfedgeHandle(5);
1070 
1071  mesh.status(heh0).set_selected(true);
1072  mesh.status(heh1).set_feature(true);
1073  mesh.status(heh2).set_tagged(true);
1074  mesh.status(heh3).set_locked(true);
1075  mesh.status(heh4).set_deleted(true);
1076  mesh.status(heh5).set_hidden(true);
1077  mesh.status(heh0).set_fixed_nonmanifold(true);
1078 
1079  std::string filename_without_status = "no_halfedge_status_test.om";
1080  std::string filename_with_status = "edge_halfstatus_test.om";
1081 
1083  OpenMesh::IO::write_mesh(mesh, filename_without_status);
1084  OpenMesh::IO::write_mesh(mesh, filename_with_status, opt_with_status);
1085 
1086  // Load no status from file with status
1087  {
1088  Mesh loaded_mesh;
1089  OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
1090 
1091  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should not have been loaded";
1092  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
1093  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
1094  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
1095  }
1096 
1097  // Load status from file with status
1098  {
1099  Mesh loaded_mesh;
1100  OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status, opt_with_status);
1101 
1102  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should have been loaded";
1103  EXPECT_TRUE(loaded_mesh.has_halfedge_status()) << "Mesh has no halfedge status even though file should not have a stored status";
1104  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
1105  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
1106 
1107  if (loaded_mesh.has_halfedge_status())
1108  {
1109  for (auto heh : mesh.halfedges())
1110  {
1111  EXPECT_EQ(mesh.status(heh).bits(), loaded_mesh.status(heh).bits());
1112  }
1113  }
1114  }
1115 
1116  // Load no status from file with status
1117  {
1118  Mesh loaded_mesh;
1119  loaded_mesh.request_halfedge_status();
1120  OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
1121 
1122  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
1123  EXPECT_TRUE (loaded_mesh.has_halfedge_status()) << "Mesh halfedge status was removed by reading";
1124  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
1125  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
1126 
1127  for (auto heh : loaded_mesh.halfedges())
1128  {
1129  EXPECT_EQ(loaded_mesh.status(heh).bits(), 0u) << "Edge status was modified even though it should not have been loaded";
1130  }
1131  }
1132 
1133  // Try to load status from file without status
1134  {
1135  Mesh loaded_mesh;
1136  OpenMesh::IO::read_mesh(loaded_mesh, filename_without_status, opt_with_status);
1137 
1138  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
1139  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
1140  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though they file should not have a stored status";
1141  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though they file should not have a stored status";
1142  }
1143 }
1144 
1145 
1146 /*
1147  * Save and load simple mesh with edge status
1148  */
1149 TEST_F(OpenMeshReadWriteOM, WriteReadStatusPropertyEdgeOnly) {
1150 
1151  //read file
1152  Mesh mesh;
1153  auto vh0 = mesh.add_vertex(Mesh::Point(0,0,0));
1154  auto vh1 = mesh.add_vertex(Mesh::Point(1,0,0));
1155  auto vh2 = mesh.add_vertex(Mesh::Point(0,1,0));
1156  mesh.add_face(vh0, vh1, vh2);
1157 
1158  mesh.request_edge_status();
1159 
1160  auto eh0 = OpenMesh::EdgeHandle(0);
1161  auto eh1 = OpenMesh::EdgeHandle(1);
1162  auto eh2 = OpenMesh::EdgeHandle(2);
1163 
1164  mesh.status(eh0).set_selected(true);
1165  mesh.status(eh1).set_feature(true);
1166  mesh.status(eh2).set_tagged(true);
1167  mesh.status(eh0).set_locked(true);
1168  mesh.status(eh1).set_deleted(true);
1169  mesh.status(eh2).set_hidden(true);
1170  mesh.status(eh0).set_fixed_nonmanifold(true);
1171 
1172  std::string filename_without_status = "no_edge_status_test.om";
1173  std::string filename_with_status = "edge_status_test.om";
1174 
1176  OpenMesh::IO::write_mesh(mesh, filename_without_status);
1177  OpenMesh::IO::write_mesh(mesh, filename_with_status, opt_with_status);
1178 
1179  // Load no status from file with status
1180  {
1181  Mesh loaded_mesh;
1182  OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
1183 
1184  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should not have been loaded";
1185  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
1186  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
1187  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
1188  }
1189 
1190  // Load status from file with status
1191  {
1192  Mesh loaded_mesh;
1193  OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status, opt_with_status);
1194 
1195  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should have been loaded";
1196  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
1197  EXPECT_TRUE(loaded_mesh.has_edge_status()) << "Mesh has no edge status even though file should not have a stored status";
1198  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
1199 
1200  if (loaded_mesh.has_edge_status())
1201  {
1202  for (auto eh : mesh.edges())
1203  {
1204  EXPECT_EQ(mesh.status(eh).bits(), loaded_mesh.status(eh).bits());
1205  }
1206  }
1207  }
1208 
1209  // Load no status from file with status
1210  {
1211  Mesh loaded_mesh;
1212  loaded_mesh.request_edge_status();
1213  OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
1214 
1215  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
1216  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
1217  EXPECT_TRUE (loaded_mesh.has_edge_status()) << "Mesh edge status was removed by reading";
1218  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
1219 
1220  for (auto eh : loaded_mesh.edges())
1221  {
1222  EXPECT_EQ(loaded_mesh.status(eh).bits(), 0u) << "Edge status was modified even though it should not have been loaded";
1223  }
1224  }
1225 
1226  // Try to load status from file without status
1227  {
1228  Mesh loaded_mesh;
1229  OpenMesh::IO::read_mesh(loaded_mesh, filename_without_status, opt_with_status);
1230 
1231  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
1232  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
1233  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though they file should not have a stored status";
1234  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though they file should not have a stored status";
1235  }
1236 }
1237 
1238 
1239 /*
1240  * Save and load simple mesh with face status
1241  */
1242 TEST_F(OpenMeshReadWriteOM, WriteReadStatusPropertyFaceOnly) {
1243 
1244  //read file
1245  Mesh mesh;
1246  auto vh0 = mesh.add_vertex(Mesh::Point(0,0,0));
1247  auto vh1 = mesh.add_vertex(Mesh::Point(1,0,0));
1248  auto vh2 = mesh.add_vertex(Mesh::Point(0,1,0));
1249  auto vh3 = mesh.add_vertex(Mesh::Point(1,1,0));
1250  auto fh0 = mesh.add_face(vh0, vh1, vh2);
1251  auto fh1 = mesh.add_face(vh2, vh1, vh3);
1252 
1253  mesh.request_face_status();
1254 
1255  mesh.status(fh0).set_selected(true);
1256  mesh.status(fh1).set_feature(true);
1257  mesh.status(fh0).set_tagged(true);
1258  mesh.status(fh1).set_locked(true);
1259  mesh.status(fh0).set_deleted(true);
1260  mesh.status(fh1).set_hidden(true);
1261  mesh.status(fh0).set_fixed_nonmanifold(true);
1262 
1263  std::string filename_without_status = "no_face_status_test.om";
1264  std::string filename_with_status = "face_status_test.om";
1265 
1267  OpenMesh::IO::write_mesh(mesh, filename_without_status);
1268  OpenMesh::IO::write_mesh(mesh, filename_with_status, opt_with_status);
1269 
1270  // Load no status from file with status
1271  {
1272  Mesh loaded_mesh;
1273  OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
1274 
1275  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should not have been loaded";
1276  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
1277  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
1278  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though file should not have a stored status";
1279  }
1280 
1281  // Load status from file with status
1282  {
1283  Mesh loaded_mesh;
1284  OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status, opt_with_status);
1285 
1286  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though they should have been loaded";
1287  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
1288  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though file should not have a stored status";
1289  EXPECT_TRUE(loaded_mesh.has_face_status()) << "Mesh has no face status even though file should not have a stored status";
1290 
1291  if (loaded_mesh.has_face_status())
1292  {
1293  for (auto fh : mesh.faces())
1294  {
1295  EXPECT_EQ(mesh.status(fh).bits(), loaded_mesh.status(fh).bits());
1296  }
1297  }
1298  }
1299 
1300  // Load no status from file with status
1301  {
1302  Mesh loaded_mesh;
1303  loaded_mesh.request_face_status();
1304  OpenMesh::IO::read_mesh(loaded_mesh, filename_with_status);
1305 
1306  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
1307  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
1308  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edgestatus even though file should not have a stored status";
1309  EXPECT_TRUE (loaded_mesh.has_face_status()) << "Mesh face status was removed by reading";
1310 
1311  for (auto fh : loaded_mesh.faces())
1312  {
1313  EXPECT_EQ(loaded_mesh.status(fh).bits(), 0u) << "Edge status was modified even though it should not have been loaded";
1314  }
1315  }
1316 
1317  // Try to load status from file without status
1318  {
1319  Mesh loaded_mesh;
1320  OpenMesh::IO::read_mesh(loaded_mesh, filename_without_status, opt_with_status);
1321 
1322  EXPECT_FALSE(loaded_mesh.has_vertex_status()) << "Mesh has vertex status even though file should not have a stored status";
1323  EXPECT_FALSE(loaded_mesh.has_halfedge_status()) << "Mesh has halfedge status even though file should not have a stored status";
1324  EXPECT_FALSE(loaded_mesh.has_edge_status()) << "Mesh has edge status even though they file should not have a stored status";
1325  EXPECT_FALSE(loaded_mesh.has_face_status()) << "Mesh has face status even though they file should not have a stored status";
1326  }
1327 }
1328 
1329 
1330 /*
1331  * Just load a triangle mesh from an om file of version 1.2
1332  */
1333 TEST_F(OpenMeshReadWriteOM, LoadTriangleMeshVersion_1_2) {
1334 
1335  mesh_.clear();
1336 
1337  std::string file_name = "cube_tri_version_1_2.om";
1338 
1339  bool ok = OpenMesh::IO::read_mesh(mesh_, file_name);
1340 
1341  EXPECT_TRUE(ok) << file_name;
1342 
1343  EXPECT_EQ(8u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
1344  EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
1345  EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
1346  EXPECT_EQ(36u , mesh_.n_halfedges()) << "The number of loaded halfedges is not correct!";
1347 }
1348 
1349 
1350 /*
1351  * Just load a polyhedral mesh from an om file of version 1.2
1352  */
1353 TEST_F(OpenMeshReadWriteOM, LoadPolyMeshVersion_1_2) {
1354 
1355  PolyMesh mesh;
1356 
1357  std::string file_name = "cube_poly_version_1_2.om";
1358 
1359  bool ok = OpenMesh::IO::read_mesh(mesh, file_name);
1360 
1361  EXPECT_TRUE(ok) << file_name;
1362 
1363  EXPECT_EQ(8u , mesh.n_vertices()) << "The number of loaded vertices is not correct!";
1364  EXPECT_EQ(12u , mesh.n_edges()) << "The number of loaded edges is not correct!";
1365  EXPECT_EQ(6u , mesh.n_faces()) << "The number of loaded faces is not correct!";
1366  EXPECT_EQ(24u , mesh.n_halfedges()) << "The number of loaded halfedges is not correct!";
1367 }
1368 
1369 
1370 /*
1371  * Just load a triangle mesh from an om file of version 2.0
1372  */
1373 TEST_F(OpenMeshReadWriteOM, LoadTriangleMeshVersion_2_0) {
1374 
1375  mesh_.clear();
1376 
1377  std::string file_name = "cube_tri_version_2_0.om";
1378 
1379  bool ok = OpenMesh::IO::read_mesh(mesh_, file_name);
1380 
1381  EXPECT_TRUE(ok) << file_name;
1382 
1383  EXPECT_EQ(8u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
1384  EXPECT_EQ(18u , mesh_.n_edges()) << "The number of loaded edges is not correct!";
1385  EXPECT_EQ(12u , mesh_.n_faces()) << "The number of loaded faces is not correct!";
1386  EXPECT_EQ(36u , mesh_.n_halfedges()) << "The number of loaded halfedges is not correct!";
1387 }
1388 
1389 
1390 /*
1391  * Just load a polyhedral mesh from an om file of version 2.0
1392  */
1393 TEST_F(OpenMeshReadWriteOM, LoadPolyMeshVersion_2_0) {
1394 
1395  PolyMesh mesh;
1396 
1397  std::string file_name = "cube_poly_version_2_0.om";
1398 
1399  bool ok = OpenMesh::IO::read_mesh(mesh, file_name);
1400 
1401  EXPECT_TRUE(ok) << file_name;
1402 
1403  EXPECT_EQ(8u , mesh.n_vertices()) << "The number of loaded vertices is not correct!";
1404  EXPECT_EQ(12u , mesh.n_edges()) << "The number of loaded edges is not correct!";
1405  EXPECT_EQ(6u , mesh.n_faces()) << "The number of loaded faces is not correct!";
1406  EXPECT_EQ(24u , mesh.n_halfedges()) << "The number of loaded halfedges is not correct!";
1407 }
1408 
1409 
1410 /*
1411  * Try to load mesh from om file with a version that is not yet supported
1412  */
1413 TEST_F(OpenMeshReadWriteOM, LoadTriMeshVersion_7_5) {
1414 
1415  PolyMesh mesh;
1416 
1417  std::string file_name = "cube_tri_version_7_5.om";
1418 
1419  bool ok = OpenMesh::IO::read_mesh(mesh, file_name);
1420 
1421  EXPECT_FALSE(ok) << file_name;
1422 }
1423 
1424 }
Has (r) / store (w) vertex colors.
Definition: Options.hh:105
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
Kernel::Color Color
Color type.
Definition: PolyMeshT.hh:116
VertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Definition: PolyMeshT.hh:235
Has (r) / store (w) float values for colors (currently only implemented for PLY and OFF files) ...
Definition: Options.hh:112
void calc_face_centroid(FaceHandle _fh, Point &_pt) const
calculates the average of the vertices defining _fh
Definition: PolyMeshT.hh:275
bool write_mesh(const Mesh &_mesh, const std::string &_filename, Options _opt=Options::Default, std::streamsize _precision=6)
Write a mesh to the file _filename.
Definition: MeshIO.hh:207
Handle for a halfedge entity.
Definition: Handles.hh:127
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
Has (r) / store (w) texture coordinates.
Definition: Options.hh:106
Has (r) / store (w) status properties.
Definition: Options.hh:114
Set options for reader/writer modules.
Definition: Options.hh:90
Handle for a edge entity.
Definition: Handles.hh:134
bool read_mesh(Mesh &_mesh, const std::string &_filename)
Read a mesh from file _filename.
Definition: MeshIO.hh:112
VertexHandle split(EdgeHandle _eh, const Point &_p)
Edge split (= 2-to-4 split)
Definition: TriMeshT.hh:267