Developer Documentation

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

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
FileVTK.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49
50 #include "FileVTK.hh"
51
52 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
53 #endif
54 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
55 #endif
56
57 #if QT_VERSION >= 0x050000
58 #else
59 #include <QtGui>
60 #endif
61
62
63 //-----------------------------------------------------------------------------------------------------
64 void remove_duplicated_vertices(std::vector<quint32>& _indices)
65 {
66 std::vector<quint32>::iterator endIter = _indices.end();
67 for (std::vector<quint32>::iterator iter = _indices.begin(); iter != endIter; ++iter)
68 endIter = std::remove(iter+1, endIter, *(iter));
69
70 _indices.erase(endIter,_indices.end());
71 }
72
73 //-----------------------------------------------------------------------------------------------------
74
76 FileVTKPlugin::FileVTKPlugin():
77 forceTriangleMesh_(false),
78 forcePolyMesh_(false),
79 saveOptions_(0),
80 saveBinary_(0),
81 saveFaceNormals_(0),
82 saveVertexNormals_(0),
83 saveVertexTexCoords_(0),
84 savePrecisionLabel_(0),
85 savePrecision_(0),
86 saveDefaultButton_(),
87 binary_(false),
88 userWriteOptions_(0)
89 {
90 }
91
92 //-----------------------------------------------------------------------------------------------------
93
94 void FileVTKPlugin::initializePlugin() {
95
96 if(OpenFlipperSettings().value("FileVtk/Save/Binary",false).toBool())
97 userWriteOptions_ |= BINARY; //currently unsupported
98 if(OpenFlipperSettings().value("FileVtk/Save/FaceNormals",true).toBool())
99 userWriteOptions_ |= FACENORMALS;
100 if(OpenFlipperSettings().value("FileVtk/Save/VertexNormals",true).toBool())
101 userWriteOptions_ |= VERTEXNORMALS;
102 if(OpenFlipperSettings().value("FileVtk/Save/VertexTexCoords",true).toBool())
103 userWriteOptions_ |= VERTEXTEXCOORDS;
104 }
105
106 //-----------------------------------------------------------------------------------------------------
107
108 QString FileVTKPlugin::getLoadFilters() {
109 return QString( tr("Visualization Toolkit ASCII ( *.vtk )") );
110 }
111
112 //-----------------------------------------------------------------------------------------------------
113
114 QString FileVTKPlugin::getSaveFilters() {
115 return QString( tr("Visualization Toolkit ASCII ( *.vtk )") );
116 }
117
118 //-----------------------------------------------------------------------------------------------------
119
120 DataType FileVTKPlugin::supportedType() {
121 DataType type = DATA_POLY_MESH | DATA_TRIANGLE_MESH | DATA_GROUP;
122
123 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
124 type |= DATA_POLYHEDRAL_MESH;
125 #endif
126 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
127 type |= DATA_HEXAHEDRAL_MESH;
128 #endif
129
130 return type;
131 }
132
133 //-----------------------------------------------------------------------------------------------------
134
135 QWidget* FileVTKPlugin::loadOptionsWidget(QString /*_currentFilter*/) {
136 return 0;
137 }
138
139 //-----------------------------------------------------------------------------------------------------
140
141 QWidget* FileVTKPlugin::saveOptionsWidget(QString /*_currentFilter*/) {
142
143 if (saveOptions_ == 0){
144 //generate widget
145 saveOptions_ = new QWidget();
146 QVBoxLayout* layout = new QVBoxLayout();
147 layout->setAlignment(Qt::AlignTop);
148
149 saveBinary_ = new QCheckBox("Save Binary");
150 layout->addWidget(saveBinary_);
151 saveBinary_->setCheckable(false);
152
153 saveFaceNormals_ = new QCheckBox("Save Face Normals");
154 layout->addWidget(saveFaceNormals_);
155
156 saveVertexNormals_ = new QCheckBox("Save Vertex Normals");
157 layout->addWidget(saveVertexNormals_);
158
159 saveVertexTexCoords_ = new QCheckBox("Save Vertex TexCoords");
160 layout->addWidget(saveVertexTexCoords_);
161
162 savePrecisionLabel_ = new QLabel("Writer Precision");
163 layout->addWidget(savePrecisionLabel_);
164
165 savePrecision_ = new QSpinBox();
166 savePrecision_->setMinimum(1);
167 savePrecision_->setMaximum(12);
168 savePrecision_->setValue(6);
169 layout->addWidget(savePrecision_);
170
171 saveDefaultButton_ = new QPushButton("Make Default");
172 layout->addWidget(saveDefaultButton_);
173
174 saveOptions_->setLayout(layout);
175
176 connect(saveBinary_, SIGNAL(clicked(bool)), savePrecision_, SLOT(setDisabled(bool)));
177 connect(saveDefaultButton_, SIGNAL(clicked()), this, SLOT(slotSaveDefault()));
178
179 saveBinary_->setChecked( OpenFlipperSettings().value("FileVtk/Save/Binary",false).toBool() );
180 saveFaceNormals_->setChecked( OpenFlipperSettings().value("FileVtk/Save/FaceNormals",true).toBool() );
181 saveVertexNormals_->setChecked( OpenFlipperSettings().value("FileVtk/Save/VertexNormals",true).toBool() );
182 saveVertexTexCoords_->setChecked( OpenFlipperSettings().value("FileVtk/Save/VertexTexCoords",true).toBool() );
183 }
184
185 return saveOptions_;
186 }
187
188 //-----------------------------------------------------------------------------------------------------
189
190 void FileVTKPlugin::slotSaveDefault() {
191 OpenFlipperSettings().setValue( "FileVtk/Save/Binary", saveBinary_->isChecked() );
192 OpenFlipperSettings().setValue( "FileVtk/Save/FaceNormals", saveFaceNormals_->isChecked() );
193 OpenFlipperSettings().setValue( "FileVtk/Save/VertexNormals", saveVertexNormals_->isChecked() );
194 OpenFlipperSettings().setValue( "FileVtk/Save/VertexTexCoords", saveVertexTexCoords_->isChecked() );
195 }
196
197 //-----------------------------------------------------------------------------------------------------
198
199
200 //-----------------------------------------------------------------------------------------------------
201 //-----------------------------------------------------------------------------------------------------
202 //-------------------------------------- cool helper function -----------------------------------------
203 //-----------------------------------------------------------------------------------------------------
204 //-----------------------------------------------------------------------------------------------------
205
206
207 template <typename MeshT>
208 int FileVTKPlugin::addTetraCellToOpenMesh(MeshT /*_mesh*/, std::vector<quint32> /*_indices*/)
209 {
210 emit log(LOGWARN,tr("Unsupported Cell Type TETRA") );
211 return -1;
212 }
213
214 template <typename MeshT>
215 int FileVTKPlugin::addHexaCellToOpenMesh(MeshT /*_mesh*/, std::vector<quint32> /*_indices*/)
216 {
217 emit log(LOGWARN,tr("Unsupported Cell Type HEXAHEDRON") );
218 return -1;
219 }
220
221 template <typename MeshT>
222 int FileVTKPlugin::addWedgeCellToOpenMesh(MeshT /*_mesh*/, std::vector<quint32> /*_indices*/)
223 {
224 emit log(LOGWARN,tr("Unsupported Cell Type WEDGE") );
225 return -1;
226 }
227
228 template <typename MeshT>
229 int FileVTKPlugin::addPyramidCellToOpenMesh(MeshT /*_mesh*/, std::vector<quint32> /*_indices*/)
230 {
231 emit log(LOGWARN,tr("Unsupported Cell Type PYRAMID") );
232 return -1;
233 }
234
235 template <typename MeshT>
236 int FileVTKPlugin::addFaceToOpenMesh(MeshT*& _mesh, std::vector<quint32> _indices)
237 {
238 std::vector<OpenMesh::VertexHandle> handles;
239 for (std::vector<quint32>::const_iterator it = _indices.begin(); it != _indices.end(); ++it)
240 handles.push_back(_mesh->vertex_handle(*it));
241
242 OpenMesh::FaceHandle fh = _mesh->add_face(handles);
243
244 // Try the other direction
245 if ( ! fh.is_valid() ) {
246
247 std::vector< OpenMesh::VertexHandle > inverseHandles;
248 for ( int i = handles.size()-1 ; i >= 0 ; --i)
249 inverseHandles.push_back(handles[i]);
250
251 fh = _mesh->add_face(inverseHandles);
252
253 if ( !fh.is_valid() ) {
254 return add_non_manifold_face(_mesh, handles);
255 }
256 }
257 return fh.idx();
258 }
259
260 template <typename MeshT>
261 int FileVTKPlugin::addFaceToOpenMesh(MeshT*& _mesh, quint32 _index1, quint32 _index2, quint32 _index3)
262 {
263 OpenMesh::VertexHandle v1 = _mesh->vertex_handle(_index1);
264 OpenMesh::VertexHandle v2 = _mesh->vertex_handle(_index2);
265 OpenMesh::VertexHandle v3 = _mesh->vertex_handle(_index3);
266 return _mesh->add_face(v1,v2,v3).idx();
267 }
268
269 template <typename MeshT>
270 void FileVTKPlugin::updateFaceNormalsOfOpenMesh(MeshT*& _mesh)
271 {
272 _mesh->update_face_normals();
273 }
274
275 void FileVTKPlugin::updateFaceNormals(TriMesh*& _mesh) { updateFaceNormalsOfOpenMesh(_mesh); }
276 void FileVTKPlugin::updateFaceNormals(PolyMesh*& _mesh) { updateFaceNormalsOfOpenMesh(_mesh); }
277
278
279 template <typename MeshT>
280 void FileVTKPlugin::updateVertexNormalsOfOpenMesh(MeshT*& _mesh)
281 {
282 _mesh->update_vertex_normals();
283 }
284
285 template <typename MeshT>
286 void FileVTKPlugin::removeTemporaryPropertiesOfOpenMesh(MeshT*& _mesh)
287 {
288 //if we added this property temporarily, we need to remove it now
289 OpenMesh::VPropHandleT< OpenMesh::VertexHandle > originalVertexIdx;
290 if (! _mesh->get_property_handle(originalVertexIdx,"FileVTKPlugin_originalVertexIdx")) {
291 _mesh->remove_property( originalVertexIdx );
292 }
293 }
294
295 template <typename MeshT>
296 void FileVTKPlugin::addVertexNormalToOpenMesh(MeshT _mesh, quint32 _index, OpenMesh::Vec3d _normal)
297 {
298 OpenMesh::VertexHandle vh = _mesh->vertex_handle(_index);
299 if ( vh.is_valid() )
300 _mesh->set_normal( vh , _normal );
301 }
302
303
304 template <typename MeshT>
305 void FileVTKPlugin::addFaceNormalToOpenMesh(MeshT _mesh, quint32 _index, OpenMesh::Vec3d _normal)
306 {
307 OpenMesh::FaceHandle fh = _mesh->face_handle(_index);
308 if ( fh.is_valid() )
309 _mesh->set_normal( fh, _normal );
310 }
311
312 template <typename MeshT>
313 void FileVTKPlugin::addCellNormal(MeshT*& _mesh,const CellType& _cell, OpenMesh::Vec3d _normal)
314 {
315 if ((_cell.type <= 4) || (_cell.type >= 10))
316 {
317 // vertex, poly vertex, line, poly line, tetra, voxel, hexahedron, wedge, pyramid, and quadratic stuff
318 emit log(LOGWARN,tr("Normals not supported for type %1").arg(_cell.type) );
319 }
320 else if (_cell.type == 5)
321 {
322 // Triangle
323 addFaceNormal(_mesh, _cell.index, _normal);
324 }
325 else if (_cell.type == 6)
326 {
327 // Triangle strip
328 int numberOfTriangles = _cell.indices.size() - 2;
329 // we assume here that the triangles have contigous indices as they were freshly created while loading the file
330 for (int i = 0; i < numberOfTriangles; i++)
331 addFaceNormal(_mesh, _cell.index + i, _normal);
332 }
333 else if ((_cell.type >= 7) && (_cell.type <= 9))
334 {
335 // polygon, pixel, quad
336 if (forceTriangleMesh_)
337 {
338 // _mesh is a TriMesh even if cell represents a polygon with more than 3 vertices
339 // for more than 3 vertices the polygon will be split into triangles
340 // we have to set the normal for all these triangles
341 // we assume again that the triangles have contigous indices as they were freshly created while loading the file
342 int numberOfTriangles = _cell.indices.size() - 2;
343 for (int i = 0; i < numberOfTriangles; i++)
344 addFaceNormal(_mesh, _cell.index + i, _normal);
345 }
346 else
347 {
348 // Here _mesh might also be a TriMesh. But this is only the case if all polygons are triangles
349 // so we only need to set a single normal
350 addFaceNormal(_mesh, _cell.index , _normal);
351 }
352 }
353 }
354
355 template <typename MeshT>
356 void FileVTKPlugin::setNormalsOfDuplicatedVerticesOfOpenMesh(MeshT*& _mesh)
357 {
358 //iterate over all contained vertices and set the normals
359 OpenMesh::VPropHandleT< OpenMesh::VertexHandle > originalVertexIdx;
360 if (! _mesh->get_property_handle(originalVertexIdx,"FileVTKPlugin_originalVertexIdx")) {
361 //TODO: check if this is correct;
362 //if the property was not found, there are no copied vertices and we can leave
363 return;
364 //old and maybe unnecessary: _mesh->add_property( originalVertexIdx, "FileVTKPlugin_originalVertexIdx" );
365 }
366
367 typename MeshT::VertexIter vit = _mesh->vertices_begin();
368 typename MeshT::VertexIter vend = _mesh->vertices_end();
369
370 for(; vit != vend; ++vit) {
371 if ( _mesh->property(originalVertexIdx, *vit).is_valid() ) {
372 //copied vertex found
373 _mesh->set_normal( *vit, _mesh->normal(_mesh->property (originalVertexIdx, *vit) ) );
374 }
375 }
376 }
377
378 template< class MeshT >
379 bool FileVTKPlugin::writeASCIIDataOfOpenMesh(std::ostream& _out, MeshT& _mesh ) {
380
381 if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0)
382 _out.precision(savePrecision_->value());
383
384 _out << "DATASET POLYDATA\n";
385
386 typename MeshT::Point p;
387 typename MeshT::Normal n;
388 typename OpenMesh::Vec4f c;
389 typename MeshT::TexCoord2D t;
390
391 typename MeshT::VertexIter vit = _mesh.vertices_begin();
392 typename MeshT::VertexIter end_vit = _mesh.vertices_end();
393 typename MeshT::FaceIter fit = _mesh.faces_begin();
394 typename MeshT::FaceIter end_fit = _mesh.faces_end();
395 typename MeshT::FaceVertexIter fvit;
396
397 int total_face_vertices = _mesh.n_faces();
398 for (; fit != end_fit; ++fit) {
399 total_face_vertices += _mesh.valence(*fit);
400 }
401 // Write vertex data
402 _out << "POINTS " << _mesh.n_vertices() << " float\n";
403 for (; vit != end_vit; ++vit) {
404 // Write vertex p[0] p[1] p[2]
405 p = _mesh.point(*vit);
406 _out << p[0] << " " << p[1] << " " << p[2];
407 _out << "\n";
408 }
409
410 // Write face connectivity
411 _out << "POLYGONS "<< _mesh.n_faces() << " " << total_face_vertices << "\n";
412 for (fit = _mesh.faces_begin(); fit != end_fit; ++fit) {
413 // Write face valence
414 _out << _mesh.valence(*fit);
415
416 // Get face-vertex iterator
417 fvit = _mesh.fv_iter(*fit);
418
419 // Write vertex indices
420 for (;fvit.is_valid(); ++fvit) {
421 _out << " " << fvit->idx();
422 }
423 _out << "\n";
424 }
425
426 //*************//
427 //OPTIONAL DATA//
428 //*************//
429
430 /*** Write face attributes ***/
431 _out << "CELL_DATA "<< _mesh.n_faces() << "\n";
432
433 //Write face normals
434 if (_mesh.has_face_normals() && (userWriteOptions_ & FileVTKPlugin::FACENORMALS)) {
435 _out << "NORMALS faceNormals float\n";
436 for (fit = _mesh.faces_begin(); fit != end_fit; ++fit) {
437 n = _mesh.normal(*fit);
438 _out << n[0] << " " << n[1] << " " << n[2];
439 _out << "\n";
440 }
441 }
442
443 /*** Write vertex attributes ***/
444 _out << "POINT_DATA "<< _mesh.n_vertices() << "\n";
445
446 //Write vertex normals
447 if (_mesh.has_vertex_normals() && (userWriteOptions_ & FileVTKPlugin::VERTEXNORMALS)) {
448 _out << "NORMALS vertexNormals float\n";
449 for (vit = _mesh.vertices_begin(); vit != end_vit; ++vit) {
450 n = _mesh.normal(*vit);
451 _out << n[0] << " " << n[1] << " " << n[2];
452 _out << "\n";
453 }
454 }
455
456 // Write vertex texcoords (only 2D for now)
457 if (_mesh.has_vertex_texcoords2D() && (userWriteOptions_ & FileVTKPlugin::VERTEXTEXCOORDS)) {
458 _out << "TEXTURE_COORDINATES vertexTexcoords 2 float\n";
459 for (vit = _mesh.vertices_begin(); vit != end_vit; ++vit) {
460 t = _mesh.texcoord2D(*vit);
461 _out << t[0] << " " << t[1];
462 _out << "\n";
463 }
464 }
465
466 return true;
467 }
468
469 int FileVTKPlugin::addTetraCell(TriMesh*& _mesh, std::vector<quint32> _indices) { return addTetraCellToOpenMesh(_mesh, _indices); }
470 int FileVTKPlugin::addTetraCell(PolyMesh*& _mesh, std::vector<quint32> _indices) { return addTetraCellToOpenMesh(_mesh, _indices); }
471
472 int FileVTKPlugin::addHexaCell(TriMesh*& _mesh, std::vector<quint32> _indices) { return addHexaCellToOpenMesh(_mesh, _indices); }
473 int FileVTKPlugin::addHexaCell(PolyMesh*& _mesh, std::vector<quint32> _indices) { return addHexaCellToOpenMesh(_mesh, _indices); }
474
475 int FileVTKPlugin::addWedgeCell(TriMesh*& _mesh, std::vector<quint32> _indices) { return addWedgeCellToOpenMesh(_mesh, _indices); }
476 int FileVTKPlugin::addWedgeCell(PolyMesh*& _mesh, std::vector<quint32> _indices) { return addWedgeCellToOpenMesh(_mesh, _indices); }
477
478 int FileVTKPlugin::addPyramidCell(TriMesh*& _mesh, std::vector<quint32> _indices) { return addPyramidCellToOpenMesh(_mesh, _indices); }
479 int FileVTKPlugin::addPyramidCell(PolyMesh*& _mesh, std::vector<quint32> _indices) { return addPyramidCellToOpenMesh(_mesh, _indices); }
480
481 int FileVTKPlugin::addFace(TriMesh*& _mesh, std::vector<quint32> _indices) { return addFaceToOpenMesh(_mesh, _indices); }
482 int FileVTKPlugin::addFace(PolyMesh*& _mesh, std::vector<quint32> _indices) { return addFaceToOpenMesh(_mesh, _indices); }
483
484 int FileVTKPlugin::addFace(TriMesh*& _mesh, quint32 _index1, quint32 _index2, quint32 _index3) { return addFaceToOpenMesh(_mesh, _index1, _index2, _index3); }
485 int FileVTKPlugin::addFace(PolyMesh*& _mesh, quint32 _index1, quint32 _index2, quint32 _index3) { return addFaceToOpenMesh(_mesh, _index1, _index2, _index3); }
486
487 void FileVTKPlugin::updateVertexNormals(TriMesh*& _mesh) { updateVertexNormalsOfOpenMesh(_mesh); }
488 void FileVTKPlugin::updateVertexNormals(PolyMesh*& _mesh) { updateVertexNormalsOfOpenMesh(_mesh); }
489
490 void FileVTKPlugin::removeTemporaryProperties(TriMesh*& _mesh) { removeTemporaryPropertiesOfOpenMesh(_mesh); }
491 void FileVTKPlugin::removeTemporaryProperties(PolyMesh*& _mesh) { removeTemporaryPropertiesOfOpenMesh(_mesh); }
492
493 void FileVTKPlugin::addVertexNormal(TriMesh*& _mesh, quint32 _index, OpenMesh::Vec3d _normal) { addVertexNormalToOpenMesh(_mesh, _index, _normal); }
494 void FileVTKPlugin::addVertexNormal(PolyMesh*& _mesh, quint32 _index, OpenMesh::Vec3d _normal) { addVertexNormalToOpenMesh(_mesh, _index, _normal); }
495
496 void FileVTKPlugin::addFaceNormal(TriMesh*& _mesh, quint32 _index, OpenMesh::Vec3d _normal) { addFaceNormalToOpenMesh(_mesh, _index, _normal); }
497 void FileVTKPlugin::addFaceNormal(PolyMesh*& _mesh, quint32 _index, OpenMesh::Vec3d _normal) { addFaceNormalToOpenMesh(_mesh, _index, _normal); }
498
499 void FileVTKPlugin::setNormalsOfDuplicatedVertices(TriMesh*& _mesh) { setNormalsOfDuplicatedVerticesOfOpenMesh(_mesh); }
500 void FileVTKPlugin::setNormalsOfDuplicatedVertices(PolyMesh*& _mesh) { setNormalsOfDuplicatedVerticesOfOpenMesh(_mesh); }
501
502 bool FileVTKPlugin::writeASCIIData(std::ostream &_out, TriMesh &_mesh) { return writeASCIIDataOfOpenMesh(_out, _mesh); }
503 bool FileVTKPlugin::writeASCIIData(std::ostream &_out, PolyMesh &_mesh) { return writeASCIIDataOfOpenMesh(_out, _mesh); }
504
505
506 #ifdef ENABLE_OPENVOLUMEMESH_SUPPORT
507
508 template <typename MeshT>
509 int FileVTKPlugin::addTetraCellToOpenVolumeMesh(MeshT _mesh, std::vector<quint32> _indices)
510 {
511 if (_indices.size() != 4)
512 { /*emit log(LOGWARN,tr("Unsupported Cell Type Tetra") );*/ }
513
514 std::vector< std::vector<OpenVolumeMesh::VertexHandle> > faces;
515 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
516 faces[0].push_back(_indices[0]);
517 faces[0].push_back(_indices[1]);
518 faces[0].push_back(_indices[2]);
519 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
520 faces[1].push_back(_indices[0]);
521 faces[1].push_back(_indices[3]);
522 faces[1].push_back(_indices[1]);
523 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
524 faces[2].push_back(_indices[1]);
525 faces[2].push_back(_indices[3]);
526 faces[2].push_back(_indices[2]);
527 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
528 faces[3].push_back(_indices[0]);
529 faces[3].push_back(_indices[2]);
530 faces[3].push_back(_indices[3]);
531
532 std::vector<OpenVolumeMesh::HalfFaceHandle> halffacehandles;
533 for (unsigned int i = 0; i < faces.size(); i++)
534 halffacehandles.push_back(_mesh->halfface(faces[i]));
535
536 for (unsigned int i = 0; i < halffacehandles.size(); i++)
537 if (halffacehandles[i] == OpenVolumeMesh::HalfFaceHandle(-1))
538 {
539 // face didn't exist
540 OpenVolumeMesh::FaceHandle fh = _mesh->add_face(faces[i]);
541 halffacehandles[i] = _mesh->halfface_handle(fh, 0);
542 }
543
544 return _mesh->add_cell(halffacehandles).idx();
545
546 }
547
548 template <typename MeshT>
549 int FileVTKPlugin::addHexaCellToOpenVolumeMesh(MeshT _mesh, std::vector<quint32> _indices)
550 {
551 if (_indices.size() != 8)
552 { emit log(LOGWARN,tr("Expected 8 indices to add Hexahedron but got %1").arg(_indices.size()) ); }
553
554 std::vector< std::vector<OpenVolumeMesh::VertexHandle> > faces;
555 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
556 faces[0].push_back(_indices[0]);
557 faces[0].push_back(_indices[1]);
558 faces[0].push_back(_indices[2]);
559 faces[0].push_back(_indices[3]);
560 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
561 faces[1].push_back(_indices[0]);
562 faces[1].push_back(_indices[4]);
563 faces[1].push_back(_indices[5]);
564 faces[1].push_back(_indices[1]);
565 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
566 faces[2].push_back(_indices[0]);
567 faces[2].push_back(_indices[3]);
568 faces[2].push_back(_indices[7]);
569 faces[2].push_back(_indices[4]);
570 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
571 faces[3].push_back(_indices[1]);
572 faces[3].push_back(_indices[5]);
573 faces[3].push_back(_indices[6]);
574 faces[3].push_back(_indices[2]);
575 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
576 faces[4].push_back(_indices[2]);
577 faces[4].push_back(_indices[6]);
578 faces[4].push_back(_indices[7]);
579 faces[4].push_back(_indices[3]);
580 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
581 faces[5].push_back(_indices[4]);
582 faces[5].push_back(_indices[7]);
583 faces[5].push_back(_indices[6]);
584 faces[5].push_back(_indices[5]);
585
586 std::vector<OpenVolumeMesh::HalfFaceHandle> halffacehandles;
587 for (unsigned int i = 0; i < faces.size(); i++)
588 halffacehandles.push_back(_mesh->halfface(faces[i]));
589
590 for (unsigned int i = 0; i < halffacehandles.size(); i++)
591 if (halffacehandles[i] == OpenVolumeMesh::HalfFaceHandle(-1))
592 {
593 // face didn't exist
594 OpenVolumeMesh::FaceHandle fh = _mesh->add_face(faces[i]);
595 halffacehandles[i] = _mesh->halfface_handle(fh, 0);
596 }
597
598 return _mesh->add_cell(halffacehandles).idx();
599 }
600
601 template <typename MeshT>
602 int FileVTKPlugin::addWedgeCellToOpenVolumeMesh(MeshT _mesh, std::vector<quint32> _indices)
603 {
604 if (_indices.size() != 6)
605 { emit log(LOGWARN,tr("Expected 6 indices to add Hexahedron but got %1").arg(_indices.size()) ); }
606
607 std::vector< std::vector<OpenVolumeMesh::VertexHandle> > faces;
608 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
609 faces[0].push_back(_indices[0]);
610 faces[0].push_back(_indices[1]);
611 faces[0].push_back(_indices[4]);
612 faces[0].push_back(_indices[3]);
613 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
614 faces[1].push_back(_indices[0]);
615 faces[1].push_back(_indices[2]);
616 faces[1].push_back(_indices[1]);
617 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
618 faces[2].push_back(_indices[3]);
619 faces[2].push_back(_indices[4]);
620 faces[2].push_back(_indices[5]);
621 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
622 faces[3].push_back(_indices[0]);
623 faces[3].push_back(_indices[3]);
624 faces[3].push_back(_indices[5]);
625 faces[3].push_back(_indices[2]);
626 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
627 faces[4].push_back(_indices[1]);
628 faces[4].push_back(_indices[2]);
629 faces[4].push_back(_indices[5]);
630 faces[4].push_back(_indices[4]);
631
632 std::vector<OpenVolumeMesh::HalfFaceHandle> halffacehandles;
633 for (unsigned int i = 0; i < faces.size(); i++)
634 halffacehandles.push_back(_mesh->halfface(faces[i]));
635
636 for (unsigned int i = 0; i < halffacehandles.size(); i++)
637 if (halffacehandles[i] == OpenVolumeMesh::HalfFaceHandle(-1))
638 {
639 // face didn't exist
640 OpenVolumeMesh::FaceHandle fh = _mesh->add_face(faces[i]);
641 halffacehandles[i] = _mesh->halfface_handle(fh, 0);
642 }
643
644 return _mesh->add_cell(halffacehandles).idx();
645 }
646
647 template <typename MeshT>
648 int FileVTKPlugin::addPyramidCellToOpenVolumeMesh(MeshT _mesh, std::vector<quint32> _indices)
649 {
650 if (_indices.size() != 6)
651 { emit log(LOGWARN,tr("Expected 6 indices to add Hexahedron but got %1").arg(_indices.size()) ); }
652
653 std::vector< std::vector<OpenVolumeMesh::VertexHandle> > faces;
654 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
655 faces[0].push_back(_indices[0]);
656 faces[0].push_back(_indices[1]);
657 faces[0].push_back(_indices[2]);
658 faces[0].push_back(_indices[3]);
659 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
660 faces[1].push_back(_indices[0]);
661 faces[1].push_back(_indices[4]);
662 faces[1].push_back(_indices[1]);
663 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
664 faces[2].push_back(_indices[0]);
665 faces[2].push_back(_indices[3]);
666 faces[2].push_back(_indices[4]);
667 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
668 faces[3].push_back(_indices[2]);
669 faces[3].push_back(_indices[4]);
670 faces[3].push_back(_indices[3]);
671 faces.push_back(std::vector<OpenVolumeMesh::VertexHandle>());
672 faces[4].push_back(_indices[1]);
673 faces[4].push_back(_indices[4]);
674 faces[4].push_back(_indices[2]);
675
676 std::vector<OpenVolumeMesh::HalfFaceHandle> halffacehandles;
677 for (unsigned int i = 0; i < faces.size(); i++)
678 halffacehandles.push_back(_mesh->halfface(faces[i]));
679
680 for (unsigned int i = 0; i < halffacehandles.size(); i++)
681 if (halffacehandles[i] == OpenVolumeMesh::HalfFaceHandle(-1))
682 {
683 // face didn't exist
684 OpenVolumeMesh::FaceHandle fh = _mesh->add_face(faces[i]);
685 halffacehandles[i] = _mesh->halfface_handle(fh, 0);
686 }
687
688 return _mesh->add_cell(halffacehandles).idx();
689 }
690
691 template <typename MeshT>
692 int FileVTKPlugin::addFaceToOpenVolumeMesh(MeshT*& _mesh, std::vector<quint32> _indices)
693 {
694 if (_indices.size() < 3)
695 { emit log(LOGWARN,tr("Expected at least 3 indices to add a face but got %1").arg(_indices.size()) ); }
696
697 std::vector<OpenVolumeMesh::VertexHandle> face;
698 for (unsigned int i = 0; i < _indices.size(); i++)
699 face.push_back(OpenVolumeMesh::VertexHandle(_indices[i]));
700
701
702 OpenVolumeMesh::HalfFaceHandle halffacehandle;
703 halffacehandle = _mesh->halfface(face);
704 if (halffacehandle == -1) // face didn't exist
705 {
706 OpenVolumeMesh::FaceHandle fh = _mesh->add_face(face).idx();
707 halffacehandle = _mesh->halfface_handle(fh, 0);
708 }
709 return halffacehandle.idx();
710 }
711
712 template <typename MeshT>
713 int FileVTKPlugin::addFaceToOpenVolumeMesh(MeshT*& _mesh, quint32 _index1, quint32 _index2, quint32 _index3)
714 {
715 std::vector<OpenVolumeMesh::VertexHandle> face;
716 face.push_back(OpenVolumeMesh::VertexHandle(_index1));
717 face.push_back(OpenVolumeMesh::VertexHandle(_index2));
718 face.push_back(OpenVolumeMesh::VertexHandle(_index3));
719
720 OpenVolumeMesh::HalfFaceHandle halffacehandle;
721 halffacehandle = _mesh->halfface(face);
722 if (halffacehandle == -1) // face didn't exist
723 {
724 OpenVolumeMesh::FaceHandle fh = _mesh->add_face(face).idx();
725 halffacehandle = _mesh->halfface_handle(fh, 0);
726 }
727 return halffacehandle.idx();
728 }
729
730 template <typename MeshT>
731 void FileVTKPlugin::addVertexNormalToOpenVolumeMesh(MeshT _mesh, quint32 _index, OpenMesh::Vec3d _normal)
732 {
733 OpenVolumeMesh::VertexPropertyT< typename OpenMesh::Vec3d > vertexNormals = _mesh->template request_vertex_property< typename OpenMesh::Vec3d >("vertex_normals");
734 vertexNormals[OpenVolumeMesh::VertexHandle(_index)] = _normal;
735 }
736
737 template <typename MeshT>
738 void FileVTKPlugin::addFaceNormalToOpenVolumeMesh(MeshT _mesh, quint32 _index, OpenMesh::Vec3d _normal)
739 {
740 OpenVolumeMesh::FacePropertyT< OpenMesh::Vec3d > faceNormals = _mesh->template request_face_property< OpenMesh::Vec3d >("face_normals");
741
742 OpenVolumeMesh::HalfFaceHandle hfh = OpenVolumeMesh::HalfFaceHandle(_index);
743 OpenVolumeMesh::FaceHandle fh = _mesh->face_handle(hfh);
744 if (hfh == _mesh->halfface_handle(fh, 0))
745 faceNormals[_mesh->face_handle(_index)] = _normal;
746 else
747 faceNormals[_mesh->face_handle(_index)] = -_normal;
748
749 }
750
751 template <typename MeshT>
752 int getCellType(MeshT& _mesh, OpenVolumeMesh::CellHandle _cellHandle)
753 {
754 int incidentFaces = _mesh.cell(_cellHandle).halffaces().size();
755 int incidentVertices = 0;
756 for (OpenVolumeMesh::CellVertexIter cvit = OpenVolumeMesh::CellVertexIter(_cellHandle, &_mesh); cvit.valid(); ++cvit)
757 incidentVertices++;
758
759 if ((incidentFaces == 4) && (incidentVertices == 4))
760 return 10; // tetra
761 else if ((incidentFaces == 6) && (incidentVertices == 8))
762 return 12; // hexahedron
763 else if ((incidentFaces == 5) && (incidentVertices == 6))
764 return 13; // wedge
765 else if ((incidentFaces == 5) && (incidentVertices == 5))
766 return 14; // pyramid
767 else
768 return -1;
769 }
770
771 template <typename MeshT>
772 int getCellType(MeshT& _mesh, OpenVolumeMesh::FaceHandle _faceHandle)
773 {
774 std::vector<OpenVolumeMesh::HalfEdgeHandle> halfedges = _mesh.face(_faceHandle).halfedges();
775 if (halfedges.size() == 3)
776 return 5; // triangle;
777 else
778 return 7; // polygon
779 }
780
781 template <typename MeshT>
782 std::vector<int> getCellVertexIndices(MeshT& _mesh, OpenVolumeMesh::CellHandle _cellHandle, int _cellType)
783 {
784 if (_cellType == 10) //tetra
785 {
786 // first three vertices are the three vertices of an arbitrary face
787 // the last vertex is the one that is left
788 OpenVolumeMesh::OpenVolumeMeshCell cell = _mesh.cell(_cellHandle);
789 OpenVolumeMesh::OpenVolumeMeshFace face = _mesh.halfface(cell.halffaces()[0]);
790 std::vector<OpenVolumeMesh::HalfEdgeHandle> halfedges = face.halfedges();
791 std::vector<int> indices;
792 for (unsigned int i = 0; i < halfedges.size(); i++)
793 indices.push_back(_mesh.halfedge(halfedges[i]).from_vertex().idx());
794 for (OpenVolumeMesh::CellVertexIter cvit = OpenVolumeMesh::CellVertexIter(_cellHandle, &_mesh); cvit.valid(); ++cvit)
795 if ((cvit->idx() != indices[0]) && ((*cvit).idx() != indices[1]) && ((*cvit).idx() != indices[2]))
796 indices.push_back(cvit->idx());
797 return indices;
798 }
799 else if (_cellType == 12) // hexahedron
800 {
801 // take an arbitrary face and add its vertices
802 OpenVolumeMesh::OpenVolumeMeshCell cell = _mesh.cell(_cellHandle);
803 OpenVolumeMesh::HalfFaceHandle hfh = cell.halffaces()[0];
804 OpenVolumeMesh::OpenVolumeMeshFace face = _mesh.halfface(hfh);
805 OpenVolumeMesh::HalfEdgeHandle heh = face.halfedges()[0];
806 std::vector<int> indices;
807 for (unsigned int i = 0; i < 4; i++)
808 {
809 OpenVolumeMesh::OpenVolumeMeshEdge edge = _mesh.halfedge(heh);
810 indices.push_back(edge.from_vertex().idx());
811 heh = _mesh.next_halfedge_in_halfface(heh, hfh);
812 }
813 // we now added four vertices and heh is a handle to the edge coming out of the first added vertex
814 // we will now navigate to the oppsite face
815 OpenVolumeMesh::HalfFaceHandle intermediateHalfFaceHandle = _mesh.adjacent_halfface_in_cell(hfh, heh);
816 heh = _mesh.opposite_halfedge_handle(heh);
817 heh = _mesh.next_halfedge_in_halfface(heh, intermediateHalfFaceHandle);
818 heh = _mesh.next_halfedge_in_halfface(heh, intermediateHalfFaceHandle);
819 OpenVolumeMesh::HalfFaceHandle oppositeHalfFaceHandle = _mesh.adjacent_halfface_in_cell(intermediateHalfFaceHandle, heh);
820 heh = _mesh.opposite_halfedge_handle(heh);
821 // heh is now the halfedge pointing to vertex 4 and lies in the opposite half face.
822 // we now have to add the four vertices of that face but in clockwise order
823 for (unsigned int i = 0; i < 4; i++)
824 {
825 OpenVolumeMesh::OpenVolumeMeshEdge edge = _mesh.halfedge(heh);
826 indices.push_back(edge.to_vertex().idx());
827 heh = _mesh.prev_halfedge_in_halfface(heh, oppositeHalfFaceHandle);
828 }
829 return indices;
830 }
831 else if (_cellType == 13) // wedge
832 {
833 // take a face with three vertices and add its vertices in clockwise order
834 OpenVolumeMesh::OpenVolumeMeshCell cell = _mesh.cell(_cellHandle);
835 OpenVolumeMesh::HalfFaceHandle hfh;
836 for (unsigned int i = 0; i < cell.halffaces().size(); i++)
837 if (_mesh.halfface(cell.halffaces()[i]).halfedges().size() == 3)
838 hfh = cell.halffaces()[i];
839 OpenVolumeMesh::OpenVolumeMeshFace face = _mesh.halfface(hfh);
840 OpenVolumeMesh::HalfEdgeHandle heh = face.halfedges()[0];
841 std::vector<int> indices;
842 for (unsigned int i = 0; i < 3; i++)
843 {
844 OpenVolumeMesh::OpenVolumeMeshEdge edge = _mesh.halfedge(heh);
845 indices.push_back(edge.from_vertex().idx());
846 heh = _mesh.prev_halfedge_in_halfface(heh, hfh);
847 }
848 // we now added three vertices and heh is a handle to the edge coming out of the first added vertex
849 // we will now navigate to the oppsite face
850 OpenVolumeMesh::HalfFaceHandle intermediateHalfFaceHandle = _mesh.adjacent_halfface_in_cell(hfh, heh);
851 heh = _mesh.opposite_halfedge_handle(heh);
852 heh = _mesh.next_halfedge_in_halfface(heh, intermediateHalfFaceHandle);
853 heh = _mesh.next_halfedge_in_halfface(heh, intermediateHalfFaceHandle);
854 OpenVolumeMesh::HalfFaceHandle oppositeHalfFaceHandle = _mesh.adjacent_halfface_in_cell(intermediateHalfFaceHandle, heh);
855 heh = _mesh.opposite_halfedge_handle(heh);
856 // heh is now the halfedge pointing to vertex 3 and lies in the opposite half face.
857 // we now have to add the three vertices of that face but in counter clockwise order
858 for (unsigned int i = 0; i < 3; i++)
859 {
860 OpenVolumeMesh::OpenVolumeMeshEdge edge = _mesh.halfedge(heh);
861 indices.push_back(edge.to_vertex().idx());
862 heh = _mesh.next_halfedge_in_halfface(heh, oppositeHalfFaceHandle);
863 }
864 return indices;
865
866 }
867 else if (_cellType == 14) // pyramid
868 {
869 // the first four vertices are the for vertices of the face with for vertices
870 // the other vertex is the one that is left
871 OpenVolumeMesh::OpenVolumeMeshCell cell = _mesh.cell(_cellHandle);
872 std::vector<OpenVolumeMesh::HalfFaceHandle> halffaces = cell.halffaces();
873 OpenVolumeMesh::OpenVolumeMeshFace face = _mesh.halfface(halffaces[0]);
874 for (unsigned int i = 0; i < halffaces.size(); i++)
875 if (_mesh.halfface(halffaces[i]).halfedges().size() == 4)
876 face = _mesh.halfface(halffaces[i]);
877 std::vector<OpenVolumeMesh::HalfEdgeHandle> halfedges = face.halfedges();
878 std::vector<int> indices;
879 for (unsigned int i = 0; i < halfedges.size(); i++)
880 indices.push_back(_mesh.halfedge(halfedges[i]).from_vertex().idx());
881 for (OpenVolumeMesh::CellVertexIter cvit = OpenVolumeMesh::CellVertexIter(_cellHandle, &_mesh); cvit.valid(); ++cvit)
882 if ((cvit->idx() != indices[0]) && ((*cvit).idx() != indices[1]) && ((*cvit).idx() != indices[2]) && ((*cvit).idx() != indices[3]))
883 indices.push_back(cvit->idx());
884 return indices;
885 }
886 else // unsupported type
887 return std::vector<int>();
888 }
889
890 template <typename MeshT>
891 bool FileVTKPlugin::writeASCIIDataOfOpenVolumeMesh(std::ostream& _out, MeshT& _mesh)
892 {
893 if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0)
894 _out.precision(savePrecision_->value());
895
896 _out << "DATASET UNSTRUCTURED_GRID\n";
897
898
899 // save all vertices
900
901 OpenVolumeMesh::VertexIter vit = _mesh.vertices_begin();
902 OpenVolumeMesh::VertexIter end_vit = _mesh.vertices_end();
903 _out << "POINTS " << _mesh.n_vertices() << " float\n";
904 for (; vit != end_vit; ++vit) {
905 // Write vertex p[0] p[1] p[2]
906 ACG::Vec3d p = _mesh.vertex(*vit);
907 _out << p[0] << " " << p[1] << " " << p[2];
908 _out << "\n";
909 }
910
911
912
913 // Remember which faces have been added, so we can later save the isolated faces.
914 OpenVolumeMesh::FacePropertyT<bool> fpAlreadyStored = _mesh.template request_face_property<bool>();
915
916 // Remember which edges have been added, so we can later save the isolated edges;
917 OpenVolumeMesh::EdgePropertyT<bool> epAlreadyStored = _mesh.template request_edge_property<bool>();
918
919 int cellCount = 0;
920
921 // count the cell list size (for each cell: 1 + adjacent vertices)
922
923 quint32 listSize = 0;
924 for (OpenVolumeMesh::CellIter cit = _mesh.cells_begin(); cit != _mesh.cells_end(); ++cit)
925 {
926 int cellType = getCellType(_mesh, *cit);
927
928 if (cellType == 10 )
929 listSize += 1 + 4;
930 else if (cellType == 12 )
931 listSize += 1 + 8;
932 else if (cellType == 13 )
933 listSize += 1 + 6;
934 else if (cellType == 14 )
935 listSize += 1 + 5;
936 else // type not supported by vtk file -> ignore
937 continue;
938
939 cellCount++;
940
941 std::vector<OpenVolumeMesh::HalfFaceHandle> halffaces = _mesh.cell(*cit).halffaces();
942 for (unsigned int i = 0; i < halffaces.size(); i++)
943 {
944 OpenVolumeMesh::FaceHandle fh = _mesh.face_handle(halffaces[i]);
945 if (!(fpAlreadyStored[fh]))
946 {
947 // mark this face and its edges as already stored
948 // if the user wants to save face normals we cannot skip adding the faces
949 if (!(userWriteOptions_ & FileVTKPlugin::FACENORMALS))
950 fpAlreadyStored[fh] = true;
951 //mark the edges as already added.
952 OpenVolumeMesh::OpenVolumeMeshFace face = _mesh.halfface(halffaces[i]);
953 for (std::vector<OpenVolumeMesh::HalfEdgeHandle>::const_iterator heit = face.halfedges().begin();
954 heit != face.halfedges().end();
955 ++heit)
956 {
957 epAlreadyStored[_mesh.edge_handle(*heit)] = true;
958 }
959 }
960 }
961 }
962
963 for (OpenVolumeMesh::FaceIter fit = _mesh.faces_begin(); fit != _mesh.faces_end(); ++fit)
964 {
965 if (!(fpAlreadyStored[*fit]))
966 {
967 //mark edges as already stored
968 std::vector<OpenVolumeMesh::HalfEdgeHandle> halfedges = _mesh.face(*fit).halfedges();
969 for (unsigned int i = 0; i < halfedges.size(); i++)
970 epAlreadyStored[_mesh.edge_handle(halfedges[i])] = true;
971
972 // number of incident vertices == number of incident halfedges
973 listSize += 1 + halfedges.size();
974
975 cellCount++;
976 }
977 }
978
979 for (OpenVolumeMesh::EdgeIter eit = _mesh.edges_begin(); eit != _mesh.edges_end(); ++eit)
980 {
981 if (!(epAlreadyStored[*eit]))
982 {
983 listSize += 1 + 2;
984 cellCount++;
985 }
986 }
987
988 _out << "CELLS " << cellCount << " " << listSize << "\n";
989
990
991 // save all cellCells.
992
993 for (OpenVolumeMesh::CellIter cit = _mesh.cells_begin(); cit != _mesh.cells_end(); ++cit)
994 {
995 //std::vector<OpenVolumeMesh::VertexHandle> vertices;
996
997 int cellType = getCellType(_mesh, *cit);
998
999 // TODO:
1000 if (cellType == 10 )
1001 listSize += 1 + 4;
1002 else if (cellType == 12 )
1003 listSize += 1 + 8;
1004 else if (cellType == 13 )
1005 listSize += 1 + 6;
1006 else if (cellType == 14 )
1007 listSize += 1 + 5;
1008 else // type not supported by vtk file -> ignore
1009 continue;
1010
1011 if (cellType == -1)// type not supported by vtk file -> ignore
1012 continue;
1013 else
1014 {
1015 std::vector<int> indices = getCellVertexIndices(_mesh, *cit, cellType);
1016 _out << indices.size();
1017 for (unsigned int i = 0; i < indices.size(); i++)
1018 _out << " " << indices[i];
1019 _out << "\n";
1020 }
1021
1022 }
1023
1024 // save isolated faces
1025
1026 for (OpenVolumeMesh::FaceIter fit = _mesh.faces_begin(); fit != _mesh.faces_end(); ++fit)
1027 {
1028 if (!(fpAlreadyStored[*fit]))
1029 {
1030 std::vector<OpenVolumeMesh::HalfEdgeHandle> halfedges = _mesh.face(*fit).halfedges();
1031
1032 _out << halfedges.size();
1033 for (unsigned int i = 0; i < halfedges.size(); i++)
1034 {
1035 OpenVolumeMesh::HalfEdgeHandle heh = halfedges[i];
1036 OpenVolumeMesh::OpenVolumeMeshEdge edge = _mesh.halfedge(heh);
1037 _out << " " << edge.from_vertex().idx();
1038 }
1039 _out << "\n";
1040 }
1041 }
1042
1043
1044 // save isolated edges
1045
1046
1047 for (OpenVolumeMesh::EdgeIter eit = _mesh.edges_begin(); eit != _mesh.edges_end(); ++eit)
1048 {
1049 if (!(epAlreadyStored[*eit]))
1050 {
1051 OpenVolumeMesh::OpenVolumeMeshEdge edge = _mesh.edge(*eit);
1052 _out << "2";
1053 _out << " " << edge.from_vertex().idx();
1054 _out << " " << edge.to_vertex().idx();
1055 _out << "\n";
1056 }
1057 }
1058
1059
1060
1061 // write cell types to file
1062
1063 _out << "CELL_TYPES " << cellCount << "\n";
1064
1065 // cell cellTypes
1066 for (OpenVolumeMesh::CellIter cit = _mesh.cells_begin(); cit != _mesh.cells_end(); ++cit)
1067 {
1068 int cellType = getCellType(_mesh, *cit);
1069 if (cellType == -1) //type not supported by vtk file, so this cell was not added
1070 continue;
1071 else
1072 _out << cellType << "\n";
1073 }
1074
1075 // face cell types
1076
1077 for (OpenVolumeMesh::FaceIter fit = _mesh.faces_begin(); fit != _mesh.faces_end(); ++fit)
1078 {
1079 if (!(fpAlreadyStored[*fit]))
1080 {
1081 int cellType = getCellType(_mesh,*fit);
1082 if (cellType == -1) //type not supported by vtk file, so this cell was not added
1083 continue;
1084 else
1085 _out << cellType << "\n";
1086 }
1087 }
1088
1089
1090 // edge cell type
1091 for (OpenVolumeMesh::EdgeIter eit = _mesh.edges_begin(); eit != _mesh.edges_end(); ++eit)
1092 {
1093 if (!(epAlreadyStored[*eit]))
1094 {
1095 // all edges have type 3
1096 _out << "2\n";
1097 }
1098 }
1099
1100
1101
1102 //*************//
1103 //OPTIONAL DATA//
1104 //*************//
1105
1106 //writing of tex coords also not supported yet.
1107
1108
1109 //Write vertex normals
1110 if ((userWriteOptions_ & FileVTKPlugin::VERTEXNORMALS))
1111 {
1112 _out << "POINT_DATA "<< _mesh.n_vertices() << "\n";
1113
1114 OpenVolumeMesh::VertexPropertyT< typename OpenMesh::Vec3d > vertexNormals = _mesh.template request_vertex_property< typename OpenMesh::Vec3d >("vertex_normals");
1115 _out << "NORMALS vertex_normals float\n";
1116 for (OpenVolumeMesh::VertexIter vit = _mesh.vertices_begin(); vit != _mesh.vertices_end(); ++vit) {
1117 typename OpenMesh::Vec3d n = vertexNormals[*vit];
1118 _out << n[0] << " " << n[1] << " " << n[2];
1119 _out << "\n";
1120 }
1121 }
1122
1123
1124 //Write face normals
1125 if ((userWriteOptions_ & FileVTKPlugin::FACENORMALS))
1126 {
1127 _out << "CELL_DATA "<< cellCount << "\n";
1128 _out << "NORMALS face_normals float\n";
1129 // write dummy normal for cells
1130
1131 for (OpenVolumeMesh::CellIter cit = _mesh.cells_begin(); cit != _mesh.cells_end(); ++cit)
1132 {
1133 int cellType = getCellType(_mesh, *cit);
1134
1135 if (cellType == -1 )// type not supported by vtk file -> ignore
1136 continue;
1137 else
1138 {
1139 _out << 1 << " " << 0 << " " << 0;
1140 _out << "\n";
1141 }
1142 }
1143
1144
1145 // write face normals
1146 OpenVolumeMesh::FacePropertyT< typename OpenMesh::Vec3d > faceNormals = _mesh.template request_face_property< typename OpenMesh::Vec3d >("face_normals");
1147
1148 for (OpenVolumeMesh::FaceIter fit = _mesh.faces_begin(); fit != _mesh.faces_end(); ++fit) {
1149 typename OpenMesh::Vec3d n = faceNormals[*fit];
1150 _out << n[0] << " " << n[1] << " " << n[2];
1151 _out << "\n";
1152 }
1153
1154
1155 // write dummy normals for edges
1156 for (OpenVolumeMesh::EdgeIter eit = _mesh.edges_begin(); eit != _mesh.edges_end(); ++eit)
1157 {
1158 if (!(epAlreadyStored[*eit]))
1159 {
1160 _out << 1 << " " << 0 << " " << 0;
1161 _out << "\n";
1162 }
1163 }
1164
1165
1166 }
1167
1168 return true;
1169 }
1170
1171 #endif //ENABLE_OPENVOLUMEMESH_SUPPORT
1172
1173 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1174 int FileVTKPlugin::addTetraCell(HexahedralMesh*& _mesh, std::vector<quint32> indices) { return addTetraCellToOpenVolumeMesh(_mesh, indices); }
1175 int FileVTKPlugin::addHexaCell(HexahedralMesh*& _mesh, std::vector<quint32> indices) { return addHexaCellToOpenVolumeMesh(_mesh, indices); }
1176 int FileVTKPlugin::addWedgeCell(HexahedralMesh*& _mesh, std::vector<quint32> indices) { return addWedgeCellToOpenVolumeMesh(_mesh, indices); }
1177 int FileVTKPlugin::addPyramidCell(HexahedralMesh*& _mesh, std::vector<quint32> indices) { return addPyramidCellToOpenVolumeMesh(_mesh, indices); }
1178 int FileVTKPlugin::addFace(HexahedralMesh*& _mesh, std::vector<quint32> indices) { return addFaceToOpenVolumeMesh(_mesh, indices); }
1179 int FileVTKPlugin::addFace(HexahedralMesh*& _mesh, quint32 _index1, quint32 _index2, quint32 _index3) { return addFaceToOpenVolumeMesh(_mesh, _index1, _index2, _index3); }
1180 void FileVTKPlugin::addVertexNormal(HexahedralMesh*& _mesh, quint32 _index, OpenMesh::Vec3d _normal) { addVertexNormalToOpenVolumeMesh(_mesh, _index, _normal); }
1181 void FileVTKPlugin::addFaceNormal(HexahedralMesh*& _mesh, quint32 _index, OpenMesh::Vec3d _normal) { addFaceNormalToOpenVolumeMesh(_mesh, _index, _normal); }
1182 bool FileVTKPlugin::writeASCIIData(std::ostream& _out, HexahedralMesh& _mesh) { return writeASCIIDataOfOpenVolumeMesh(_out, _mesh); }
1183 #endif //ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1184
1185
1186 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1187 int FileVTKPlugin::addTetraCell(PolyhedralMesh*& _mesh, std::vector<quint32> indices) { return addTetraCellToOpenVolumeMesh(_mesh, indices); }
1188 int FileVTKPlugin::addHexaCell(PolyhedralMesh*& _mesh, std::vector<quint32> indices) { return addHexaCellToOpenVolumeMesh(_mesh, indices); }
1189 int FileVTKPlugin::addWedgeCell(PolyhedralMesh*& _mesh, std::vector<quint32> indices) { return addWedgeCellToOpenVolumeMesh(_mesh, indices); }
1190 int FileVTKPlugin::addPyramidCell(PolyhedralMesh*& _mesh, std::vector<quint32> indices) { return addPyramidCellToOpenVolumeMesh(_mesh, indices); }
1191 int FileVTKPlugin::addFace(PolyhedralMesh*& _mesh, std::vector<quint32> indices) { return addFaceToOpenVolumeMesh(_mesh, indices); }
1192 int FileVTKPlugin::addFace(PolyhedralMesh*& _mesh, quint32 _index1, quint32 _index2, quint32 _index3) { return addFaceToOpenVolumeMesh(_mesh, _index1, _index2, _index3); }
1193 void FileVTKPlugin::addVertexNormal(PolyhedralMesh*& _mesh, quint32 _index, OpenMesh::Vec3d _normal) { addVertexNormalToOpenVolumeMesh(_mesh, _index, _normal); }
1194 void FileVTKPlugin::addFaceNormal(PolyhedralMesh*& _mesh, quint32 _index, OpenMesh::Vec3d _normal) { addFaceNormalToOpenVolumeMesh(_mesh, _index, _normal); }
1195 bool FileVTKPlugin::writeASCIIData(std::ostream& _out, PolyhedralMesh& _mesh) { return writeASCIIDataOfOpenVolumeMesh(_out, _mesh); }
1196 #endif //ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1197
1198 //-----------------------------------------------------------------------------------------------------
1199 //-----------------------------------------------------------------------------------------------------
1200 //----------------------------------- end of cool helper function -------------------------------------
1201 //-----------------------------------------------------------------------------------------------------
1202 //-----------------------------------------------------------------------------------------------------
1203
1204 FileVTKPlugin::BestMeshType FileVTKPlugin::findBestObjectType(QString _filename)
1205 {
1206 QFile file(_filename);
1207
1208 if ( !file.open(QIODevice::ReadOnly) ) {
1209 return BMT_None;
1210 }
1211
1212 QTextStream in(&file);
1213
1214 QString line = in.readLine();
1215
1216 QStringList header = line.split(" ",QString::SkipEmptyParts);
1217 if ( header.size() != 5 ) {
1218 return BMT_None;
1219 }
1220
1221 QString version = header[4];
1222
1223 header.removeLast();
1224
1225 QString magic = header.join(" ");
1226
1227 if ( magic != "# vtk DataFile Version" ) {
1228 return BMT_None;
1229 }
1230
1231 QString description = in.readLine();
1232
1233 QString fileTypeStr = in.readLine();
1234
1235 fileTypeStr = fileTypeStr.simplified();
1236
1237 if ( fileTypeStr.toLower() == "binary" ) {
1238 binary_ = true;
1239 } else if ( fileTypeStr.toLower() == "ascii" ) {
1240 binary_ = false;
1241 } else {
1242 return BMT_None;
1243 }
1244
1245 line = "";
1246
1247 while ( line.simplified() == "" )
1248 line = in.readLine();
1249
1250 QStringList datasetList = line.split(" ",QString::SkipEmptyParts);
1251
1252 if ( datasetList.size() != 2 ) {
1253 return BMT_None;
1254 }
1255
1256 Dataset dataset;
1257
1258 datasetList[1] = datasetList[1].simplified();
1259
1260 if ( datasetList[1] == "STRUCTURED_POINTS" )
1261 dataset = STRUCTURED_POINTS;
1262 else if ( datasetList[1] == "STRUCTURED_GRID" )
1263 dataset = STRUCTURED_GRID;
1264 else if ( datasetList[1] == "RECTILINEAR_GRID" )
1265 dataset = RECTILINEAR_GRID;
1266 else if ( datasetList[1] == "POLYDATA" )
1267 dataset = POLYDATA;
1268 else if ( datasetList[1] == "UNSTRUCTURED_GRID" )
1269 dataset = UNSTRUCTURED_GRID;
1270 else {
1271 return BMT_None;
1272 }
1273
1274
1275 if ((dataset == STRUCTURED_POINTS) || (dataset == STRUCTURED_GRID) || (dataset == RECTILINEAR_GRID) )
1276 {
1277 // Just points so every type is ok. Just use TriMesh. (Apperently these aren't even supported.)
1278 return BMT_TriMesh;
1279 }
1280 else if (dataset == POLYDATA)
1281 {
1282 // The file could contain vertices, lines, polygons, or triangle strips.
1283 // So we will use either TriMesh or PolyMesh.
1284 //
1285 // Test if all polygons are triangles
1286
1287 line = in.readLine();
1288
1289 // Search for line "POLYGONS n size"
1290 while ( !line.contains("POLYGONS") ) {
1291
1292 // stop at end of file!
1293 if ( in.atEnd() ) {
1294 // we didn't find polygons -> all primitives are either vertices, lines or trianglestrips
1295 return BMT_TriMesh;
1296 }
1297
1298 line = in.readLine();
1299 }
1300
1301 QStringList polygonsLine = line.split(" ",QString::SkipEmptyParts);
1302
1303 // It has to contain the Keyword POLYGONS , the number of polygons to read and the total number of values to read ( each polygon: 1 + valence )
1304 if ( polygonsLine.size() != 3 ) {
1305 emit log(LOGERR,tr("Expected to get Points line with exactly 3 entries, but %1 found!").arg(polygonsLine.size()));
1306 return BMT_None;
1307 }
1308
1309 bool ok = true;
1310
1311 // Number of polygons to read
1312 quint32 polygoncount = polygonsLine[1].toUInt(&ok);
1313
1314 if ( ! ok) {
1315 emit log(LOGERR,tr("Expected to get number of points and entries, but read %1 !").arg(polygonsLine.join(" ")));
1316 return BMT_None;
1317 }
1318
1319 quint32 read = 0;
1320 while ( read < polygoncount) {
1321
1322 // Read first integer describing number of indices
1323 quint32 valence;
1324 if ( !binary_ )
1325 in >> valence;
1326 else
1327 in.device()->read((char*)&valence,sizeof(quint32));
1328
1329 if (valence != 3)
1330 {
1331 // Polygone with more than 3 vertices found -> TriMesh not possible
1332 return BMT_PolyMesh;
1333 }
1334
1335 // read rest
1336 quint32 index;
1337
1338 for ( unsigned int i = 0 ; i < valence; ++i ) {
1339
1340 // Read one index
1341 if ( !binary_ )
1342 in >> index;
1343 else
1344 in.device()->read((char*)&valence,sizeof(quint32));
1345 }
1346 ++read;
1347 }
1348
1349 // if we reach this point, all polygons were triangles
1350 return BMT_TriMesh;
1351
1352 }
1353 else /*if (dataset == UNSTRUCTURED_GRID)*/
1354 {
1355 // The file could contain all different kind of primitives.
1356 // We need to check if all of them are triangles.
1357 // If OpenVolumeMesh is supported we additionally check whether there are
1358 // Cell primitives, and if so, whether all of them are hexaherdral.
1359
1360 line = in.readLine();
1361
1362 // Search for line "CELL_TYPES n"
1363 while ( !line.contains("CELL_TYPES") ) {
1364
1365 // stop at end of file!
1366 if ( in.atEnd() ) {
1367 // we didn't find the line "CELL_TYPES n" -> bad file
1368 return BMT_None;
1369 }
1370
1371 line = in.readLine();
1372 }
1373
1374 // Split the header line into components
1375 QStringList cellLine = line.split(" ",QString::SkipEmptyParts);
1376
1377 // It has to contain the Keyword CELL_TYPES , the number of cells to read
1378 if ( cellLine.size() != 2 ) {
1379 emit log(LOGERR,tr("Expected to get CELL_TYPES line with exactly 2 entries, but %1 found!").arg(cellLine.size()));
1380 return BMT_None;
1381 }
1382
1383 bool ok = true;
1384
1385 // Number of cells to read
1386 quint32 cellCountTypes = cellLine[1].toUInt(&ok);
1387
1388 if ( ! ok) {
1389 emit log(LOGERR,tr("Expected to get number of cell types, but read %1 !").arg(cellLine[1]));
1390 return BMT_None;
1391 }
1392
1393 bool triMeshPossible = true;
1394 bool polyMeshPossible = true;
1395
1396 #ifndef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1397 bool hexahedralMeshPossible = false;
1398 #else
1399 bool hexahedralMeshPossible = true;
1400 #endif
1401 #ifndef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1402 bool polyhedralMeshPossible = false;
1403 #else
1404 bool polyhedralMeshPossible = true;
1405 #endif
1406
1407 quint32 read = 0;
1408 while ( read < cellCountTypes) {
1409
1410 // Read first integer describing number of indizes
1411 quint32 type;
1412 if ( !binary_ )
1413 in >> type;
1414 else
1415 in.device()->read((char*)&type,sizeof(quint32));
1416
1417
1418 if (( 1 <= type ) && (type <= 6 ))
1419 {
1420 // vertex, poly vertex, line, poly line, triangle, triangle strip
1421 // all mesh types possible except hexahedral mesh
1422 hexahedralMeshPossible = false;
1423 }
1424 else if (( 7 <= type ) && (type <= 9 ))
1425 {
1426 // polygone, pixel (axis alligned quad), quad -> triMesh not possible
1427 // while polygone could be a triangle as well, we assume that it's not because
1428 // we hope the file author would have chosen type == 5 int that case
1429 triMeshPossible = false;
1430 hexahedralMeshPossible = false;
1431 }
1432 // TODO: ignore if no OpenVolumeMesh support
1433 else if (( 10 == type ) || ( 13 == type ) || (type == 14 ))
1434 {
1435 // tetra, wedge, pyramid
1436 // cannot be represented by anything other than polyhedral mesh
1437 triMeshPossible = false;
1438 polyMeshPossible = false;
1439 hexahedralMeshPossible = false;
1440 }
1441 else if (( 11 == type ) || ( 12 == type ))
1442 {
1443 // voxel, hexahedron
1444 // cannot be represented by open mesh
1445 triMeshPossible = false;
1446 polyMeshPossible = false;
1447 }
1448
1449
1450 if ( in.status() != QTextStream::Ok ) {
1451 emit log(LOGERR,tr("Read corrupted cell type data!"));
1452 return BMT_None;
1453 }
1454 ++read;
1455 }
1456
1457 if (triMeshPossible)
1458 return BMT_TriMesh;
1459 else if (polyMeshPossible)
1460 return BMT_PolyMesh;
1461 else if (hexahedralMeshPossible)
1462 return BMT_HexahedralMesh;
1463 else if (polyhedralMeshPossible)
1464 return BMT_PolyhedralMesh;
1465 else
1466 return BMT_None;
1467
1468 }
1469
1470
1471
1472 }
1473
1474 int FileVTKPlugin::loadObject(QString _filename) {
1475 std::cerr << "Loading vtk file" << std::endl;
1476
1477 BestMeshType bestType = findBestObjectType(_filename);
1478
1479 QFile file(_filename);
1480
1481 if ( !file.open(QIODevice::ReadOnly) ) {
1482 emit log(LOGERR,"Unable to open vtk file!");
1483 return -1;
1484 }
1485
1486 QTextStream in(&file);
1487
1488 std::cerr << "File is open!" << std::endl;
1489
1490 QString line = in.readLine();
1491
1492 std::cerr << "Got line: " << std::endl;
1493 std::cerr << line.toStdString() << std::endl;
1494
1495 QStringList header = line.split(" ",QString::SkipEmptyParts);
1496
1497 if ( header.size() != 5 ) {
1498 emit log(LOGERR,tr("Bad VTK header? ") + line);
1499 return -1;
1500 }
1501
1502 QString version = header[4];
1503
1504 header.removeLast();
1505
1506 QString magic = header.join(" ");
1507
1508 if ( magic != "# vtk DataFile Version" ) {
1509 emit log(LOGERR,tr("Bad VTK header magic? ") + magic);
1510 return -1;
1511 }
1512
1513 QString description = in.readLine();
1514
1515 QString fileTypeStr = in.readLine();
1516
1517 fileTypeStr = fileTypeStr.simplified();
1518
1519 if ( fileTypeStr.toLower() == "binary" ) {
1520 binary_ = true;
1521 emit log(LOGINFO,tr("Loading VTK binary file of version %1.").arg(version));
1522 emit log(LOGERR,tr("Not yet implemented!"));
1523 } else if ( fileTypeStr.toLower() == "ascii" ) {
1524 binary_ = false;
1525 emit log(LOGINFO,tr("Loading VTK ascii file of version %1.").arg(version));
1526 } else {
1527 emit log(LOGERR,tr("Bad VTK type? ") + fileTypeStr);
1528 return -1;
1529 }
1530
1531 emit log(LOGINFO,description);
1532
1533 line = "";
1534
1535 while ( line.simplified() == "" )
1536 line = in.readLine();
1537
1538 QStringList datasetList = line.split(" ",QString::SkipEmptyParts);
1539
1540 if ( datasetList.size() != 2 ) {
1541 emit log(LOGERR,tr("Bad dataset specification!"));
1542 return -1;
1543 }
1544
1545 Dataset dataset;
1546
1547 datasetList[1] = datasetList[1].simplified();
1548
1549 if ( datasetList[1] == "STRUCTURED_POINTS" )
1550 dataset = STRUCTURED_POINTS;
1551 else if ( datasetList[1] == "STRUCTURED_GRID" )
1552 dataset = STRUCTURED_GRID;
1553 else if ( datasetList[1] == "RECTILINEAR_GRID" )
1554 dataset = RECTILINEAR_GRID;
1555 else if ( datasetList[1] == "POLYDATA" )
1556 dataset = POLYDATA;
1557 else if ( datasetList[1] == "UNSTRUCTURED_GRID" )
1558 dataset = UNSTRUCTURED_GRID;
1559 else {
1560 emit log(LOGERR,tr("Unknown dataset specification! %1").arg(datasetList[1]));
1561 return -1;
1562 }
1563
1564 BaseObject* baseObj = 0;
1565
1566 if ( (forceTriangleMesh_) || (bestType == BMT_TriMesh) ){
1567
1568 // add a triangle mesh
1569 int id = -1;
1570 emit addEmptyObject(DATA_TRIANGLE_MESH, id);
1571
1572 TriMeshObject* object(0);
1573
1574 if(PluginFunctions::getObject( id, object)){
1575
1576 TriMesh* _mesh;
1577 PluginFunctions::getMesh(id,_mesh);
1578
1579 if ( _mesh != 0 ) {
1580 if ( !loadMesh(in,_mesh,dataset) ) {
1581 emit log(LOGERR,"Unable to load mesh!");
1582 return -1;
1583 }
1584 } else {
1585 emit log(LOGERR,"Unable to add empty triangle mesh!");
1586 return -1;
1587 }
1588
1589 baseObj = object;
1590 }
1591
1592 }
1593 // If no type can represent the object in the file just use PolyMesh
1594 // and load as much as possible
1595 else if ((bestType == BMT_PolyMesh) || (bestType == BMT_None))
1596 {
1597
1598 int id = -1;
1599 emit addEmptyObject(DATA_POLY_MESH, id);
1600
1601
1602 PolyMeshObject* object(0);
1603
1604 if(PluginFunctions::getObject( id, object)){
1605
1606 PolyMesh* _mesh(0);
1607 PluginFunctions::getMesh(id, _mesh);
1608
1609 if ( _mesh != 0 ) {
1610 if ( !loadMesh(in,_mesh,dataset) ) {
1611 emit log(LOGERR,"Unable to load mesh!");
1612 return -1;
1613 }
1614 } else {
1615 emit log(LOGERR,"Unable to add empty poly mesh!");
1616 return -1;
1617 }
1618
1619 baseObj = object;
1620
1621 }
1622
1623
1624 }
1625 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1626 else if (bestType == BMT_PolyhedralMesh)
1627 {
1628 // add a Polyhedral mesh
1629 int id = -1;
1630 emit addEmptyObject(DATA_POLYHEDRAL_MESH, id);
1631
1632 PolyhedralMeshObject* object(0);
1633
1634 if(PluginFunctions::getObject( id, object)){
1635
1636 PolyhedralMesh* _mesh;
1637 _mesh = PluginFunctions::polyhedralMesh(object);
1638
1639 if ( _mesh != 0 ) {
1640 if ( !loadMesh(in,_mesh,dataset) ) {
1641 emit log(LOGERR,"Unable to load mesh!");
1642 return -1;
1643 }
1644 } else {
1645 emit log(LOGERR,"Unable to add empty polyhedral mesh!");
1646 return -1;
1647 }
1648
1649 baseObj = object;
1650 }
1651
1652 }
1653 #endif //ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1654 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1655 else if (bestType == BMT_HexahedralMesh)
1656 {
1657 // add a heexahedral mesh
1658 int id = -1;
1659 emit addEmptyObject(DATA_HEXAHEDRAL_MESH, id);
1660
1661 HexahedralMeshObject* object(0);
1662
1663 if(PluginFunctions::getObject( id, object)){
1664
1665 HexahedralMesh* _mesh;
1666 _mesh = PluginFunctions::hexahedralMesh(object);
1667
1668 if ( _mesh != 0 ) {
1669 if ( !loadMesh(in,_mesh,dataset) ) {
1670 emit log(LOGERR,"Unable to load mesh!");
1671 return -1;
1672 }
1673 } else {
1674 emit log(LOGERR,"Unable to add empty hexahedral mesh!");
1675 return -1;
1676 }
1677 baseObj = object;
1678 }
1679
1680 }
1681 #endif //ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1682
1683 if (baseObj)
1684 {
1685 baseObj->setFromFileName(_filename);
1686 baseObj->setName(baseObj->filename());
1687
1688
1689 emit updatedObject(baseObj->id(), UPDATE_ALL);
1690
1691 //general stuff
1692 emit openedFile( baseObj->id() );
1693
1694 return baseObj->id();
1695 }
1696
1697 emit log(LOGERR,tr("Error in load mesh!"));
1698
1699 return -1;
1700
1701
1702 }
1703
1704 template <typename MeshT>
1705 bool FileVTKPlugin::loadMeshPoints(QString _spec, QTextStream& _in,MeshT*& _mesh){
1706
1707 std::cerr << "loadMeshPoints" << std::endl;
1708
1709 bool ok = true;
1710
1711 // Split the header line into components
1712 QStringList pointsLine = _spec.split(" ",QString::SkipEmptyParts);
1713
1714 // It has to contain the Keyword POINTS , the number of points to read and the datatype of the points
1715 if ( pointsLine.size() != 3 ) {
1716 emit log(LOGERR,tr("Expected to get Points line with exactly 3 entries, but %1 found!").arg(pointsLine.size()));
1717 return false;
1718 }
1719
1720 // Get the number of points to read
1721 quint32 points = pointsLine[1].toUInt(&ok);
1722
1723 if ( ! ok) {
1724 emit log(LOGERR,tr("Expected to get number of points, but read %1 !").arg(pointsLine[1]));
1725 return false;
1726 }
1727
1728 // In OpenMesh we use doubles for the point representation
1729 OpenMesh::Vec3d vec;
1730
1731 quint32 read = 0;
1732 while ( read < points ) {
1733
1734
1735 if ( binary_ ) {
1736
1737 // Read binary float values
1738 if ( pointsLine[2] == "float" ) {
1739 // Read floats
1740 OpenMesh::Vec3f vecf;
1741 _in.device()->read((char*)&vecf[0],sizeof(float));
1742 _in.device()->read((char*)&vecf[1],sizeof(float));
1743 _in.device()->read((char*)&vecf[2],sizeof(float));
1744
1745 // convert
1746 vec = vecf;
1747 } else {
1748 emit log(LOGERR,tr("Not implemented data type %1 !").arg(pointsLine[2]));
1749 return false;
1750 }
1751
1752 } else {
1753 // Don't care about original type, as we read text and convert it anyway.
1754 _in >> vec[0] >> vec[1] >> vec[2];
1755 }
1756
1757 // Next point to read
1758 ++read;
1759
1760 // Check if the stream is still ok
1761 if ( _in.status() == QTextStream::Ok ) {
1762 _mesh->add_vertex(vec);
1763 } else {
1764 emit log(LOGERR,tr("Read corrupted point data!"));
1765 return false;
1766 }
1767
1768 }
1769
1770 if (binary_) {
1771 if ( pointsLine[2] == "float" ) {
1772 // Reposition text stream. We read points * 3 * sizeof(float)
1773 // For the text stream we calculate the position in charactersso convert it witth 1.0 / sizeof(char)
1774 _in.seek(_in.pos() + read * 3 * sizeof(float) / sizeof(char) );
1775 }
1776 }
1777
1778 return true;
1779
1780 }
1781
1782 template <typename MeshT>
1783 bool FileVTKPlugin::loadMeshLines(QString _spec,QTextStream& _in,MeshT*& _mesh) {
1784 std::cerr << "loadMeshLines" << std::endl;
1785
1786 bool ok = true;
1787
1788 // Split the header line into components
1789 QStringList linesLine = _spec.split(" ",QString::SkipEmptyParts);
1790
1791 // It has to contain the Keyword LINES , the number of polygons to read and the total number of values to read ( each line: 1 + valence )
1792 if ( linesLine.size() != 3 ) {
1793 emit log(LOGERR,tr("Expected to get LINES line with exactly 3 entries, but %1 found!").arg(linesLine.size()));
1794 return false;
1795 }
1796
1797 // umber of lines to read
1798 quint32 linecount = linesLine[1].toUInt(&ok);
1799
1800 // number of ints in the whole line description!
1801 quint32 entrycount = linesLine[2].toUInt(&ok);
1802
1803 if ( ! ok) {
1804 emit log(LOGERR,tr("Expected to get number of lines and entries, but read %1 !").arg(linesLine.join(" ")));
1805 return false;
1806 }
1807
1808 quint32 read = 0;
1809
1810 while ( read < linecount) {
1811
1812 // Read first integer describing number of indizes in the current line
1813 quint32 valence;
1814
1815 if ( !binary_ )
1816 _in >> valence;
1817 else
1818 _in.device()->read((char*)&valence,sizeof(quint32));
1819
1820
1821 quint32 index;
1822
1823 if ( _in.status() == QTextStream::Ok ) {
1824
1825 if ( !binary_ ) {
1826 for ( unsigned int i = 0 ; i < valence; ++i )
1827 _in >> index;
1828 } else {
1829 for ( unsigned int i = 0 ; i < valence; ++i )
1830 _in.device()->read((char*)&valence,sizeof(quint32));
1831 }
1832
1833 if ( _in.status() == QTextStream::Ok ) {
1834 // TODO : Generate lines here!
1835
1836 //_mesh->add_edge(handles);
1837 } else {
1838 emit log(LOGERR,tr("Read corrupted face data!"));
1839 return false;
1840 }
1841
1842 } else {
1843 emit log(LOGERR,tr("Read corrupted POLYGONS data!"));
1844 return false;
1845 }
1846
1847 ++read;
1848 }
1849
1850 if ( binary_ ) {
1851 // Reposition text stream. We read entrycount * sizeof(quint32) .
1852 // For the text stream we calculate the position in charactersso convert it witth 1.0 / sizeof(char)
1853 _in.seek(_in.pos() + entrycount * sizeof(quint32) / sizeof(char) );
1854 }
1855
1856 emit log(LOGWARN,tr("Lines not supported yet ... skipped!"));
1857
1858 return true;
1859 }
1860
1861 template <typename MeshT>
1862 bool FileVTKPlugin::loadMeshPolygons(QString _spec,QTextStream& _in,MeshT*& _mesh, std::vector<CellType>& _cells) {
1863 std::cerr << "loadMeshPolygons" << std::endl;
1864
1865 bool ok = true;
1866
1867 // Split the header line into components
1868 QStringList polygonsLine = _spec.split(" ",QString::SkipEmptyParts);
1869
1870 // It has to contain the Keyword POLYGONS , the number of polygons to read and the total number of values to read ( each polygon: 1 + valence )
1871 if ( polygonsLine.size() != 3 ) {
1872 emit log(LOGERR,tr("Expected to get Points line with exactly 3 entries, but %1 found!").arg(polygonsLine.size()));
1873 return false;
1874 }
1875
1876 // Number of polygons to read
1877 quint32 polygoncount = polygonsLine[1].toUInt(&ok);
1878
1879 // number of ints in the whole polygon description
1880 quint32 entrycount = polygonsLine[2].toUInt(&ok);
1881
1882 if ( ! ok) {
1883 emit log(LOGERR,tr("Expected to get number of points and entries, but read %1 !").arg(polygonsLine.join(" ")));
1884 return false;
1885 }
1886
1887 // Disable OpenMesh error logging
1888 bool errorEnabled = omerr().is_enabled();
1889 omerr().disable();
1890
1891 quint32 read = 0;
1892 while ( read < polygoncount) {
1893
1894 // Read first integer describing number of indices
1895 quint32 valence;
1896 if ( !binary_ )
1897 _in >> valence;
1898 else
1899 _in.device()->read((char*)&valence,sizeof(quint32));
1900
1901
1902 quint32 index;
1903 std::vector< quint32 > indices;
1904
1905 for ( unsigned int i = 0 ; i < valence; ++i ) {
1906
1907 // Read one index
1908 if ( !binary_ )
1909 _in >> index;
1910 else
1911 _in.device()->read((char*)&valence,sizeof(quint32));
1912
1913 // Remember it
1914 indices.push_back( index );
1915 }
1916
1917 if ( _in.status() == QTextStream::Ok ) {
1918
1919 //check, if there exists duplicate vertices inside of the face
1920 remove_duplicated_vertices(indices);
1921
1922 if (indices.size() >= 3)
1923 {
1924 CellType cell;
1925 cell.type = 7; // VTK_POLYGON
1926 cell.indices = indices;
1927 cell.index = addFace(_mesh, indices);
1928 _cells.push_back(cell);
1929 }
1930 } else {
1931 emit log(LOGERR,tr("Read corrupted face data!"));
1932
1933 // Restore error logging state before returning
1934 if ( errorEnabled )
1935 omerr().enable();
1936
1937 return false;
1938 }
1939 ++read;
1940 }
1941
1942 // Restore error logging state.
1943 if ( errorEnabled )
1944 omerr().enable();
1945
1946 if (binary_) {
1947 // Reposition text stream. We read entrycount * sizeof(qint32)
1948 // For the text stream we calculate the position in charactersso convert it witth 1.0 / sizeof(char)
1949 _in.seek(_in.pos() + entrycount * sizeof(qint32) / sizeof(char) );
1950 }
1951
1952 return true;
1953 }
1954
1955 template <typename MeshT>
1956 int FileVTKPlugin::add_non_manifold_face(MeshT*& _mesh, std::vector< OpenMesh::VertexHandle >& _vhandles) {
1957
1958 // Duplicate vertices of non-manifold faces
1959 // and add them as new isolated face
1960 if (_vhandles.empty()) return -1;
1961
1962 OpenMesh::VPropHandleT< OpenMesh::VertexHandle > originalVertexIdx;
1963 if (! _mesh->get_property_handle(originalVertexIdx,"FileVTKPlugin_originalVertexIdx")) {
1964 _mesh->add_property( originalVertexIdx, "FileVTKPlugin_originalVertexIdx" );
1965
1966 //mark all vertices
1967 typename MeshT::VertexIter vit = _mesh->vertices_begin();
1968 typename MeshT::VertexIter vend = _mesh->vertices_end();
1969 for(; vit != vend; ++vit) {
1970 _mesh->property (originalVertexIdx, *vit) = OpenMesh::VertexHandle(-1);
1971 }
1972 }
1973
1974 // double vertices
1975 for (unsigned int j = 0; j < _vhandles.size(); ++j)
1976 {
1977 typename MeshT::Point p = _mesh->point(_vhandles[j]);
1978 OpenMesh::VertexHandle original_handle = _vhandles[j];
1979 _vhandles[j] = _mesh->add_vertex(p);
1980 // DO STORE p, reference may not work since vertex array
1981 // may be relocated after adding a new vertex !
1982
1983 // Mark vertices of failed face as non-manifold
1984 if (_mesh->has_vertex_status()) {
1985 _mesh->status(_vhandles[j]).set_fixed_nonmanifold(true);
1986 }
1987 // To assign other properties to this vertex later, save its "original" in property
1988 _mesh->property (originalVertexIdx, _vhandles[j]) = original_handle;
1989 }
1990
1991 // add face
1992 OpenMesh::FaceHandle fh = _mesh->add_face(_vhandles);
1993
1994 // Mark failed face as non-manifold
1995 if (_mesh->has_face_status())
1996 _mesh->status(fh).set_fixed_nonmanifold(true);
1997
1998 // Mark edges of failed face as non-two-manifold
1999 if (_mesh->has_edge_status()) {
2000 typename MeshT::FaceEdgeIter fe_it = _mesh->fe_iter(fh);
2001 for (; fe_it.is_valid(); ++fe_it) {
2002 _mesh->status(*fe_it).set_fixed_nonmanifold(true);
2003 }
2004 }
2005
2006 return fh.idx();
2007 }
2008
2009
2010 template <typename MeshT>
2011 bool FileVTKPlugin::loadMeshTriangleStrips(QString _spec,QTextStream& _in,MeshT*& _mesh, std::vector<CellType>& _cells) {
2012 std::cerr << "loadMeshTriangleStrips" << std::endl;
2013
2014 bool ok = true;
2015
2016 // Split the header line into components
2017 QStringList triStripsLine = _spec.split(" ",QString::SkipEmptyParts);
2018
2019 // It has to contain the Keyword TRIANGLE_STRIPS , the number of strips to read and the total number of values to read ( each strip: 1 + valence )
2020 if ( triStripsLine.size() != 3 ) {
2021 emit log(LOGERR,tr("Expected to get TRIANGLE_STRIPS line with exactly 3 entries, but %1 found!").arg(triStripsLine.size()));
2022 return false;
2023 }
2024
2025 // Number of polygons to read
2026 quint32 stripcount = triStripsLine[1].toUInt(&ok);
2027
2028 // number of ints in the whole polygon description
2029 quint32 entrycount = triStripsLine[2].toUInt(&ok);
2030
2031 if ( ! ok) {
2032 emit log(LOGERR,tr("Expected to get number of strips and entries, but read %1 !").arg(triStripsLine.join(" ")));
2033 return false;
2034 }
2035
2036 quint32 read = 0;
2037 while ( read < stripcount) {
2038
2039 // Read first integer describing number of indizes in the strip
2040 quint32 valence;
2041 if ( !binary_ )
2042 _in >> valence;
2043 else
2044 _in.device()->read((char*)&valence,sizeof(quint32));
2045
2046
2047 quint32 index;
2048 QList< quint32 > indices;
2049
2050 // Read first two of strip:
2051 for ( unsigned int i = 0 ; i < 2; ++i ) {
2052
2053 // Read one index
2054 if ( !binary_ )
2055 _in >> index;
2056 else
2057 _in.device()->read((char*)&valence,sizeof(quint32));
2058
2059 // Remember it
2060 indices.push_back( index );
2061 }
2062
2063 // Read rest of strip while adding faces
2064 for ( unsigned int i = 2 ; i < valence; ++i ) {
2065
2066 // Read one index
2067 if ( !binary_ )
2068 _in >> index;
2069 else
2070 _in.device()->read((char*)&valence,sizeof(quint32));
2071
2072 // Remember it
2073 indices.push_back( index );
2074
2075 if ( _in.status() == QTextStream::Ok ) {
2076 // TODO : handle non manifold cases!
2077 CellType cell;
2078 cell.type = 6; //VTK_TRIANGLE_STRIP
2079 cell.indices.resize(3);
2080 cell.indices[0] = indices[i];
2081 cell.indices[1] = indices[i-1];
2082 cell.indices[2] = indices[i-2];
2083 if ( i % 2 != 0 )
2084 std::swap(cell.indices[1],cell.indices[2]);
2085 cell.index = addFace(_mesh, cell.indices);
2086 _cells.push_back(cell);
2087 } else {
2088 emit log(LOGERR,tr("Read corrupted face data!"));
2089 return false;
2090 }
2091
2092
2093 }
2094
2095 ++read;
2096 }
2097
2098
2099 if (binary_) {
2100 // Reposition text stream. We read entrycount * sizeof(qint32)
2101 // For the text stream we calculate the position in charactersso convert it witth 1.0 / sizeof(char)
2102 _in.seek(_in.pos() + entrycount * sizeof(qint32) / sizeof(char) );
2103 }
2104
2105 return true;
2106 }
2107
2108 template <typename MeshT>
2109 bool FileVTKPlugin::loadMeshNormals(QString _spec,QTextStream& _in,MeshT*& _mesh, std::vector<CellType>& _cells, bool _pointNormal, quint32 _count) {
2110 std::cerr << "loadMeshNormals" << std::endl;
2111
2112 // Split the header line into components
2113 QStringList normalsLine = _spec.split(" ",QString::SkipEmptyParts);
2114
2115 // It has to contain the Keyword NORMALS , the name of the dataset and the datatype
2116 if ( normalsLine.size() != 3 ) {
2117 emit log(LOGERR,tr("Expected to get NORMALS line with exactly 3 entries, but %1 found!").arg(normalsLine.size()));
2118 return false;
2119 }
2120
2121 // In OpenMesh we use doubles for the normal representation
2122 OpenMesh::Vec3d normal;
2123
2124 quint32 read = 0;
2125 while ( read < _count) {
2126
2127 if ( binary_ ) {
2128
2129 // Read binary float values
2130 if ( normalsLine[2] == "float" ) {
2131
2132 // Read floats
2133 OpenMesh::Vec3f vecf;
2134 _in.device()->read((char*)&vecf[0],sizeof(float));
2135 _in.device()->read((char*)&vecf[1],sizeof(float));
2136 _in.device()->read((char*)&vecf[2],sizeof(float));
2137
2138 // convert
2139 normal = vecf;
2140 } else {
2141 emit log(LOGERR,tr("Not implemented data type %1 !").arg(normalsLine[2]));
2142 return false;
2143 }
2144
2145 } else {
2146 // Don't care about original type, as we read text and convert it anyway.
2147 _in >> normal[0] >> normal[1] >> normal[2];
2148 }
2149
2150 // Check if the stream is still ok
2151 if ( _in.status() == QTextStream::Ok ) {
2152
2153 if ( _pointNormal ) {
2154 addVertexNormal(_mesh, read, normal);
2155
2156 } else {
2157 addCellNormal(_mesh, _cells[read], normal);
2158 }
2159
2160 } else {
2161 emit log(LOGERR,tr("Read corrupted point data!"));
2162 return false;
2163 }
2164
2165 // Next normal to read
2166 ++read;
2167 }
2168
2169 if (binary_) {
2170 if ( normalsLine[2] == "float" ) {
2171 // Reposition text stream. We read points * 3 * sizeof(float)
2172 // For the text stream we calculate the position in charactersso convert it with 1.0 / sizeof(char)
2173 _in.seek(_in.pos() + read * 3 * sizeof(float) / sizeof(char) );
2174 }
2175 }
2176
2177 setNormalsOfDuplicatedVertices(_mesh);
2178
2179
2180 return true;
2181 }
2182
2183 template <typename MeshT>
2184 bool FileVTKPlugin::loadMeshCells(QString _spec,QTextStream& _in,MeshT*& _mesh, std::vector<CellType>& _cells) {
2185
2186 std::cerr << "loadMeshCells" << std::endl;
2187
2188 // Split the header line into components
2189 QStringList cellLine = _spec.split(" ",QString::SkipEmptyParts);
2190
2191 // It has to contain the Keyword CELLS , the number of cells to read and the total number of values to read ( each cell: 1 + valence )
2192 if ( cellLine.size() != 3 ) {
2193 emit log(LOGERR,tr("Expected to get CELLS line with exactly 3 entries, but %1 found!").arg(cellLine.size()));
2194 return false;
2195 }
2196
2197 bool ok = true;
2198
2199 // Number of cells to read
2200 quint32 cellCount = cellLine[1].toUInt(&ok);
2201
2202 // number of ints in the whole cell description
2203 quint32 entryCount = cellLine[2].toUInt(&ok);
2204
2205
2206 if ( ! ok) {
2207 emit log(LOGERR,tr("Expected to get number of cells and entries, but read %1 !").arg(cellLine.join(" ")));
2208 return false;
2209 }
2210
2211 quint32 read = 0;
2212 while ( read < cellCount) {
2213
2214 CellType currentCell;
2215
2216 // Read first integer describing number of indizes
2217 quint32 valence;
2218 if ( !binary_ )
2219 _in >> valence;
2220 else
2221 _in.device()->read((char*)&valence,sizeof(quint32));
2222
2223
2224 quint32 index;
2225
2226 for ( unsigned int i = 0 ; i < valence; ++i ) {
2227
2228 // Read one index
2229 if ( !binary_ )
2230 _in >> index;
2231 else
2232 _in.device()->read((char*)&valence,sizeof(quint32));
2233
2234 // Remember it
2235 currentCell.indices.push_back( index );
2236 }
2237
2238 if ( _in.status() == QTextStream::Ok ) {
2239 _cells.push_back(currentCell);
2240 } else {
2241 emit log(LOGERR,tr("Read corrupted face data!"));
2242 return false;
2243 }
2244 ++read;
2245
2246 }
2247
2248 if (binary_) {
2249 // Reposition text stream. We read entryCount * sizeof(quint32)
2250 // For the text stream we calculate the position in charactersso convert it with 1.0 / sizeof(char)
2251 _in.seek(_in.pos() + entryCount * sizeof(quint32) / sizeof(char) );
2252 }
2253
2254
2255 //=================================================================================
2256 //=================================================================================
2257 // Read the cell types now
2258 //=================================================================================
2259 //=================================================================================
2260 _spec ="";
2261
2262 // Read lines until we get something usefull
2263 while ( _spec.simplified().size() == 0 ) {
2264
2265 // stop at end of file!
2266 if ( _in.atEnd() ) {
2267 emit log(LOGERR,tr("File end when reading cell specification!"));
2268 return false;
2269 }
2270
2271 _spec = _in.readLine();
2272 }
2273
2274 if ( ! _spec.contains("CELL_TYPES") ) {
2275 emit log(LOGERR,tr("Wrong token! Expected CELL_TYPES but got : %1").arg(_spec));
2276 return false;
2277 }
2278
2279 // Split the header line into components
2280 cellLine = _spec.split(" ",QString::SkipEmptyParts);
2281
2282 // It has to contain the Keyword CELL_TYPES , the number of cells to read
2283 if ( cellLine.size() != 2 ) {
2284 emit log(LOGERR,tr("Expected to get CELL_TYPES line with exactly 2 entries, but %1 found!").arg(cellLine.size()));
2285 return false;
2286 }
2287
2288 // Number of cells to read
2289 quint32 cellCountTypes = cellLine[1].toUInt(&ok);
2290
2291 if ( ! ok) {
2292 emit log(LOGERR,tr("Expected to get number of cell types, but read %1 !").arg(cellLine[1]));
2293 return false;
2294 }
2295
2296 if (cellCountTypes != cellCount ) {
2297 emit log(LOGERR,tr("cellCountTypes != cellCount !").arg(cellLine.size()));
2298 return false;
2299 }
2300
2301 read = 0;
2302 while ( read < cellCount) {
2303
2304 // Read first integer describing number of indizes
2305 quint32 type;
2306 if ( !binary_ )
2307 _in >> type;
2308 else
2309 _in.device()->read((char*)&type,sizeof(quint32));
2310
2311
2312 // Remember it
2313 _cells[read].type = type;
2314
2315 if ( _in.status() != QTextStream::Ok ) {
2316 emit log(LOGERR,tr("Read corrupted cell type data!"));
2317 return false;
2318 }
2319 ++read;
2320 }
2321
2322 if (binary_) {
2323 // Reposition text stream. We read cells * sizeof(quint32)
2324 // For the text stream we calculate the position in charactersso convert it with 1.0 / sizeof(char)
2325 _in.seek(_in.pos() + read * sizeof(quint32) / sizeof(char) );
2326 }
2327
2328 //=================================================================================
2329 //=================================================================================
2330 // Now add the cells
2331 //=================================================================================
2332 //=================================================================================
2333 for ( unsigned int i = 0 ; i < _cells.size() ; ++i ) {
2334 if ( _cells[i].type == 1 ) {
2335
2336 //VERTEX
2337 // Nothing to do for meshes ... already added as vertex
2338
2339 } else if ( _cells[i].type == 2 ) {
2340
2341 //POLY_VERTEX
2342 // Nothing to do for meshes ... already added as vertex
2343
2344 } else if ( _cells[i].type == 3 ) {
2345
2346 //LINE
2347 emit log(LOGWARN,tr("Unsupported Cell Type LINE") );
2348
2349 } else if ( _cells[i].type == 4 ) {
2350 //POLY_LINE
2351
2352 emit log(LOGWARN,tr("Unsupported Cell Type POLY_LINE") );
2353
2354 } else if ( _cells[i].type == 5 ) {
2355 //TRIANGLE
2356 _cells[i].index = addFace(_mesh, _cells[i].indices);
2357 } else if ( _cells[i].type == 6 ) {
2358 //TRIANGLE_STRIP
2359
2360 for ( unsigned int j = 2 ; j < _cells[i].indices.size() ; ++j) {
2361 if ( (j % 2) == 0 )
2362 _cells[i].index = addFace(_mesh, _cells[i].indices[j-2],_cells[i].indices[j],_cells[i].indices[j-1]);
2363 else
2364 _cells[i].index = addFace(_mesh, _cells[i].indices[j-2],_cells[i].indices[j-1],_cells[i].indices[j]);
2365 }
2366
2367 //TODO : handle non manifold cases!
2368
2369 } else if ( _cells[i].type == 7 ) {
2370 //POLYGON
2371
2372 _cells[i].index = addFace(_mesh, _cells[i].indices);
2373
2374 } else if ( _cells[i].type == 8 ) {
2375 //PIXEL
2376
2377 emit log(LOGWARN,tr("Unsupported Cell Type PIXEL") );
2378
2379 } else if ( _cells[i].type == 9 ) {
2380 //QUAD
2381
2382 _cells[i].index = addFace(_mesh, _cells[i].indices);
2383
2384 } else if ( _cells[i].type == 10 ) {
2385 //Tetra
2386 _cells[i].index = addTetraCell(_mesh, _cells[i].indices);
2387
2388 } else if ( _cells[i].type == 11 ) {
2389 //VOXEL
2390
2391 emit log(LOGWARN,tr("Unsupported Cell Type VOXEL") );
2392
2393 } else if ( _cells[i].type == 12 ) {
2394 //HEXAHEDRON
2395
2396 _cells[i].index = addHexaCell(_mesh, _cells[i].indices);
2397 } else if ( _cells[i].type == 13 ) {
2398 //WEDGE
2399
2400 _cells[i].index = addWedgeCell(_mesh, _cells[i].indices);
2401 } else if ( _cells[i].type == 14 ) {
2402 //PYRAMID
2403
2404 _cells[i].index = addPyramidCell(_mesh, _cells[i].indices);
2405
2406 } else {
2407 emit log(LOGERR,tr("Unknown cell type").arg(_cells[i].type) );
2408 }
2409 }
2410
2411 std::cerr << "Read " << read << " Cells " << std::endl;
2412 std::cerr << "Vector has size: " << _cells.size() << std::endl;
2413
2414
2415 return true;
2416 }
2417
2418 template <typename MeshT>
2419 bool FileVTKPlugin::loadMesh(QTextStream& _in,MeshT*& _mesh, Dataset _type){
2420
2421
2422 if ( _type != POLYDATA && _type != UNSTRUCTURED_GRID ) {
2423 emit log(LOGERR,"Unsupported DATASET" );
2424 return false;
2425 }
2426
2427 QString line = "";
2428
2429 bool ok = true;
2430
2431 // Flag if normals have been read from files
2432 bool pointNormalsRead = false;
2433 bool faceNormalsRead = false;
2434
2435 // flag if we are in Point data mode
2436 bool pointData = false;
2437
2438 // Size of the point data
2439 quint32 pointDataSize = 0;
2440
2441 // flag if we are in cell data mode
2442 bool cellData = false;
2443
2444 // Size of the cell data
2445 quint32 cellDataSize = 0;
2446
2447 std::vector<CellType> cells;
2448
2449 while (ok) {
2450
2451 line = _in.readLine();
2452
2453 // Read lines until we get something usefull
2454 while ( line.simplified().size() == 0 ) {
2455
2456 // stop at end of file!
2457 if ( _in.atEnd() ) {
2458 ok = false;
2459 std::cerr << "atEnd" << std::endl;
2460 break;
2461 }
2462
2463 line = _in.readLine();
2464 }
2465
2466 // Stop if something is wrong or we are at the end of the file
2467 if ( !ok )
2468 break;
2469
2470 std::cerr << "Line is: " << line.toStdString() << std::endl;
2471
2472 // if we got a points token:
2473 if ( line.contains("POINTS") ) {
2474
2475 ok = loadMeshPoints(line,_in,_mesh);
2476 } else if ( line.contains("POINT_DATA") ) {
2477
2478 bool ok = true;
2479
2480 // Split the header line into components
2481 QStringList pointDataLine = line.split(" ",QString::SkipEmptyParts);
2482
2483 // It has to contain the Keyword POINT_DATA , and the number of datasets
2484 if ( pointDataLine.size() != 2 ) {
2485 emit log(LOGERR,tr("Expected to get POINT_DATA line with exactly 2 entries, but %1 found!").arg(line.size()));
2486 return false;
2487 }
2488
2489 // Number of polygons to read
2490 pointDataSize = pointDataLine[1].toUInt(&ok);
2491
2492 pointData = true;
2493 cellData = false;
2494
2495 std::cerr << "Point data mode with " << pointDataSize << "Elements" << std::endl;
2496
2497 } else if ( line.contains("CELL_DATA") ) {
2498
2499 bool ok = true;
2500
2501 // Split the header line into components
2502 QStringList cellDataLine = line.split(" ",QString::SkipEmptyParts);
2503
2504 // It has to contain the Keyword CELL_DATA , and the number of datasets
2505 if ( cellDataLine.size() != 2 ) {
2506 emit log(LOGERR,tr("Expected to get CELL_DATA line with exactly 2 entries, but %1 found!").arg(line.size()));
2507 return false;
2508 }
2509
2510 // Number of polygons to read
2511 cellDataSize = cellDataLine[1].toUInt(&ok);
2512
2513 cellData = true;
2514 pointData = false;
2515
2516 std::cerr << "Cell data mode with " << cellDataSize << "Elements" << std::endl;
2517
2518 } else if ( line.contains("VERTICES") ) {
2519 std::cerr << "Vertices will be skipped as they are already added!" << std::endl;
2520 } else if ( line.contains("LINES") ) {
2521 ok = loadMeshLines(line,_in,_mesh);
2522 } else if ( line.contains("POLYGONS") ) {
2523 ok = loadMeshPolygons(line,_in,_mesh, cells);
2524 } else if ( line.contains("TRIANGLE_STRIPS") ) {
2525 ok = loadMeshTriangleStrips(line,_in,_mesh, cells);
2526 } else if ( line.contains("CELL") ) {
2527 ok = loadMeshCells(line,_in,_mesh, cells);
2528 } else if ( line.contains("NORMALS") ) {
2529 // load per point normals or per face normals
2530 if ( pointData ) {
2531 ok = loadMeshNormals(line,_in,_mesh,cells,true,pointDataSize);
2532 pointNormalsRead = true;
2533 } else if (cellData) {
2534 ok = loadMeshNormals(line,_in,_mesh,cells,false,cellDataSize);
2535 faceNormalsRead = true;
2536 } else {
2537 emit log(LOGERR,tr("Got normals keyword but we are neither in pointdata nor celldata mode") );
2538 return false;
2539 }
2540
2541 } else {
2542 std::cerr << "Unrecognized keyword : " << line.toStdString() << std::endl;
2543 }
2544
2545 }
2546
2547 if ( !faceNormalsRead )
2548 updateFaceNormals(_mesh);
2549
2550 if ( !pointNormalsRead )
2551 updateVertexNormals(_mesh);
2552
2553 removeTemporaryProperties(_mesh);
2554
2555 return true;
2556 }
2557
2558 //-----------------------------------------------------------------------------------------------------
2559
2561 int FileVTKPlugin::loadObject(QString _filename, DataType _type){
2562
2563 if ( _type == DATA_TRIANGLE_MESH )
2564 forceTriangleMesh_ = true;
2565 else if ( _type == DATA_POLY_MESH )
2566 forcePolyMesh_ = true;
2567
2568 return loadObject(_filename);
2569 }
2570
2571 //-----------------------------------------------------------------------------------------------------
2572
2573 bool FileVTKPlugin::saveObject(int _id, QString _filename) {
2574
2575 BaseObjectData* object;
2576 if ( !PluginFunctions::getObject(_id,object) ) {
2577 emit log(LOGERR, tr("saveObject : cannot get object id %1 for save name %2").arg(_id).arg(_filename) );
2578 return false;
2579 }
2580
2581 std::string filename = std::string( _filename.toUtf8() );
2582
2583 std::fstream ofs( filename.c_str(), std::ios_base::out );
2584
2585 if (!ofs) {
2586
2587 emit log(LOGERR, tr("saveObject : Cannot not open file %1 for writing!").arg(_filename) );
2588 return false;
2589 }
2590
2591 // Get user specified options
2592 updateUserOptions();
2593
2594 if ( object->dataType( DATA_POLY_MESH ) ) {
2595
2596 object->setFromFileName(_filename);
2597 object->setName(object->filename());
2598
2599 PolyMeshObject* polyObj = dynamic_cast<PolyMeshObject* >( object );
2600
2601 if (writeMesh(ofs, *polyObj->mesh())){
2602 emit log(LOGINFO, tr("Saved object to ") + _filename );
2603 ofs.close();
2604 return true;
2605 }else{
2606 emit log(LOGERR, tr("Unable to save ") + _filename);
2607 ofs.close();
2608 return false;
2609 }
2610 } else if ( object->dataType( DATA_TRIANGLE_MESH ) ) {
2611
2612 object->setFromFileName(_filename);
2613 object->setName(object->filename());
2614
2615 TriMeshObject* triObj = dynamic_cast<TriMeshObject* >( object );
2616
2617 if (writeMesh(ofs, *triObj->mesh())) {
2618 emit log(LOGINFO, tr("Saved object to ") + _filename );
2619 ofs.close();
2620 return true;
2621 } else {
2622 emit log(LOGERR, tr("Unable to save ") + _filename);
2623 ofs.close();
2624 return false;
2625 }
2626 }
2627 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
2628 else if ( object->dataType( DATA_POLYHEDRAL_MESH ) )
2629 {
2630
2631 object->setFromFileName(_filename);
2632 object->setName(object->filename());
2633
2634 PolyhedralMeshObject* polyhedralObj = dynamic_cast<PolyhedralMeshObject* >( object );
2635
2636 if (writeMesh(ofs, *polyhedralObj->mesh())) {
2637 emit log(LOGINFO, tr("Saved object to ") + _filename );
2638 ofs.close();
2639 return true;
2640 } else {
2641 emit log(LOGERR, tr("Unable to save ") + _filename);
2642 ofs.close();
2643 return false;
2644 }
2645 }
2646 #endif
2647 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
2648 else if ( object->dataType( DATA_HEXAHEDRAL_MESH ) )
2649 {
2650
2651 object->setFromFileName(_filename);
2652 object->setName(object->filename());
2653
2654 HexahedralMeshObject* polyhedralObj = dynamic_cast<HexahedralMeshObject* >( object );
2655
2656 if (writeMesh(ofs, *polyhedralObj->mesh())) {
2657 emit log(LOGINFO, tr("Saved object to ") + _filename );
2658 ofs.close();
2659 return true;
2660 } else {
2661 emit log(LOGERR, tr("Unable to save ") + _filename);
2662 ofs.close();
2663 return false;
2664 }
2665 }
2666 #endif
2667
2668 else {
2669 emit log(LOGERR, tr("Unable to save (object is not a compatible mesh type)"));
2670 ofs.close();
2671 return false;
2672 }
2673
2674 }
2675
2676 //-----------------------------------------------------------------------------------------------------
2677
2678 template< class MeshT >
2679 bool FileVTKPlugin::writeMesh(std::ostream& _out, MeshT& _mesh ) {
2680
2681 /*****************
2682 * HEADER
2683 ******************/
2684 //every VTK file has to start with this
2685 _out << "# vtk DataFile Version 2.0\n";
2686 //write header info. Max. 256 characters!
2687 _out << "Mesh saved from OpenFlipper - www.openflipper.org\n";
2688 //only ASCII is supported right now
2689 _out << "ASCII\n";
2690
2691 /*****************
2692 * DATA
2693 ******************/
2694
2695 // Call corresponding write routine
2696 return writeASCIIData(_out, _mesh);
2697 }
2698
2699 //------------------------------------------------------------------------------------------------------
2700
2701
2702 void FileVTKPlugin::updateUserOptions() {
2703
2704 // If the options dialog has not been initialized, keep
2705 // the initial values
2706
2707 if( OpenFlipper::Options::nogui() )
2708 return;
2709
2710 // Save options
2711 if(saveBinary_) {
2712 if(saveBinary_->isChecked()) userWriteOptions_ |= BINARY;
2713 else { if(userWriteOptions_ & BINARY) userWriteOptions_ -= BINARY; }
2714 }
2715 if(saveFaceNormals_) {
2716 if(saveFaceNormals_->isChecked()) userWriteOptions_ |= FACENORMALS;
2717 else { if(userWriteOptions_ & FACENORMALS) userWriteOptions_ -= FACENORMALS; }
2718 }
2719 if(saveVertexNormals_) {
2720 if(saveVertexNormals_->isChecked()) userWriteOptions_ |= VERTEXNORMALS;
2721 else { if(userWriteOptions_ & VERTEXNORMALS) userWriteOptions_ -= VERTEXNORMALS; }
2722 }
2723 if(saveVertexTexCoords_) {
2724 if(saveVertexTexCoords_->isChecked()) userWriteOptions_ |= VERTEXTEXCOORDS;
2725 else { if(userWriteOptions_ & VERTEXTEXCOORDS) userWriteOptions_ -= VERTEXTEXCOORDS; }
2726 }
2727 }
2728
2729 #if QT_VERSION < 0x050000
2730 Q_EXPORT_PLUGIN2( filevtkplugin , FileVTKPlugin );
2731 #endif
2732
2733
2734
OpenFlipperSettings
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
Definition: GlobalOptions.cc:938
FileVTKPlugin::findBestObjectType
BestMeshType findBestObjectType(QString _filename)
Reads the file to check for present primitives and returns the object type that fits best...
Definition: FileVTK.cc:1204
FileVTKPlugin::getSaveFilters
QString getSaveFilters()
Definition: FileVTK.cc:114
FileVTKPlugin::setNormalsOfDuplicatedVertices
void setNormalsOfDuplicatedVertices(TriMesh *&_mesh)
Sets normals of duplicated vertices that were created for non-manifold meshes.
Definition: FileVTK.cc:499
FileVTKPlugin::writeMesh
bool writeMesh(std::ostream &_out, MeshT &_mesh)
Writes the header of the VTK file, then calls writeASCIIData (binary VTK is currently unsupported) ...
Definition: FileVTK.cc:2679
OpenVolumeMesh::CellHandle
Definition: OpenVolumeMeshHandle.hh:101
MeshObject::mesh
MeshT * mesh()
return a pointer to the mesh
Definition: MeshObjectT.cc:351
FileVTKPlugin::writeASCIIData
bool writeASCIIData(std::ostream &_out, TriMesh &_mesh)
Writes the data of the VTK file in ASCII format.
Definition: FileVTK.cc:502
FileVTKPlugin::updateFaceNormals
void updateFaceNormals(TriMesh *&_mesh)
Updates face normals.
Definition: FileVTK.cc:275
VolumeMeshObject::mesh
MeshT * mesh()
return a pointer to the mesh
Definition: VolumeMeshObjectT.cc:215
PolyMeshObject
Type for a Meshobject containing a poly mesh.
Definition: PolyMesh.hh:70
OpenVolumeMesh::FaceHandle
Definition: OpenVolumeMeshHandle.hh:100
FileVTKPlugin::loadMeshCells
bool loadMeshCells(QString _spec, QTextStream &_in, MeshT *&_mesh, std::vector< CellType > &_cells)
Reads unstructured grid data from the stream and adds it to the mesh.
Definition: FileVTK.cc:2184
FileVTKPlugin::addVertexNormal
void addVertexNormal(TriMesh *&_mesh, quint32 _index, OpenMesh::Vec3d _normal)
Adds a vertex normal.
Definition: FileVTK.cc:493
PluginFunctions::getMesh
bool getMesh(int _identifier, PolyMesh *&_mesh)
Get the Poly Mesh which has the given identifier.
Definition: PluginFunctionsPolyMesh.cc:107
LOGERR
Definition: LoggingInterface.hh:107
BaseObjectData
Definition: BaseObjectData.hh:105
OpenVolumeMesh::OpenVolumeMeshEdge
Definition: BaseEntities.hh:52
FileVTKPlugin::addPyramidCell
int addPyramidCell(TriMesh *&_mesh, std::vector< quint32 > _indices)
Adds a pyramid cell to the mesh. (Does nothing, yet)
Definition: FileVTK.cc:478
FileVTKPlugin::addFaceNormal
void addFaceNormal(TriMesh *&_mesh, quint32 _index, OpenMesh::Vec3d _normal)
Adds a face normal.
Definition: FileVTK.cc:496
OpenVolumeMesh::FacePropertyT
Definition: PropertyDefines.hh:108
BaseObject::filename
QString filename() const
return the filename of the object
Definition: BaseObject.cc:717
TriMeshObject
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:73
DATA_POLYHEDRAL_MESH
#define DATA_POLYHEDRAL_MESH
Definition: PolyhedralMesh.hh:63
UPDATE_ALL
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
PluginFunctions::getObject
bool getObject(int _identifier, BSplineCurveObject *&_object)
Definition: PluginFunctionsBSplineCurve.cc:75
OpenVolumeMesh::VertexIter
Definition: Iterators.hh:686
DATA_GROUP
const DataType DATA_GROUP(1)
Items used for Grouping.
FileVTKPlugin::add_non_manifold_face
int add_non_manifold_face(MeshT *&_mesh, std::vector< OpenMesh::VertexHandle > &_vhandles)
Helper function for loadMeshPolygons() that takes care of adding non-manifold faces.
Definition: FileVTK.cc:1956
FileVTKPlugin::addFaceToOpenMesh
int addFaceToOpenMesh(MeshT *&_mesh, std::vector< quint32 > _indices)
Adds a face to the mesh.
Definition: FileVTK.cc:236
OpenVolumeMesh::EdgeIter
Definition: Iterators.hh:740
BaseObject::setFromFileName
void setFromFileName(const QString &_filename)
Definition: BaseObject.cc:727
FileVTKPlugin::addHexaCellToOpenMesh
int addHexaCellToOpenMesh(MeshT _mesh, std::vector< quint32 > _indices)
Adds a hexa cell to the mesh. (Does nothing, yet)
Definition: FileVTK.cc:215
OpenMesh::BaseHandle::is_valid
bool is_valid() const
The handle is valid iff the index is not equal to -1.
Definition: Handles.hh:77
OpenMesh::BaseHandle::idx
int idx() const
Get the underlying index of this handle.
Definition: Handles.hh:74
FileVTKPlugin::addFace
int addFace(TriMesh *&_mesh, std::vector< quint32 > _indices)
Adds a face to the mesh.
Definition: FileVTK.cc:481
FileVTKPlugin::addPyramidCellToOpenMesh
int addPyramidCellToOpenMesh(MeshT _mesh, std::vector< quint32 > _indices)
Adds a pyramid cell to the mesh. (Does nothing, yet)
Definition: FileVTK.cc:229
FileVTKPlugin::saveOptionsWidget
QWidget * saveOptionsWidget(QString)
Definition: FileVTK.cc:141
FileVTKPlugin::updateUserOptions
void updateUserOptions()
Definition: FileVTK.cc:2702
BaseObject::dataType
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
FileVTKPlugin::initializePlugin
void initializePlugin()
Initialize Plugin.
Definition: FileVTK.cc:94
FileVTKPlugin::description
QString description()
Return a description of what the plugin is doing.
Definition: FileVTK.hh:182
OpenVolumeMesh::CellVertexIter
Definition: Iterators.hh:452
FileVTKPlugin::loadMeshPolygons
bool loadMeshPolygons(QString _spec, QTextStream &_in, MeshT *&_mesh, std::vector< CellType > &_cells)
Reads polygons from the stream and adds them to the mesh.
Definition: FileVTK.cc:1862
FileVTKPlugin::loadMeshPoints
bool loadMeshPoints(QString _spec, QTextStream &_in, MeshT *&_mesh)
Reads points from the stream and adds them to the mesh.
Definition: FileVTK.cc:1705
FileVTKPlugin::updateFaceNormalsOfOpenMesh
void updateFaceNormalsOfOpenMesh(MeshT *&_mesh)
Updates face normals.
Definition: FileVTK.cc:270
FileVTKPlugin::writeASCIIDataOfOpenMesh
bool writeASCIIDataOfOpenMesh(std::ostream &_out, MeshT &_mesh)
Writes the data of the VTK file in ASCII format.
Definition: FileVTK.cc:379
LOGWARN
Definition: LoggingInterface.hh:106
OpenVolumeMesh::HalfFaceHandle
Definition: OpenVolumeMeshHandle.hh:103
VolumeMeshObject
Definition: VolumeMeshObject.hh:72
FileVTKPlugin::addWedgeCell
int addWedgeCell(TriMesh *&_mesh, std::vector< quint32 > _indices)
Adds a wedge cell to the mesh. (Does nothing, yet)
Definition: FileVTK.cc:475
FileVTKPlugin
Definition: FileVTK.hh:85
OpenMesh::VPropHandleT
Definition: Property.hh:487
FileVTKPlugin::supportedType
DataType supportedType()
Return your supported object type( e.g. DATA_TRIANGLE_MESH )
Definition: FileVTK.cc:120
FileVTKPlugin::removeTemporaryProperties
void removeTemporaryProperties(TriMesh *&_mesh)
Removed temporary properties that might have been added during file reading.
Definition: FileVTK.cc:490
BaseObject
Definition: BaseObject.hh:94
OpenMesh::Attributes::TexCoord2D
Add 2D texture coordinates (vertices, halfedges)
Definition: Attributes.hh:92
OpenVolumeMesh::OpenVolumeMeshCell
Definition: BaseEntities.hh:119
OpenMesh::VectorT< double, 3 >
FileVTKPlugin::removeTemporaryPropertiesOfOpenMesh
void removeTemporaryPropertiesOfOpenMesh(MeshT *&_mesh)
Removed temporary properties that might have been added during file reading.
Definition: FileVTK.cc:286
FileVTKPlugin::updateVertexNormals
void updateVertexNormals(TriMesh *&_mesh)
Updates vertex normals.
Definition: FileVTK.cc:487
OpenMesh::VertexHandle
Handle for a vertex entity.
Definition: Handles.hh:125
DATA_POLY_MESH
#define DATA_POLY_MESH
Definition: PolyMesh.hh:65
FileVTKPlugin::slotSaveDefault
void slotSaveDefault()
Slot called when user wants to save the given Save options as default.
Definition: FileVTK.cc:190
FileVTKPlugin::loadMeshLines
bool loadMeshLines(QString _spec, QTextStream &_in, MeshT *&_mesh)
Reads lines from the stream and adds them to the mesh.
Definition: FileVTK.cc:1783
FileVTKPlugin::loadMeshNormals
bool loadMeshNormals(QString _spec, QTextStream &_in, MeshT *&_mesh, std::vector< CellType > &_cells, bool _pointNormal, quint32 _count)
Reads Normals from the stream and adds them to the mesh.
Definition: FileVTK.cc:2109
FileVTKPlugin::addTetraCell
int addTetraCell(TriMesh *&_mesh, std::vector< quint32 > _indices)
Adds a tetra cell to the mesh. (Does nothing, yet)
Definition: FileVTK.cc:469
FileVTKPlugin::loadOptionsWidget
QWidget * loadOptionsWidget(QString)
Definition: FileVTK.cc:135
OpenMesh::FaceHandle
Handle for a face entity.
Definition: Handles.hh:146
OpenVolumeMesh::EdgePropertyT
Definition: PropertyDefines.hh:88
FileVTKPlugin::loadObject
int loadObject(QString _filename)
Loads Object and converts it to a triangle mesh if possible.
Definition: FileVTK.cc:1474
FileVTKPlugin::getLoadFilters
QString getLoadFilters()
Definition: FileVTK.cc:108
FileVTKPlugin::addTetraCellToOpenMesh
int addTetraCellToOpenMesh(MeshT _mesh, std::vector< quint32 > _indices)
Adds a tetra cell to the mesh. (Does nothing, yet)
Definition: FileVTK.cc:208
LOGINFO
Definition: LoggingInterface.hh:105
FileVTKPlugin::binary_
bool binary_
Reading binary file?
Definition: FileVTK.hh:220
OpenVolumeMesh::VertexPropertyT
Property classes for the different entity types.
Definition: PropertyDefines.hh:78
FileVTKPlugin::updateVertexNormalsOfOpenMesh
void updateVertexNormalsOfOpenMesh(MeshT *&_mesh)
Updates vertex normals.
Definition: FileVTK.cc:280
FileVTKPlugin::CellType
Definition: FileVTK.hh:88
OpenVolumeMesh::HalfEdgeHandle
Definition: OpenVolumeMeshHandle.hh:102
OpenMesh::Attributes::Normal
Add normals to mesh item (vertices/faces)
Definition: Attributes.hh:87
FileVTKPlugin::setNormalsOfDuplicatedVerticesOfOpenMesh
void setNormalsOfDuplicatedVerticesOfOpenMesh(MeshT *&_mesh)
Sets normals of duplicated vertices that were created for non-manifold meshes.
Definition: FileVTK.cc:356
FileVTKPlugin::addVertexNormalToOpenMesh
void addVertexNormalToOpenMesh(MeshT _mesh, quint32 _index, OpenMesh::Vec3d _normal)
Adds a vertex normal.
Definition: FileVTK.cc:296
FileVTKPlugin::loadMeshTriangleStrips
bool loadMeshTriangleStrips(QString _spec, QTextStream &_in, MeshT *&_mesh, std::vector< CellType > &_cells)
Reads triangle strips from the stream and adds them to the mesh.
Definition: FileVTK.cc:2011
OpenVolumeMesh::FaceIter
Definition: Iterators.hh:848
FileVTKPlugin::FileVTKPlugin
FileVTKPlugin()
Constructor.
Definition: FileVTK.cc:76
DATA_HEXAHEDRAL_MESH
#define DATA_HEXAHEDRAL_MESH
Definition: HexahedralMesh.hh:63
OpenVolumeMesh::VertexHandle
Definition: OpenVolumeMeshHandle.hh:98
OpenVolumeMesh::OpenVolumeMeshFace
Definition: BaseEntities.hh:90
DataType
Predefined datatypes.
Definition: DataTypes.hh:96
OpenFlipperQSettings::setValue
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
Definition: OpenFlipperQSettings.cc:68
OpenVolumeMesh::CellIter
Definition: Iterators.hh:956
BaseObject::setName
virtual void setName(QString _name)
path to the file from which the object is loaded ( defaults to "." )
Definition: BaseObject.cc:734
OpenVolumeMesh::GeometryKernel
Definition: GeometryKernel.hh:55
DATA_TRIANGLE_MESH
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66
PluginFunctions::hexahedralMesh
HexahedralMesh * hexahedralMesh(BaseObjectData *_object)
Get an HexahedralMesh from an object.
Definition: PluginFunctionsHexahedralMesh.cc:120
FileVTKPlugin::addFaceNormalToOpenMesh
void addFaceNormalToOpenMesh(MeshT _mesh, quint32 _index, OpenMesh::Vec3d _normal)
Adds a face normal.
Definition: FileVTK.cc:305
FileVTKPlugin::addHexaCell
int addHexaCell(TriMesh *&_mesh, std::vector< quint32 > _indices)
Adds a hexa cell to the mesh. (Does nothing, yet)
Definition: FileVTK.cc:472
BaseObject::id
int id() const
Definition: BaseObject.cc:201
FileVTKPlugin::addCellNormal
void addCellNormal(MeshT *&_mesh, const CellType &_cell, OpenMesh::Vec3d _normal)
Adds a normal to the cell.
Definition: FileVTK.cc:313
PluginFunctions::polyhedralMesh
PolyhedralMesh * polyhedralMesh(BaseObjectData *_object)
Get an PolyhedralMesh from an object.
Definition: PluginFunctionsPolyhedralMesh.cc:120
FileVTKPlugin::addWedgeCellToOpenMesh
int addWedgeCellToOpenMesh(MeshT _mesh, std::vector< quint32 > _indices)
Adds a wedge cell to the mesh. (Does nothing, yet)
Definition: FileVTK.cc:222