MEPP2 Project
AIFMeshWriter.inl
Go to the documentation of this file.
1 // Copyright (c) 2012-2019 University of Lyon and CNRS (France).
2 // All rights reserved.
3 //
4 // This file is part of MEPP2; you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as
6 // published by the Free Software Foundation; either version 3 of
7 // the License, or (at your option) any later version.
8 //
9 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12 
15 #ifdef FEVV_USE_VTK
17 #endif
19 
20 #include "FEVV/Types/Material.h"
21 
22 namespace FEVV {
23 namespace DataStructures {
24 namespace AIF {
25 
26 inline
27 void
28 AIFMeshWriter::write(const ptr_input inputMesh, const std::string &filePath)
29 {
30  write(*inputMesh, filePath);
31 }
32 
33 inline
34 void
35 AIFMeshWriter::write(/*const*/ input_type &inputMesh,
36  const std::string &filePath)
37 {
38  using namespace FileUtils;
39 
40  if(!has_extension(filePath))
41  throw std::invalid_argument(
42  "Writer::write -> output file path find without any extension.");
43 
44  // std::cout << "AIFWriting of \"" << get_file_full_name(filePath) << "\"" <<
45  // std::endl;
46 
47  std::vector< std::string > validExtensions = {
48  ".obj", ".off", ".coff", "ply", ".msh"};
49  std::vector< std::string > validVtkExtensions = {".vtk", ".vtp", ".vtu"};
50  if(!(has_extension(filePath, validExtensions)
51 #ifdef FEVV_USE_VTK
52  || has_extension(filePath, validVtkExtensions)
53 #endif
54  ))
55  {
56  throw std::invalid_argument(
57  "Writer::write -> output file extension can't be read (yet).");
58  }
59 
62  typedef AIFPropertiesHelpers PropHelpers;
63  typedef helpers::vertex_container::const_iterator vertex_iterator;
64  typedef boost::iterator_range< vertex_iterator > vertex_range;
65  typedef helpers::edge_container::const_iterator edge_iterator;
66  typedef boost::iterator_range< edge_iterator > edge_range;
67  typedef helpers::face_container::const_iterator face_iterator;
68  typedef boost::iterator_range< face_iterator > face_range;
69  typedef helpers::vertex_container_in_face::const_iterator
70  vertex_face_iterator;
71  typedef boost::iterator_range< vertex_face_iterator > vertex_face_range;
72 
73  std::vector< std::vector< coord_type > > points_coords;
74  std::vector< std::vector< coordN_type > > normals_coords;
75  std::vector< std::vector< coordT_type > > texture_coords;
76  std::vector< std::vector< coordC_type > > vertex_color_coords;
77  std::vector< std::vector< coordC_type > > face_color_coords;
78  std::vector< std::vector< index_type > > lines_indices, faces_indices;
79  std::vector< std::vector< index_type > > texture_face_indices;
80  std::vector< std::vector< index_type > > normal_face_indices;
81  std::vector< std::vector< coordC_type > > line_colors_coords;
82  std::vector< index_type > face_material;
83  std::vector< FEVV::Types::Material > materials;
84 
85  std::vector< std::vector< std::vector< double > > > field_attributes;
86  std::vector< std::string > field_names;
87  // which vertex attribute are available for export ?
88 
89  bool useNorm = false;
90  bool useVertexColor = false;
91  bool useFaceColor = false;
92  bool useVertexTextureCoord = false;
93  bool useVertexDatafield = false;
94  bool useFaceDatafield = false;
95 
96 #ifdef FEVV_USE_VTK
97  bool useEdgeColor =
98  false; // not a common usage, therfore we restric it to vtk
99  if(inputMesh.isPropertyMap< AIFEdge::ptr >("e:color"))
100  useEdgeColor = true;
101 #endif
102 
103  if(inputMesh.isPropertyMap< AIFVertex::ptr >("v:normal"))
104  useNorm = true;
105  if(inputMesh.isPropertyMap< AIFVertex::ptr >("v:color"))
106  useVertexColor = true;
107  if(inputMesh.isPropertyMap< AIFFace::ptr >("f:color"))
108  useFaceColor = true;
109  if(inputMesh.isPropertyMap< AIFVertex::ptr >("v:texcoord"))
110  useVertexTextureCoord = true;
111  if (inputMesh.isAPropertyMapStartingWithPrefix< AIFVertex::ptr >("v:datafield:"))
112  useVertexDatafield = true;
113  if (inputMesh.isAPropertyMapStartingWithPrefix< AIFFace::ptr >("f:datafield:"))
114  useFaceDatafield = true;
115 
116  std::vector<std::string> dfv_names = inputMesh.GetPropertyMapNamesStartingWithPrefix< AIFVertex::ptr >("v:datafield:");
117  std::vector<std::string> dff_names = inputMesh.GetPropertyMapNamesStartingWithPrefix< AIFFace::ptr >("f:datafield:");
118 
119  long vertexIndex = 0; // to be sure to start to 0
120  std::map< helpers::vertex_descriptor, long >
121  indexMap; // for correct corresponding between vertex order in file and
122  // vertices around face indices
123 
124  // VERTICES IN CONTAINER
125  vertex_range vRange = helpers::vertices(inputMesh);
126 
127  for(vertex_iterator itV = vRange.begin(); itV != vRange.end(); ++itV)
128  {
129  PropHelpers::Point p = PropHelpers::get_point(inputMesh, *itV);
130  std::vector< coord_type > point;
131 
132  for(unsigned int i = 0; i < p.size(); ++i)
133  point.push_back(p[i]);
134 
135  points_coords.push_back(point);
136 
137  indexMap[*itV] = vertexIndex;
138  ++vertexIndex;
139 
140  // deal with vertex attributes here
141 
142  if(useNorm)
143  {
144  // store vertex normal in standard container
145  AIFMesh::Normal &vn =
146  inputMesh.GetProperty< AIFVertex::ptr, AIFMesh::Normal >(
147  "v:normal", (*itV)->GetIndex());
148  std::vector< coordN_type > normal(vn.cbegin(), vn.cend());
149  normals_coords.push_back(normal);
150  }
151 
152  if(useVertexColor)
153  {
154  // store vertex color in standard container
155  AIFMesh::Vector &vc =
156  inputMesh.GetProperty< AIFVertex::ptr, AIFMesh::Vector >(
157  "v:color", (*itV)->GetIndex());
158  std::vector< coordC_type > color(vc.cbegin(), vc.cend());
159  vertex_color_coords.push_back(color);
160  }
161 
162  if(useVertexTextureCoord)
163  {
164  // store vertex texture-coordinates in standard container
165  AIFMesh::PointUV &uv =
166  inputMesh.GetProperty< AIFVertex::ptr, AIFMesh::PointUV >(
167  "v:texcoord", (*itV)->GetIndex());
168  std::vector< coordT_type > vt(uv.cbegin(), uv.cend());
169  texture_coords.push_back(vt);
170  }
171 
172  if (useVertexDatafield)
173  {
174  auto it_s = dfv_names.begin(), it_se = dfv_names.end();
175  size_t i = 0;
176  for (; it_s != it_se; ++it_s, ++i)
177  {
178  const std::vector< double >&vdata =
179  inputMesh.GetProperty< AIFVertex::ptr, std::vector< double > >(
180  *it_s, (*itV)->GetIndex());
181 
182  if (itV == vRange.begin())
183  {
184  field_names.push_back("POINT_DATA_" + it_s->substr(12));
185  field_attributes.resize(field_attributes.size() + 1);
186  }
187 
188  field_attributes[i].push_back(vdata);
189  }
190  }
191  }
192 
193  // EDGES IN CONTAINER (needed to take into accound dangling or isolated edges)
194  edge_range eRange = helpers::edges(inputMesh);
195 
196  for(edge_iterator itE = eRange.begin(); itE != eRange.end(); ++itE)
197  {
199  {
200  std::vector< index_type > line;
201 
202  line.push_back(indexMap[(*itE)->get_first_vertex()]);
203  line.push_back(indexMap[(*itE)->get_second_vertex()]);
204 
205  lines_indices.push_back(line);
206 #ifdef FEVV_USE_VTK
207  if(useEdgeColor)
208  {
209  // store vertex color in standard container
210  AIFMesh::Vector &vc =
211  inputMesh.GetProperty< AIFEdge::ptr, AIFMesh::Vector >(
212  "e:color", (*itE)->GetIndex());
213  std::vector< coordC_type > color(vc.cbegin(), vc.cend());
214  line_colors_coords.push_back(color);
215  }
216 #endif
217  }
218  }
219 
220  // FACES IN CONTAINER
221  std::set< AIFVertex::ptr > already_processed; // use to export dangling polylines only once
222  face_range fRange = helpers::faces(inputMesh);
223 
224  for(face_iterator itF = fRange.begin(); itF != fRange.end(); ++itF)
225  {
226  std::vector< index_type > face;
227  std::vector< index_type > normal_indices;
228  std::vector< index_type > texture_indices;
229 
230  vertex_face_range vfRange = helpers::incident_vertices(*itF);
231 
232  for(vertex_face_iterator itVF = vfRange.begin(); itVF != vfRange.end();
233  ++itVF)
234  {
235  if ( has_extension(filePath, ".off") )
236  {
237  auto nb_incident_dangling_edges = helpers::num_incident_dangling_edge(*itVF);
238  if(nb_incident_dangling_edges>1)
239  throw std::runtime_error("Writer::write -> multiple dangling edge integration into face indices is not available for .off");
240  else if ( (nb_incident_dangling_edges == 1) && (already_processed.find(*itVF)==already_processed.end()))
241  {
242  already_processed.insert(*itVF);
243  //throw std::runtime_error("Writer::write -> dangling edge integration into face indices for .off has not been implemented yet");
244  // 1) insert the dangling polyline
245  AIFVertex::ptr current_v = *itVF;
246  AIFEdge::ptr current_e = helpers::get_incident_dangling_edge(current_v);
247  face.push_back(indexMap[*itVF]);
248  int nb_indices_before = static_cast<int>(face.size());
249  do
250  {
251  current_v = helpers::opposite_vertex(current_e, current_v);
252  face.push_back(indexMap[current_v]);
254  nb_incident_dangling_edges = helpers::num_incident_dangling_edge(current_v);
255  auto evRange = helpers::incident_edges(current_v);
256  auto iterE = evRange.begin();
257  for(; iterE != evRange.end(); ++iterE)
258  {
259  if (*iterE != current_e)
260  {
261  current_e = *iterE;
262  break;
263  }
264  }
265  } while (nb_incident_dangling_edges==2); // we only deal with dangling polylines without bisection
266  int nb_indices_after = static_cast<int>(face.size());
267  std::vector<index_type> additional_indices;
268  for (int i = nb_indices_after-2; i >= nb_indices_before; --i)
269  {
270  additional_indices.push_back(face[i]);
271  }
272  face.insert(face.end(), additional_indices.begin(), additional_indices.end());
273  // 2) remove it from lines_indices
274  // not done since a) it is costly and b) lines_indices are not used by off writer
275  }
276  }
277  face.push_back(
278  indexMap[*itVF]); // for correct corresponding between vertex order in
279  // file and vertices around face indices
280 
281  // face's vertices attributes (normal & texture)
282  if(useNorm)
283  normal_indices.push_back(indexMap[*itVF]);
284  if(useVertexTextureCoord)
285  texture_indices.push_back(indexMap[*itVF]);
286  }
287 
288  faces_indices.push_back(face);
289  if(useNorm)
290  normal_face_indices.push_back(normal_indices);
291  if(useVertexTextureCoord)
292  texture_face_indices.push_back(texture_indices);
293 
294  // face color
295  if(useFaceColor)
296  {
297  // retrieve face-color from property map
298  AIFMesh::Vector &fc =
299  inputMesh.GetProperty< AIFFace::ptr, AIFMesh::Vector >(
300  "f:color", (*itF)->GetIndex());
301 
302  // store face-color in standard container
303  std::vector< coordC_type > color(fc.cbegin(), fc.cend());
304  face_color_coords.push_back(color);
305  }
306 
307  if (useFaceDatafield)
308  {
309  auto it_s = dff_names.begin(), it_se = dff_names.end();
310  size_t i = 0;
311  for (; it_s != it_se; ++it_s, ++i)
312  {
313  const std::vector< double >&vdata =
314  inputMesh.GetProperty< AIFFace::ptr, std::vector< double > >(
315  *it_s, (*itF)->GetIndex());
316 
317  if (itF == fRange.begin())
318  {
319  field_names.push_back("CELL_DATA_" + it_s->substr(12));
320  field_attributes.resize(field_attributes.size() + 1);
321  }
322  if (useVertexDatafield && (it_s == dff_names.begin()))
323  i = dfv_names.size();
324 
325  field_attributes[i].push_back(vdata);
326  }
327  }
328  }
329 
330  if(has_extension(filePath, ".obj"))
331  {
332  IO::write_obj_file(filePath,
333  points_coords,
334  normals_coords,
335  texture_coords,
336  vertex_color_coords,
337  faces_indices,
338  texture_face_indices,
339  normal_face_indices,
340  materials,
341  face_material);
342  }
343  else if(has_extension(filePath, ".off") || has_extension(filePath, ".coff"))
344  {
345  IO::write_off_file(filePath,
346  points_coords,
347  normals_coords,
348  texture_coords,
349  vertex_color_coords,
350  faces_indices,
351  face_color_coords,
352  helpers::num_edges(inputMesh));
353  }
354  else if(has_extension(filePath, ".ply"))
355  {
356  throw std::runtime_error(
357  "Writer::write -> ply writer has not been implemented yet");
358  }
359  else if(has_extension(filePath, ".msh"))
360  {
361  IO::write_gmsh_file(filePath,
362  points_coords,
363  normals_coords,
364  vertex_color_coords,
365  lines_indices,
366  line_colors_coords,
367  faces_indices,
368  face_color_coords,
369  field_attributes,
370  field_names);
371  }
372 #ifdef FEVV_USE_VTK
373  else if(has_extension(filePath, ".vtk") || has_extension(filePath, ".vtp") ||
374  has_extension(filePath, ".vtu"))
375  {
377  points_coords,
378  normals_coords,
379  vertex_color_coords,
380  lines_indices,
381  line_colors_coords,
382  faces_indices,
383  face_color_coords,
384  field_attributes,
385  field_names);
386  }
387 #endif
388 
389  // std::cout << "AIFWriting of \"" << get_file_full_name(filePath) << "\"
390  // Done." << std::endl;
391 }
392 
393 } // namespace AIF
394 } // namespace DataStructures
395 } // namespace FEVV
FEVV::IO::write_off_file
void write_off_file(std::string file_path, std::vector< std::vector< CoordType > > &points_coords, std::vector< std::vector< CoordNType > > &normals_coords, std::vector< std::vector< CoordTType > > &texture_coords, std::vector< std::vector< CoordCType > > &vertex_color_coords, std::vector< std::vector< IndexType > > &face_indices, std::vector< std::vector< CoordCType > > &face_color_coords, unsigned long nb_total_edges=0)
Definition: OffFileWriter.h:50
helpers
AIFTopologyHelpers helpers
Definition: test_helpers_aif.cpp:16
FEVV::DataStructures::AIF::AIFTopologyHelpers::incident_vertices
static boost::iterator_range< vertex_container_in_edge::const_iterator > incident_vertices(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:1189
FEVV::DataStructures::AIF::AIFVertex::ptr
boost::shared_ptr< self > ptr
Definition: AIFVertex.hpp:47
FEVV::DataStructures::AIF::AIFTopologyHelpers::opposite_vertex
static vertex_descriptor opposite_vertex(edge_descriptor edge, vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:1270
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_isolated_edge
static bool is_isolated_edge(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:995
FEVV::DataStructures::AIF::AIFMeshWriter::ptr_input
superclass::ptr_input ptr_input
Definition: AIFMeshWriter.hpp:43
FEVV::DataStructures::AIF::AIFTopologyHelpers::num_edges
static size_type num_edges(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2174
FEVV::DataStructures::AIF::AIFFace::ptr
boost::shared_ptr< self > ptr
Definition: AIFFace.hpp:52
ObjFileWriter.h
FEVV::DataStructures::AIF::AIFTopologyHelpers::num_incident_dangling_edge
static size_type num_incident_dangling_edge(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:1079
FEVV::IO::write_obj_file
void write_obj_file(const std::string &file_path, std::vector< std::vector< CoordType > > &points_coords, std::vector< std::vector< CoordNType > > &normals_coords, std::vector< std::vector< CoordTType > > &texture_coords, std::vector< std::vector< CoordCType > > &vertex_color_coords, std::vector< std::vector< IndexType > > &face_indices, std::vector< std::vector< IndexType > > &texture_face_indices, std::vector< std::vector< IndexType > > &normal_face_indices, std::vector< MaterialType > &materials, std::vector< IndexType > &face_material)
Definition: ObjFileWriter.h:196
Point
AIFMesh::Point Point
Definition: Graph_properties_aif.h:21
Material.h
FEVV::DataStructures::AIF::AIFTopologyHelpers::faces
static boost::iterator_range< face_container::const_iterator > faces(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2606
FEVV::DataStructures::AIF::AIFTopologyHelpers::is_dangling_edge
static bool is_dangling_edge(edge_descriptor edge)
Definition: AIFTopologyHelpers.h:1009
FEVV::DataStructures::AIF::AIFMeshWriter::write
void write(const ptr_input inputMesh, const std::string &filePath)
Definition: AIFMeshWriter.inl:28
FEVV
Interfaces for plugins These interfaces will be used for different plugins.
Definition: Assert.h:16
FEVV::IO::write_vtk_or_vtp_or_vtu_file
void write_vtk_or_vtp_or_vtu_file(std::string file_path, const std::vector< std::vector< CoordType > > &points_coords, const std::vector< std::vector< CoordNType > > &normals_coords, const std::vector< std::vector< CoordCType > > &vertex_color_coords, const std::vector< std::vector< IndexType > > &line_indices, const std::vector< std::vector< CoordCType > > &lines_color_coords, const std::vector< std::vector< IndexType > > &face_indices, const std::vector< std::vector< CoordCType > > &face_color_coords, const std::vector< std::vector< std::vector< double > > > &field_attributes, const std::vector< std::string > &field_names)
Definition: VtkFileWriter.h:727
MshFileWriter.h
VtkFileWriter.h
FEVV::DataStructures::AIF::AIFTopologyHelpers::get_incident_dangling_edge
static edge_descriptor get_incident_dangling_edge(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:1109
FEVV::face_material
@ face_material
Definition: properties.h:85
FEVV::IO::write_gmsh_file
bool write_gmsh_file(const std::string &file_path, const std::vector< std::vector< CoordType > > &points_coords, const std::vector< std::vector< CoordNType > > &normals_coords, const std::vector< std::vector< CoordCType > > &vertex_color_coords, const std::vector< std::vector< IndexType > > &line_indices, const std::vector< std::vector< CoordCType > > &lines_color_coords, const std::vector< std::vector< IndexType > > &face_indices, const std::vector< std::vector< CoordCType > > &face_color_coords, const std::vector< std::vector< std::vector< double > > > &field_attributes, const std::vector< std::string > &field_names)
Definition: MshFileWriter.h:51
FEVV::DataStructures::AIF::AIFTopologyHelpers::edges
static boost::iterator_range< edge_container::const_iterator > edges(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2261
FEVV::DataStructures::AIF::AIFEdge::ptr
boost::shared_ptr< self > ptr
Definition: AIFEdge.hpp:56
FEVV::DataStructures::AIF::AIFVector
Definition: AIFProperties.h:173
FEVV::DataStructures::AIF::AIFMesh::PointUV
std::array< CoordinateType, 2 > PointUV
Definition: AIFMesh.hpp:65
FEVV::DataStructures::AIF::AIFTopologyHelpers::incident_edges
static boost::iterator_range< edge_container_in_vertex::const_iterator > incident_edges(vertex_descriptor vertex)
Definition: AIFTopologyHelpers.h:399
FEVV::DataStructures::AIF::AIFCellContainer< vertex_type::ptr >::const_iterator
std::vector< vertex_type::ptr >::const_iterator const_iterator
Definition: AIFCellContainer.h:29
FEVV::DataStructures::AIF::AIFTopologyHelpers
This class is an helper class associated to the AIFMesh structure. AIFTopologyHelpers implements all ...
Definition: AIFTopologyHelpers.h:57
FEVV::DataStructures::AIF::AIFTopologyHelpers::vertices
static boost::iterator_range< vertex_container::const_iterator > vertices(ptr_cmesh mesh)
Definition: AIFTopologyHelpers.h:2227
FEVV::DataStructures::AIF::face
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::face_descriptor face(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor h, const FEVV::DataStructures::AIF::AIFMesh &)
Returns the face incident to halfedge h.
Definition: Graph_traits_aif.h:664
FEVV::FileUtils::has_extension
bool has_extension(const std::string &file_name)
Definition: FileUtilities.hpp:58
FEVV::DataStructures::AIF::AIFMeshWriter::input_type
superclass::input_type input_type
Definition: AIFMeshWriter.hpp:42
FileUtilities.hpp
OffFileWriter.h
FEVV::DataStructures::AIF::AIFPropertiesHelpers
This class is an helper class associated to the AIFMesh structure. AIFPropertiesHelpers implements al...
Definition: AIFPropertiesHelpers.h:28