MEPP2 Project
mesh_from_vector_representation.hpp
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.
11 #pragma once
12 
13 #include <boost/graph/graph_traits.hpp>
14 #include <boost/graph/properties.hpp>
17 
18 // DBG #undef NDEBUG // disable some unwanted assertions in Debug mode
19 #include <CGAL/boost/graph/helpers.h>
20 #include <CGAL/boost/graph/internal/helpers.h>
21 #include <CGAL/boost/graph/Euler_operations.h> // for add_face(vr,g)
22 
24 
25 
26 namespace FEVV {
27 namespace Filters {
28 
32 inline
34 {
35  FEVV::Types::Image *cimg = new FEVV::Types::Image(256, 256, 1, 3);
36 
37  // draw gradient
38 
39  // loop over pixels
40  for(int row = 0; row < (*cimg).height(); row++)
41  {
42  for(int col = 0; col < (*cimg).width(); col++)
43  {
44  // (*cimg)(x, y, z, channel)
45  (*cimg)(col, row, 0, 0) = col; // R = x = col
46  (*cimg)(col, row, 0, 1) = row; // G = y = row
47  (*cimg)(col, row, 0, 2) = 0; // B = constant
48  }
49  }
50 
51  // draw text
52 
53  const unsigned char gray[] = { 128, 128, 128 };
54 
55  int size1 = 72;
56  (*cimg).draw_text(20, 128-(size1/2), "NO TEX", gray, 0, 1.0, size1);
57 
58  int size2 = 32;
59  (*cimg).draw_text( 2, 0, "(0;0)", gray, 0, 1.0, size2);
60  (*cimg).draw_text(255-50, 0, "(1;0)", gray, 0, 1.0, size2);
61  (*cimg).draw_text( 2, 255-size2, "(0;1)", gray, 0, 1.0, size2);
62  (*cimg).draw_text(255-50, 255-size2, "(1;1)", gray, 0, 1.0, size2);
63 
64  return cimg;
65 }
66 
70 template< typename BoostGraph >
71 using VertDescVect = std::vector<
73 
74 
78 template< typename FaceGraph >
79 using FaceDescVect = std::vector<
80  typename boost::graph_traits< FaceGraph >::face_descriptor >;
81 
82 
90 template< typename FaceGraph >
92 {
95 
97  bool _use_corner_texcoord)
98  {
99  m_use_corner_texcoord = _use_corner_texcoord;
100  return *this;
101  }
102 
104  {
105  m_vd_target = _vd_target;
106  return *this;
107  }
108 
110  {
111  m_fd_target = _fd_target;
112  return *this;
113  }
114 
116  VDVect *m_vd_target = nullptr;
117  FDVect *m_fd_target = nullptr;
118 };
119 
120 
134 template< typename HalfedgeGraph,
135  typename coordP_type,
136  typename coordN_type,
137  typename coordT_type,
138  typename coordC_type,
139  typename index_type,
140  typename GeometryTraits >
141 void
143  HalfedgeGraph &g,
144  FEVV::PMapsContainer &pmaps,
145  unsigned int &dup_v_nbr,
146  FEVV::Types::MVR < coordP_type,
147  coordN_type,
148  coordT_type,
149  coordC_type,
150  index_type > &mvr,
152  const GeometryTraits &/*gt*/)
153 {
154  typedef boost::graph_traits< HalfedgeGraph > GraphTraits;
156  //typedef typename GraphTraits::edge_descriptor edge_descriptor;
157  typedef typename GraphTraits::face_descriptor face_descriptor;
158  typedef typename GraphTraits::halfedge_descriptor halfedge_descriptor;
159  //typedef typename GraphTraits::face_iterator face_iterator;
160  typedef typename GeometryTraits::Point Point;
161  typedef typename GeometryTraits::Vector Vector;
162 
165 
166  // vertex-color must be defined for all vertices or none
167  if(mvr.vertex_color_coords.size() != mvr.points_coords.size())
168  mvr.vertex_color_coords.clear();
169  for(auto &color : mvr.vertex_color_coords)
170  {
171  if(color.size() != 3)
172  {
173  std::cout << __func__
174  << "(): found vertex color with size != 3. Disabling "
175  "vertex color for all vertices."
176  << std::endl;
177  mvr.vertex_color_coords.clear();
178  break;
179  }
180  }
181 
182  // face-color must be defined for all faces or none
183  if(mvr.face_color_coords.size() != mvr.faces_indices.size())
184  mvr.face_color_coords.clear();
185  for(auto &color : mvr.face_color_coords)
186  {
187  if(color.size() != 3)
188  {
189  std::cout << __func__
190  << "(): found face color with size != 3. Disabling "
191  "face color for all vertices."
192  << std::endl;
193  mvr.face_color_coords.clear();
194  break;
195  }
196  }
197 
198  // check if vertex color is in range 0...255
199  bool is_vertex_color_0_255 = false;
200  if(! mvr.vertex_color_coords.empty())
201  {
202  for(auto &color : mvr.vertex_color_coords)
203  {
204  if(color[0] > 1 || color[1] > 1 || color[2] > 1)
205  {
206  is_vertex_color_0_255 = true;
207  std::cout << __func__
208  << "(): vertex color will be converted from [0,255] "
209  "to [0.0,1.0]."
210  << std::endl;
211  break;
212  }
213  }
214  }
215 
216  // check if face color is in range 0...255
217  bool is_face_color_0_255 = false;
218  if(! mvr.face_color_coords.empty())
219  {
220  for(auto &color : mvr.face_color_coords)
221  {
222  if(color[0] > 1 || color[1] > 1 || color[2] > 1)
223  {
224  is_face_color_0_255 = true;
225  std::cout << __func__
226  << "(): face color will be converted from [0,255] "
227  "to [0.0,1.0]."
228  << std::endl;
229  break;
230  }
231  }
232  }
233 
234  // material must be defined for all faces or none
235  if(! mvr.face_material.empty())
236  {
237  if(mvr.face_material.size() != mvr.faces_indices.size())
238  {
239  std::cout << __func__
240  << "(): found some faces with a material and some "
241  "without. Disabling material for all faces."
242  << std::endl;
243  mvr.face_material.clear();
244  }
245  }
246 
247  // check if all faces have a valid material
248  if(! mvr.face_material.empty())
249  {
250  for(auto &mtl_id : mvr.face_material)
251  {
252  if(mtl_id == static_cast< index_type >(-1))
253  {
254  std::cout << __func__
255  << "(): found some faces with an invalid material. "
256  "Disabling material for all faces."
257  << std::endl;
258  mvr.face_material.clear();
259  break;
260  }
261  }
262  }
263 
264  // store materials in a property map
265  if(! mvr.materials.empty())
266  {
267  // load texture images for all materials
268  for(size_t i = 0; i < mvr.materials.size(); i++)
269  {
270  auto &material = mvr.materials[i];
271 
272  for(const auto &texture_filename : { material.ambient_texture_filename,
273  material.diffuse_texture_filename,
274  material.specular_texture_filename,
275  material.emissive_texture_filename,
276  material.transparency_texture_filename,
277  material.normal_map_filename,
278  material.metallic_map_filename,
279  material.roughness_map_filename })
280  {
281  if(texture_filename.empty())
282  continue;
283 
284  try
285  {
286  material.images[texture_filename] =
287  std::shared_ptr< FEVV::Types::Image >(
288  new FEVV::Types::Image(texture_filename.c_str()));
289  }
290  catch(const cimg_library::CImgIOException &/*e*/)
291  {
292  material.images[texture_filename] =
293  std::shared_ptr< FEVV::Types::Image >(
295  );
296  }
297  }
298  }
299 
300  // create a property map to store the material
301  auto mtl_pm = make_property_map(FEVV::mesh_materials, g);
302 
303  // populate material property map
304  for(size_t i = 0; i < mvr.materials.size(); i++)
305  put(mtl_pm, i, mvr.materials[i]);
306 
307  // add property map to bag
308  put_property_map(FEVV::mesh_materials, g, pmaps, mtl_pm);
309 
310  std::cout << __func__
311  << "(): property map for materials created."
312  << std::endl;
313  }
314 
315  // import data into mesh datastructure
316 
317  bool use_vertex_normal = false;
318  bool use_vertex_color = false;
319  bool use_vertex_texture_coord = false;
320  bool use_face_color = false;
321  bool use_face_material = false;
322  bool use_face_normal = false; // per-face vertices normals
323  //unused bool use_line_color = false;
324  bool use_corner_texture_coord = params.m_use_corner_texcoord;
325 
326  if(! mvr.texture_coords.empty())
327  {
328  // choose between vertex-texcoord and corner-texcoord
329  if(use_corner_texture_coord)
330  {
331  // corner-texture must be used
332  // nothing to do
333  }
334  else if(mvr.texture_coords.size() == mvr.points_coords.size())
335  {
336  // texture coordinates are given by vertex
337  use_vertex_texture_coord = true;
338  }
339  else if(mvr.texture_face_indices.size() == mvr.faces_indices.size())
340  {
341  // texture coordinates are given by corner
342  use_corner_texture_coord = true;
343  }
344 
345  // create property map to store texcoord
346  if(use_vertex_texture_coord)
347  {
348  // create property map to store vertex texture-coord
349  auto vtexcoord_pm = make_property_map(FEVV::vertex_texcoord, g);
350  put_property_map(FEVV::vertex_texcoord, g, pmaps, vtexcoord_pm);
351 
352  std::cout << __func__
353  << "(): property map for vertex-texture-coordinate created."
354  << std::endl;
355  }
356  else if(use_corner_texture_coord)
357  {
358  // create property map to store corner texture-coord
359  auto htexcoord_pm = make_property_map(FEVV::halfedge_texcoord, g);
360  put_property_map(FEVV::halfedge_texcoord, g, pmaps, htexcoord_pm);
361 
362  std::cout << __func__
363  << "(): property map for halfedge-texture-coordinate "
364  "created."
365  << std::endl;
366  }
367  }
368  else
369  {
370  // no texture coord provided in mesh vertex representation
371  use_corner_texture_coord = false;
372  }
373 
374 
375  if(! mvr.normals_coords.empty())
376  {
377  // per-vertex normal or per-face-vertex normal ?
378  // if there are as many normals as vertices, then it's per-vertex normal
379 
380  if(mvr.normals_coords.size() == mvr.points_coords.size())
381  {
382  use_vertex_normal = true;
383 
384  // create property map to store vertex normal
385  auto vn_pm = make_property_map(FEVV::vertex_normal, g);
386  put_property_map(FEVV::vertex_normal, g, pmaps, vn_pm);
387 
388  std::cout << __func__
389  << "(): property map for vertex-normal created."
390  << std::endl;
391  }
392  else if(! mvr.normal_face_indices[0].empty())
393  {
394  // per-face-vertex normal
395  use_face_normal = true;
396 
397  // create property map to store face-vertex normal
398  auto fn_pm = make_property_map(FEVV::face_normal, g);
399  put_property_map(FEVV::face_normal, g, pmaps, fn_pm);
400 
401  std::cout << __func__
402  << "(): property map for face-normal created."
403  << std::endl;
404  }
405  }
406 
407  if(! mvr.vertex_color_coords.empty())
408  {
409  use_vertex_color = true;
410 
411  // create property map to store vertex color
412  auto vc_pm = make_property_map(FEVV::vertex_color, g);
413  put_property_map(FEVV::vertex_color, g, pmaps, vc_pm);
414 
415  std::cout << __func__
416  << "(): property map for vertex-color created."
417  << std::endl;
418  }
419 
420  if(! mvr.face_color_coords.empty())
421  {
422  use_face_color = true;
423 
424  // create property map to store face color
425  auto fc_pm = make_property_map(FEVV::face_color, g);
426  put_property_map(FEVV::face_color, g, pmaps, fc_pm);
427 
428  std::cout << __func__
429  << "(): property map for face-color created."
430  << std::endl;
431  }
432 
433  if(! mvr.face_material.empty())
434  {
435  use_face_material = true;
436 
437  // create property map to store face material
438  auto fm_pm = make_property_map(FEVV::face_material, g);
439  put_property_map(FEVV::face_material, g, pmaps, fm_pm);
440 
441  std::cout << __func__
442  << "(): property map for face-material created."
443  << std::endl;
444  }
445 
448 
449 
452 
453  std::vector< vertex_descriptor > vertices;
454  vertices.reserve(mvr.points_coords.size());
455 
456  typedef typename std::vector< std::vector< coordP_type > >::const_iterator
457  point_it;
458  auto point_pm = get(boost::vertex_point, g);
459  int vertex_nbr = 0;
460  // loop over vertices/points
461  for(point_it it_p = mvr.points_coords.begin();
462  it_p != mvr.points_coords.end();
463  ++it_p)
464  {
465  vertex_descriptor current_vertex = add_vertex(g);
466  vertex_nbr++;
467 
468  put(point_pm, current_vertex, Point((*it_p)[0], (*it_p)[1], (*it_p)[2]));
469 
470  vertices.push_back(current_vertex);
471  // note : must keep the vertex in a vector to handle
472  // vertex indices for faces
473 
474  // Vertex normal/color/texture-coords addition when present
475  if(use_vertex_normal || use_vertex_color || use_vertex_texture_coord)
476  {
477  if(use_vertex_normal)
478  {
479  // DBG std::cout << "store normal by vertex #" << vertexNbr <<
480  // std::endl;
481  std::vector< coordN_type > &coords = mvr.normals_coords[vertex_nbr - 1];
482 
483  if(coords.size() != 3)
484  throw std::runtime_error("Support of normal coordinates of size != 3 "
485  "not yet implemented!");
486  // store normal in property map
487  Vector vn(coords[0], coords[1], coords[2]);
488  auto vn_pm = get_property_map(FEVV::vertex_normal, g, pmaps);
489  put(vn_pm, current_vertex, vn);
490  }
491  if(use_vertex_color)
492  {
493  // DBG std::cout << "store color for vertex #" << vertexNbr <<
494  // std::endl;
495  std::vector< coordC_type > &coords =
496  mvr.vertex_color_coords[vertex_nbr - 1];
497  // at this point we are sure that coords.size() == 3 because of
498  // previous sanity checks
499 
500  // fix colors in [0.0, 1.0] if provided in [0, 255]
501  if(is_vertex_color_0_255)
502  {
503  // conversion copied from Mepp1
504  // (src/mepp/Polyhedron/Polyhedron_OFF_CGALImporter.h)
505  int rgb[3];
506  rgb[0] = (int)floor(coords[0] + 0.5);
507  rgb[1] = (int)floor(coords[1] + 0.5);
508  rgb[2] = (int)floor(coords[2] + 0.5);
509  coords[0] = (coordC_type)((float)rgb[0] / 255.0);
510  coords[1] = (coordC_type)((float)rgb[1] / 255.0);
511  coords[2] = (coordC_type)((float)rgb[2] / 255.0);
512  }
513 
514  // store color in property map
515  Vector vc(coords[0], coords[1], coords[2]);
516  auto vc_pm = get_property_map(FEVV::vertex_color, g, pmaps);
517  put(vc_pm, current_vertex, vc);
518  }
519  if(use_vertex_texture_coord)
520  {
521  // DBG std::cout << "store tex coord for vertex #" << vertexNbr <<
522  // std::endl;
523  std::vector< coordT_type > &coords = mvr.texture_coords[vertex_nbr - 1];
524 
525  if(coords.size() != 2)
526  throw std::runtime_error("Support of texture coordinates of size != "
527  "2 not yet implemented!");
528 
529  // store texture coordinates in property map
530  Vector tex_coords(coords[0], coords[1], 0);
531  auto vt_pm = get_property_map(FEVV::vertex_texcoord, g, pmaps);
532  put(vt_pm, current_vertex, tex_coords);
533  }
534  }
535 
536  // save current vertex descriptor for later use
537  if(params.m_vd_target)
538  {
539  params.m_vd_target->push_back(current_vertex);
540  }
541  }
542 
545 
546  dup_v_nbr = 0;
547  typedef typename std::vector< std::vector< index_type > >::const_iterator
548  face_it;
549  typedef typename std::vector< index_type >::const_iterator index_it;
550  size_t face_id = 0;
551  // loop over the faces
552  for(face_it it_f = mvr.faces_indices.begin();
553  it_f != mvr.faces_indices.end();
554  ++it_f, ++face_id)
555  {
556  if(it_f->size() < 2)
557  {
558  throw std::runtime_error(std::string(__func__) +
559  "(): find a face with less than two "
560  "vertices : not conform.");
561  }
562  else if(it_f->size() == 2)
563  {
564  throw std::runtime_error(std::string(__func__) +
565  "(): found a face with two vertices, "
566  "isolated edge not supported.");
567  }
568  else
569  {
570  //--- create the face
571 
572  std::vector< vertex_descriptor > face_vertices;
573 
574  // loop over face's vertices
575  for(index_it it = it_f->begin(); it != it_f->end(); ++it)
576  {
577  // add current vertex to vertices list
578  face_vertices.push_back(vertices[(*it)]);
579  }
580 
581  // add face to mesh
582 
583  // DBG static unsigned int counter = 0;
584  // DBG counter ++;
585  // DBG std::cout << "call CGAL::Euler::add_face(face_vertices, g) #" <<
586  // counter << std::endl;
587 
588  face_descriptor current_face = CGAL::Euler::add_face(face_vertices, g);
589 
590  if(current_face == GraphTraits::null_face())
591  {
592  // helper lambda function to duplicate a vertex and its attributes
593  auto duplicate_v = [ &face_vertices,
594  &g,
595  &dup_v_nbr,
596  &pmaps,
597  &use_vertex_normal,
598  &use_vertex_color,
599  &use_vertex_texture_coord ](size_t i) -> void
600  {
601  vertex_descriptor vold = face_vertices[i];
602 
603  // create new vertex
604  vertex_descriptor vnew = add_vertex(g);
605  face_vertices[i] = vnew;
606  dup_v_nbr++;
607 
608  // set new vertex geometry
609  auto point_pm = get(boost::vertex_point, g);
610  put(point_pm, vnew, get(point_pm, vold));
611 
612  // set new vertex attributes
613  if(use_vertex_normal)
614  {
615  auto vn_pm = get_property_map(FEVV::vertex_normal, g, pmaps);
616  //put(vn_pm, vnew, get(vn_pm, vold));
617  // splitted in 2 lines to avoid random crash on Windows
618  Vector normal = get(vn_pm, vold);
619  put(vn_pm, vnew, normal);
620  }
621  if(use_vertex_color)
622  {
623  auto vc_pm = get_property_map(FEVV::vertex_color, g, pmaps);
624  //put(vc_pm, vnew, get(vc_pm, vold));
625  // splitted in 2 lines to avoid random crash on Windows
626  Vector color = get(vc_pm, vold);
627  put(vc_pm, vnew, color);
628  }
629  if(use_vertex_texture_coord)
630  {
631  auto vt_pm = get_property_map(FEVV::vertex_texcoord, g, pmaps);
632  //put(vt_pm, vnew, get(vt_pm, vold));
633  // splitted in 2 lines to avoid random crash on Windows
634  Vector coord = get(vt_pm, vold);
635  put(vt_pm, vnew, coord);
636  }
637  };
638 
639  // the code in this section addresses the two
640  // first reasons why Euler::add_face(vr, g)
641  // returns null_face():
642  // - one face's vertex is not on a border
643  // - one face's halfedge is not on a border
644  // (see Euler_operations.h line 593 to 606)
645 
646  // DBG std::cout << "current_face == GraphTraits::null_face()" <<
647  // std::endl;
648 
649  // try to add face by duplicating vertices
650 
651  // duplicate faulty vertices
652  bool face_vertex_duplicated = false;
653  size_t n = face_vertices.size();
654  for(size_t i = 0, ii = 1; i < n; ++i, ++ii, ii %= n)
655  // the loop above and the 'faulty vertex' conditions below
656  // are inspired by Euler_operations.h line 593 to 606
657  {
658  std::pair< halfedge_descriptor, bool > he =
659  halfedge(face_vertices[i], face_vertices[ii], g);
660 
661  if((! CGAL::internal::is_isolated(face_vertices[i], g) &&
662  ! CGAL::is_border(face_vertices[i], g)) ||
663  (he.second && ! CGAL::is_border(he.first, g)))
664  {
665  // the vertex is not isolated and not on a border,
666  // or the halfedge from this vertex to the next one
667  // is not on a border ; means that the mesh is non manifold ;
668  // the vertex must be duplicated to work with
669  // non-manifold datastructures
670 
671  // DBG std::cout << "DUPLICATE ONE VERTEX" << std::endl;
672 
673  duplicate_v(i);
674  face_vertex_duplicated = true;
675  }
676  }
677 
678  // duplicate all face vertices if necessary
679 
680  if(! face_vertex_duplicated)
681  {
682  // no faulty vertex found, let's duplicate all face vertices
683 
684  // DBG std::cout << "DUPLICATE ALL FACE-VERTICES" << std::endl;
685 
686  for(size_t i = 0; i < n; ++i)
687  {
688  duplicate_v(i);
689  }
690  }
691 
692  // add face with duplicated vertices
693  current_face = CGAL::Euler::add_face(face_vertices, g);
694 
695  if(current_face == GraphTraits::null_face())
696  {
697  // despite all efforts the face could not be created
698  std::cout << "Warning: failed to create one face." << std::endl;
699  // go to next face
700  continue;
701  }
702  }
703  // the face was successfully created
704 
705  //--- fill property maps
706 
707  vertex_descriptor prev_vertex = face_vertices.back();
708  vertex_descriptor current_vertex;
709 
710  // loop over face's vertices
711  for(index_type face_vertex_id = 0;
712  face_vertex_id < face_vertices.size();
713  ++face_vertex_id)
714  {
715  current_vertex = face_vertices[face_vertex_id];
716 
717  // corner (aka halfedge) texture
718  if(use_corner_texture_coord)
719  {
720  // DBG std::cout << "store tex coord for face #" << faceId << " and
721  // vertex #" << faceVertexId << std::endl;
722 
723  // retrieve texture coords
724  Vector texcoords;
725  if(! mvr.texture_face_indices[face_id].empty())
726  {
727  index_type texture_id =
728  mvr.texture_face_indices[face_id][face_vertex_id];
729  std::vector< coordT_type > &coords = mvr.texture_coords[texture_id];
730  if(coords.size() != 2)
731  throw std::runtime_error(std::string(__func__) +
732  "(): texture coordinates of "
733  "size != 2 not yet supported!");
734  texcoords = Vector(coords[0], coords[1], 0);
735  }
736  else
737  texcoords = Vector(0, 0, 0);
738 
739  // retrieve halfedge
740  // note: the most obvious solution
741  // h = halfedge(prevVertex, currentVertex, g).first
742  // doesn't work with AIF in case of a non-manifold halfedge
743  // because the (prevVertex, currentVertex) couple is not
744  // sufficient to identify the right halfedge (the face is missing)
745  halfedge_descriptor h = halfedge(current_face, g);
746  while(
747  !(source(h, g) == prev_vertex && target(h, g) == current_vertex))
748  h = next(h, g);
749 
750  // fill in property map
751  auto htexcoord_pm =
753  put(htexcoord_pm, h, texcoords);
754 
755  // DBG std::cout << __FILE__ << ":" << __LINE__ << " he=" << he << "
756  // (*pm)[he][0]=" << (*pm)[he][0] << " (*pm)[he][1]=" << (*pm)[he][1]
757  // << " coords[0]=" << coords[0] << " coords[1]=" << coords[1] << "
758  // texCoords[0]=" << texCoords[0] << " texCoords[1]=" << texCoords[1]
759  // << std::endl;
760  }
761 
762  // face normal
763  // compute face normal incrementally using per-vertex normals
764  // (face normal = mean of face's vertices normals)
765  if(use_face_normal)
766  {
767  // DBG std::cout << "compute normal for face #" << faceId << " (vertex
768  // #" << faceVertexId << ")" << std::endl;
769 
770  // retrieve current vertex normal
771  index_type normal_id =
772  mvr.normal_face_indices[face_id][face_vertex_id];
773  std::vector< coordN_type > &normal = mvr.normals_coords[normal_id];
774  if(normal.size() != 3)
775  throw std::runtime_error(std::string(__func__) +
776  "(): normals of size != 3 not yet "
777  "supported!");
778  Vector vnormal = Vector(normal[0], normal[1], normal[2]);
779 
780  // retrieve face normal (previous increment)
781  auto fn_pm = get_property_map(FEVV::face_normal, g, pmaps);
782  Vector fnormal = get(fn_pm, current_face);
783 
784  // compute face normal (mean of the vertices normals)
785  fnormal = fnormal + vnormal;
786  if(face_vertex_id == face_vertices.size() - 1)
787  fnormal =
788  fnormal / (static_cast< unsigned long >(face_vertex_id) + 1);
789 
790  // update face-normal map
791  put(fn_pm, current_face, fnormal);
792  }
793 
794  prev_vertex = current_vertex;
795  }
796 
797  // set face color
798  if(use_face_color)
799  {
800  std::vector< coordC_type > &color = mvr.face_color_coords[face_id];
801  // at this point we are sure that color.size() == 3 because of
802  // previous sanity checks
803 
804  // fix colors in [0.0, 1.0] if provided in [0, 255]
805  if(is_face_color_0_255)
806  {
807  // conversion copied from Mepp1
808  // (src/mepp/Polyhedron/Polyhedron_OFF_CGALImporter.h)
809  int rgb[3];
810  rgb[0] = (int)floor(color[0] + 0.5);
811  rgb[1] = (int)floor(color[1] + 0.5);
812  rgb[2] = (int)floor(color[2] + 0.5);
813  color[0] = (coordC_type)((float)rgb[0] / 255.0);
814  color[1] = (coordC_type)((float)rgb[1] / 255.0);
815  color[2] = (coordC_type)((float)rgb[2] / 255.0);
816  }
817 
818  // store color in property map
819  Vector fc(color[0], color[1], color[2]);
820  auto fc_pm = get_property_map(FEVV::face_color, g, pmaps);
821  put(fc_pm, current_face, fc);
822  }
823 
824  // set face material
825  if(use_face_material)
826  {
827  size_t mtl_id = mvr.face_material[face_id];
828 
829  // store material id in property map
830  auto fm_pm = get_property_map(FEVV::face_material, g, pmaps);
831  put(fm_pm, current_face, mtl_id);
832  }
833 
834  // save current face descriptor for later use
835  if(params.m_fd_target)
836  {
837  params.m_fd_target->push_back(current_face);
838  }
839  }
840  }
841 }
842 
843 
855 template< typename HalfedgeGraph,
856  typename coordP_type,
857  typename coordN_type,
858  typename coordT_type,
859  typename coordC_type,
860  typename index_type,
861  typename GeometryTraits = FEVV::Geometry_traits< HalfedgeGraph > >
862 void
864  const HalfedgeGraph &g,
865  const FEVV::PMapsContainer &pmaps,
866  unsigned int &dup_v_nbr,
867  FEVV::Types::MVR < coordP_type,
868  coordN_type,
869  coordT_type,
870  coordC_type,
871  index_type > &mvr,
874 {
875  GeometryTraits gt(g);
876  mesh_from_vector_representation(g, pmaps, dup_v_nbr, mvr, params, gt);
877 }
878 
879 
880 } // namespace Filters
881 } // namespace FEVV
CGAL::Euler::add_face
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::face_descriptor add_face(const VertexRange &vr, FEVV::DataStructures::AIF::AIFMesh &g)
Definition: Graph_traits_aif.h:1104
FEVV::DataStructures::AIF::vertices
std::pair< typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_iterator, typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_iterator > vertices(const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns the iterator range of the vertices of the mesh.
Definition: Graph_traits_aif.h:172
FEVV::put_property_map
void put_property_map(PropertyT p, const MeshT &, PMapsContainer &pmaps, const typename PMap_traits< PropertyT, MeshT >::pmap_type &pmap)
Definition: properties.h:664
FEVV::DataStructures::AIF::next
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor next(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor h, const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns the next halfedge around its face.
Definition: Graph_traits_aif.h:599
FEVV::Types::MVR
Definition: Mesh_vector_representation.h:32
FEVV::Filters::MeshFromVectorReprParameters::use_corner_texcoord
MeshFromVectorReprParameters & use_corner_texcoord(bool _use_corner_texcoord)
Definition: mesh_from_vector_representation.hpp:96
Vector
AIFMesh::Vector Vector
Definition: Graph_properties_aif.h:22
FEVV::get_property_map
PMap_traits< PropertyT, MeshT >::pmap_type get_property_map(PropertyT p, const MeshT &, const PMapsContainer &pmaps)
Definition: properties.h:646
FEVV::vertex_texcoord
@ vertex_texcoord
Definition: properties.h:43
FEVV::Filters::MeshFromVectorReprParameters::FDVect
FaceDescVect< FaceGraph > FDVect
Definition: mesh_from_vector_representation.hpp:94
FEVV::mesh_materials
@ mesh_materials
Definition: properties.h:89
FEVV::Filters::make_no_texture_image
FEVV::Types::Image * make_no_texture_image(void)
Definition: mesh_from_vector_representation.hpp:33
FEVV::Filters::mesh_from_vector_representation
void mesh_from_vector_representation(HalfedgeGraph &g, FEVV::PMapsContainer &pmaps, unsigned int &dup_v_nbr, FEVV::Types::MVR< coordP_type, coordN_type, coordT_type, coordC_type, index_type > &mvr, MeshFromVectorReprParameters< HalfedgeGraph > const &params, const GeometryTraits &)
Build the mesh from the given vector representation.
Definition: mesh_from_vector_representation.hpp:142
FEVV::Geometry_traits< HalfedgeGraph >
Point
AIFMesh::Point Point
Definition: Graph_properties_aif.h:21
FEVV::DataStructures::AIF::source
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_descriptor source(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::edge_descriptor e, const FEVV::DataStructures::AIF::AIFMesh &)
Returns the source vertex of e.
Definition: Graph_traits_aif.h:387
FEVV::Filters::MeshFromVectorReprParameters::m_use_corner_texcoord
bool m_use_corner_texcoord
Definition: mesh_from_vector_representation.hpp:115
FEVV::PMapsContainer
std::map< std::string, boost::any > PMapsContainer
Definition: properties.h:99
FEVV::Filters::MeshFromVectorReprParameters
Definition: mesh_from_vector_representation.hpp:92
FEVV::Types::Image
cimg_library::CImg< unsigned char > Image
Definition: Material.h:41
FEVV::get
FEVV::PCLPointCloudPointMap::value_type get(const FEVV::PCLPointCloudPointMap &pm, FEVV::PCLPointCloudPointMap::key_type key)
Specialization of get(point_map, key) for PCLPointCloud.
Definition: Graph_properties_pcl_point_cloud.h:117
FEVV::Filters::MeshFromVectorReprParameters::vd_target
MeshFromVectorReprParameters & vd_target(VDVect *_vd_target)
Definition: mesh_from_vector_representation.hpp:103
FEVV
Interfaces for plugins These interfaces will be used for different plugins.
Definition: Assert.h:16
FEVV::Filters::FaceDescVect
std::vector< typename boost::graph_traits< FaceGraph >::face_descriptor > FaceDescVect
Definition: mesh_from_vector_representation.hpp:80
FEVV::DataStructures::AIF::halfedge
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor halfedge(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_descriptor v, const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns a halfedge with target v.
Definition: Graph_traits_aif.h:296
FEVV::DataStructures::AIF::target
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_descriptor target(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::edge_descriptor e, const FEVV::DataStructures::AIF::AIFMesh &)
Returns the target vertex of e.
Definition: Graph_traits_aif.h:400
FEVV::vertex_color
@ vertex_color
Definition: properties.h:47
FEVV::face_material
@ face_material
Definition: properties.h:85
Geometry_traits.h
FEVV::Filters::MeshFromVectorReprParameters::VDVect
VertDescVect< FaceGraph > VDVect
Definition: mesh_from_vector_representation.hpp:93
FEVV::Filters::MeshFromVectorReprParameters::m_vd_target
VDVect * m_vd_target
Definition: mesh_from_vector_representation.hpp:116
FEVV::DataStructures::AIF::AIFVector
Definition: AIFProperties.h:173
FEVV::DataStructures::AIF::add_vertex
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_descriptor add_vertex(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_property_type vp, FEVV::DataStructures::AIF::AIFMesh &sm)
Definition: Graph_properties_aif.h:263
msdm2::vertex_descriptor
boost::graph_traits< MeshT >::vertex_descriptor vertex_descriptor
Definition: msdm2_surfacemesh.h:33
FEVV::put
void put(FEVV::PCLPointCloudPointMap &pm, FEVV::PCLPointCloudPointMap::key_type key, const FEVV::PCLPointCloudPointMap::value_type &value)
Specialization of put(point_map, key, value) for PCLPointCloud.
Definition: Graph_properties_pcl_point_cloud.h:126
FEVV::face_color
@ face_color
Definition: properties.h:81
FEVV::Filters::MeshFromVectorReprParameters::m_fd_target
FDVect * m_fd_target
Definition: mesh_from_vector_representation.hpp:117
properties.h
FEVV::halfedge_texcoord
@ halfedge_texcoord
Definition: properties.h:69
FEVV::vertex_normal
@ vertex_normal
Definition: properties.h:35
FEVV::Filters::VertDescVect
std::vector< typename boost::graph_traits< BoostGraph >::vertex_descriptor > VertDescVect
Definition: mesh_from_vector_representation.hpp:72
Mesh_vector_representation.h
FEVV::make_property_map
PMap_traits< PropertyT, MeshT >::pmap_type make_property_map(PropertyT, const MeshT &m)
Definition: properties.h:630
FEVV::face_normal
@ face_normal
Definition: properties.h:77
FEVV::Filters::MeshFromVectorReprParameters::fd_target
MeshFromVectorReprParameters & fd_target(FDVect *_fd_target)
Definition: mesh_from_vector_representation.hpp:109