Developer Documentation
FileOpenVolumeMeshT.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: 13548 $ *
45  * $LastChangedBy: kremer $ *
46  * $Date: 2012-01-27 11:58:19 +0100 (Fr, 27 Jan 2012) $ *
47  * *
48  \*===========================================================================*/
49 
50 #define FILEOPENVOLUMEMESHT_CC
51 
52 #include "FileOpenVolumeMesh.hh"
53 
54 //----------------------------------------------------------------------------
55 
56 template <typename MeshT>
57 void FileOpenVolumeMeshPlugin::loadMesh(const char* _filename, MeshT& _mesh, bool _comp, bool _topCheck) {
58 
59  // found edges in file
60  bool edges_in_file = false;
61 
62  typedef typename MeshT::PointT Vertex;
63  _mesh.clear(false);
64 
65  std::ifstream iff(_filename, std::ios::in);
66 
67  std::string s;
68 
69  // read header
70  iff >> s;
71  if (s != "Vertices") {
72  std::cerr << "ERROR reading OpenVolumeMesh (Vertex Section Failed)\n";
73  iff.close();
74  return;
75  }
76 
77  // read vertices
78  int nv;
79  iff >> nv;
80  for (int i = 0; i < nv; ++i) {
81  double x, y, z;
82  iff >> x;
83  iff >> y;
84  iff >> z;
85 
86  ACG::Vec3d v(x, y, z);
87  _mesh.add_vertex(v);
88  }
89 
90  iff >> s;
91  if (s != "Edges") {
92  std::cerr << "No edges found" << std::endl;
93  } else {
94  edges_in_file = true;
95  int ne;
96  iff >> ne;
97  for (int e = 0; e < ne; ++e) {
98  int v1, v2;
99  iff >> v1;
100  iff >> v2;
102  }
103  }
104 
105  if (edges_in_file) {
106  iff >> s;
107  }
108 
109  if (s != "Faces") {
110  std::cerr << "ERROR reading OpenVolumeMesh (Face Section Failed)\n";
111  iff.close();
112  return;
113  }
114 
115  if(_comp) {
116 
117  // Read vertex indices and define faces
118  // via its vertices (in correct order)
119  int nf;
120  iff >> nf;
121  for (int f = 0; f < nf; ++f) {
122  int nfv;
123  iff >> nfv;
124  std::vector<OpenVolumeMesh::VertexHandle> vids;
125  for (int v = 0; v < nfv; ++v) {
126  int i;
127  iff >> i;
128  vids.push_back(i);
129  }
130  int pos_cell, neg_cell;
131  iff >> pos_cell;
132  iff >> neg_cell;
133  _mesh.add_face(vids);
134  }
135  } else {
136 
137  // Read halfface indices
138  int nf;
139  iff >> nf;
140  for (int f = 0; f < nf; ++f) {
141  int nfhe;
142  iff >> nfhe;
143  std::vector<OpenVolumeMesh::HalfEdgeHandle> hes;
144  for (int he = 0; he < nfhe; ++he) {
145  int i;
146  iff >> i;
147  hes.push_back(i);
148  }
149 
150  _mesh.add_face(hes, _topCheck);
151  }
152  }
153 
154  // Read faces and find the respective halffaces
155  iff >> s;
156  if(s != "Polyhedra") {
157  std::cerr << "ERROR reading OpenVolumeMesh (Polyhedra Section Failed)\n";
158  iff.close();
159  return;
160  }
161 
162  if(_comp) {
163 
164  int nc;
165  iff >> nc;
166 
167  for( int i = 0; i < nc; ++i) {
168 
169  int ncf;
170  iff >> ncf;
171  std::vector< int > faceids;
172 
173  for( int f = 0; f < ncf; ++f) {
174 
175  int fidx;
176  iff >> fidx;
177  faceids.push_back(fidx);
178  }
179 
180  // Get right halffaces
181  // First determine the barycenter of the polyhedron
182  ACG::Vec3d c(0.0, 0.0, 0.0);
183  unsigned int num_faces = faceids.size();
184  for(std::vector<int>::const_iterator it = faceids.begin();
185  it != faceids.end(); ++it) {
186 
187  std::vector<OpenVolumeMesh::HalfEdgeHandle> hes = _mesh.face(*it).halfedges();
188  unsigned int val = hes.size();
189  ACG::Vec3d f_mid(0.0, 0.0, 0.0);
190  for(std::vector<OpenVolumeMesh::HalfEdgeHandle>::const_iterator p_it = hes.begin();
191  p_it != hes.end(); ++p_it) {
192  f_mid += (_mesh.vertex(_mesh.halfedge(*p_it).to_vertex()) / (double)val);
193  }
194  c += f_mid / (double)num_faces;
195  }
196 
197  // Now determine all halffaces
198  // Test whether their normals point into the polyhedron
199  std::vector<OpenVolumeMesh::HalfFaceHandle> hfhandles;
200  for(std::vector<int>::const_iterator it = faceids.begin();
201  it != faceids.end(); ++it) {
202 
203  // Get face's mid-point
204  std::vector<OpenVolumeMesh::HalfEdgeHandle> hes = _mesh.face(*it).halfedges();
205  unsigned int val = hes.size();
206  ACG::Vec3d f_mid(0.0, 0.0, 0.0);
207  for(std::vector<OpenVolumeMesh::HalfEdgeHandle>::const_iterator p_it = hes.begin();
208  p_it != hes.end(); ++p_it) {
209  f_mid += (_mesh.vertex(_mesh.halfedge(*p_it).to_vertex()) / (double)val);
210  }
211 
212  // Now compute the face's normal
213  if(hes.size() < 2) continue;
214  ACG::Vec3d p0 = _mesh.vertex(_mesh.halfedge(hes[0]).from_vertex());
215  ACG::Vec3d p1 = _mesh.vertex(_mesh.halfedge(hes[0]).to_vertex());
216  ACG::Vec3d p2 = _mesh.vertex(_mesh.halfedge(hes[1]).to_vertex());
217  ACG::Vec3d n = (p0 - p1) % (p2 - p1);
218  n.normalize();
219 
220  if(((c - f_mid) | n) >= 0.0) hfhandles.push_back(_mesh.halfface_handle(*it, 0));
221  else hfhandles.push_back(_mesh.halfface_handle(*it, 1));
222  }
223 
224  if(hfhandles.size() > 3) {
225 
226  HexahedralMesh* hm = 0;
227  hm = dynamic_cast<HexahedralMesh*>(&_mesh);
228 
229  if(hm) {
230  hm->add_cell(hfhandles, _topCheck);
231  } else {
232  _mesh.add_cell(hfhandles, _topCheck);
233  }
234  } else {
235  std::cerr << "Could not determine corresponding halffaces!" << std::endl;
236  }
237  }
238  } else {
239 
240  // Just read the specified halffaces
241  int nc;
242  iff >> nc;
243  for (int c = 0; c < nc; ++c) {
244 
245  int nhf;
246  iff >> nhf;
247  std::vector<OpenVolumeMesh::HalfFaceHandle> hfs;
248  for (int hf = 0; hf < nhf; ++hf) {
249  int i;
250  iff >> i;
251  hfs.push_back(i);
252  }
253 
254  // Implement hex mesh shit
255  HexahedralMesh* hm = 0;
256  hm = dynamic_cast<HexahedralMesh*>(&_mesh);
257 
258  if(hm) {
259  hm->add_cell(hfs, _topCheck);
260  } else {
261  _mesh.add_cell(hfs, _topCheck);
262  }
263  }
264  }
265  iff.close();
266 
267  std::cerr << "######## openvolumemesh info #########\n";
268  std::cerr << "#vertices: " << _mesh.n_vertices() << std::endl;
269  std::cerr << "#edges : " << _mesh.n_edges() << std::endl;
270  std::cerr << "#faces : " << _mesh.n_faces() << std::endl;
271  std::cerr << "#cells : " << _mesh.n_cells() << std::endl;
272 }
273 
274 //----------------------------------------------------------------------------
275 
276 template <typename MeshT>
277 void FileOpenVolumeMeshPlugin::saveMesh(const char* _filename, MeshT& _mesh, bool _comp) {
278 
280  std::ofstream off(_filename, std::ios::out);
281 
282  int n_vertices(_mesh.n_vertices());
283  off << "Vertices" << std::endl;
284  off << n_vertices << std::endl;
285 
286  // write vertices
287  for(OpenVolumeMesh::VertexIter v_it = _mesh.v_iter(); v_it; ++v_it) {
288 
289  ACG::Vec3d v = _mesh.vertex(*v_it);
290  off << v[0] << " " << v[1] << " " << v[2] << std::endl;
291  }
292 
293  int n_edges(_mesh.n_edges());
294  off << "Edges" << std::endl;
295  off << n_edges << std::endl;
296 
297  // write edges
298  for(OpenVolumeMesh::EdgeIter e_it = _mesh.e_iter(); e_it; ++e_it) {
299 
300  OpenVolumeMesh::VertexHandle from_vertex = _mesh.edge(*e_it).from_vertex();
301  OpenVolumeMesh::VertexHandle to_vertex = _mesh.edge(*e_it).to_vertex();
302  off << from_vertex << " " << to_vertex << std::endl;
303  }
304 
305  int n_faces(_mesh.n_faces());
306  off << "Faces" << std::endl;
307  off << n_faces << std::endl;
308 
309  // write faces
310  for(OpenVolumeMesh::FaceIter f_it = _mesh.f_iter(); f_it; ++f_it) {
311 
312  off << _mesh.face(*f_it).halfedges().size() << " ";
313 
314  std::vector<OpenVolumeMesh::HalfEdgeHandle> halfedges = _mesh.face(*f_it).halfedges();
315 
316  for (std::vector<OpenVolumeMesh::HalfEdgeHandle>::const_iterator it = halfedges.begin();
317  it != halfedges.end(); ++it) {
318 
319  if(_comp) {
320  off << _mesh.halfedge(*it).from_vertex();
321  } else {
322  off << *it;
323  }
324 
325  if((it+1) != halfedges.end()) off << " ";
326  }
327 
328  off << std::endl;
329  }
330 
331 
332  int n_cells(_mesh.n_cells());
333  off << "Polyhedra" << std::endl;
334  off << n_cells << std::endl;
335 
336  for(OpenVolumeMesh::CellIter c_it = _mesh.c_iter(); c_it; ++c_it) {
337 
338  off << _mesh.cell(*c_it).halffaces().size() << " ";
339 
340  std::vector<OpenVolumeMesh::HalfFaceHandle> halffaces = _mesh.cell(*c_it).halffaces();
341 
342  for (std::vector<OpenVolumeMesh::HalfFaceHandle>::const_iterator it = halffaces.begin();
343  it != halffaces.end(); ++it) {
344 
345  if(_comp) {
346  off << _mesh.face_handle(*it);
347  } else {
348  off << *it;
349  }
350 
351  if((it+1) != halffaces.end()) off << " ";
352  }
353 
354  off << std::endl;
355  }
356 
357  off.close();
358 }
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:428