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;
45 options += OpenMesh::IO::Options::VertexColor;
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;
71 options += OpenMesh::IO::Options::VertexTexCoord;
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;
111 options += OpenMesh::IO::Options::VertexColor;
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;
195 options += OpenMesh::IO::Options::VertexColor;
196 options -= OpenMesh::IO::Options::ColorFloat;
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
262 OpenMesh::VPropHandleT<bool> prop;
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
326 OpenMesh::VPropHandleT<bool> prop;
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
389 OpenMesh::VPropHandleT<bool> prop;
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
397 OpenMesh::VPropHandleT<bool> prop2;
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
459 OpenMesh::EPropHandleT<int> prop;
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
526 OpenMesh::EPropHandleT<int> prop;
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
726 OpenMesh::IO::Options options = OpenMesh::IO::Options::Status;
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
808 OpenMesh::FPropHandleT<double> prop;
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
862 OpenMesh::FPropHandleT<float> prop;
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
906 OpenMesh::FPropHandleT<double> faceProp;
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
986 OpenMesh::IO::Options opt_with_status = OpenMesh::IO::Options::Status;
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
1082 OpenMesh::IO::Options opt_with_status = OpenMesh::IO::Options::Status;
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
1175 OpenMesh::IO::Options opt_with_status = OpenMesh::IO::Options::Status;
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
1266 OpenMesh::IO::Options opt_with_status = OpenMesh::IO::Options::Status;
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 }
OpenMesh::TriMesh_ArrayKernelT
Definition: PolyMesh_ArrayKernelT.hh:73
OpenMesh::IO::Options::VertexColor
Has (r) / store (w) vertex colors.
Definition: Options.hh:105
OpenMesh::EPropHandleT
Definition: Property.hh:510
OpenMesh::PolyMeshT::Point
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
OpenMesh::PolyMeshT::Color
Kernel::Color Color
Color type.
Definition: PolyMeshT.hh:116
OpenMesh::PolyMeshT::add_vertex
VertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Definition: PolyMeshT.hh:235
OpenMesh::IO::Options::ColorFloat
Has (r) / store (w) float values for colors (currently only implemented for PLY and OFF files) ...
Definition: Options.hh:112
OpenMesh::PolyMeshT::calc_face_centroid
void calc_face_centroid(FaceHandle _fh, Point &_pt) const
calculates the average of the vertices defining _fh
Definition: PolyMeshT.hh:275
OpenMesh::IO::write_mesh
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
OpenMesh::HalfedgeHandle
Handle for a halfedge entity.
Definition: Handles.hh:127
OpenMesh::PolyMeshT::VertexHandle
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
OpenMesh::IO::Options::VertexTexCoord
Has (r) / store (w) texture coordinates.
Definition: Options.hh:106
OpenMesh::IO::Options::Status
Has (r) / store (w) status properties.
Definition: Options.hh:114
OpenMeshBase
Definition: unittests_common.hh:26
OpenMesh::IO::Options
Set options for reader/writer modules.
Definition: Options.hh:90
OpenMesh::EdgeHandle
Handle for a edge entity.
Definition: Handles.hh:134
OpenMesh::IO::read_mesh
bool read_mesh(Mesh &_mesh, const std::string &_filename)
Read a mesh from file _filename.
Definition: MeshIO.hh:112
OpenMesh::FPropHandleT
Definition: Property.hh:524
OpenMesh::TriMeshT::split
VertexHandle split(EdgeHandle _eh, const Point &_p)
Edge split (= 2-to-4 split)
Definition: TriMeshT.hh:267
OpenMesh::VPropHandleT< bool >