MEPP2 Project
Compression_Valence_Component.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.
11 
17 
18 #include <CGAL/boost/graph/Euler_operations.h>
19 #include <CGAL/boost/graph/helpers.h> // for CGAL::clear(mesh)
20 #include <CGAL/boost/graph/copy_face_graph.h> // for CGAL::copy_face_graph()
21 #include <CGAL/circulator.h> // for CGAL_For_all()
22 #include <Eigen/Dense>
23 #include <map>
24 #include <set>
25 #include <bitset>
26 #include <sstream>
27 #include <chrono>
28 #include <string>
29 #include <algorithm> // for std::min() and std::max()
30 
31 #include "FEVV/Filters/Generic/generic_writer.hpp" // for FEVV::Filters::write_mesh()
32 
33 
34 #if defined _MSC_VER
35 // disable some warnings on Windows
36 #pragma warning(push)
37 #pragma warning(disable : 4244) // for VS-2015
38 #pragma warning(disable : 4267)
39 // 4244 & 4267: converting type A to type B, possible data loss
40 #endif
41 
42 
43 #define COLOR_NUMBER 10000
44 #define USE_COLOR_METRIC
45 #define AC_BUFFER 1024 * 10000
46 
48 const int LIMIT_NUMBER = 50;
49 
50 
51 //#define DBG_Main_Function
52 
53 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
54 std::string
56  Main_Function(HalfedgeGraph &_pMesh,
57  PointMap *_pm,
58  VertexColorMap *_v_cm,
59  const std::string &_Input_File_Name,
60  const std::string &_File_Name, // output
61  const int &_Qbit,
62  const int &_NVertices,
63  const bool _Normal_flipping,
64  const bool _Use_metric,
65  const float &_Metric_thread,
66  const bool _Use_forget_metric,
67  const int &_Forget_value,
68  const bool _Compression_selected,
69  const bool _Adaptive_quantization,
70  const bool _Is_bijection_selected)
71 {
72 #ifdef DBG_Main_Function
73  // std::cout << std::hexfloat;
74  DBG_print_mesh_geometry(_pMesh, _pm, "beginning of Main_Function()");
75  DBG_print_mesh_vertexcolor(_pMesh, _v_cm, "beginning of Main_Function()");
76 #endif
77 
78  // ensure the mesh has triangular faces only
79  if(!CGAL::is_triangle_mesh(_pMesh))
80  return "Some faces of the mesh are not triangles. No compression was done.";
81 
82  // initialize property maps
83  vertex_color_int =
84  FEVV::make_vertex_property_map< HalfedgeGraph, Color_Unit >(_pMesh);
85  vertex_Seed_Edge =
86  FEVV::make_vertex_property_map< HalfedgeGraph, int >(_pMesh);
87  vertex_Component_Number =
88  FEVV::make_vertex_property_map< HalfedgeGraph, int >(_pMesh);
89  Vertex_Flag = FEVV::make_vertex_property_map< HalfedgeGraph, int >(_pMesh);
90  Vertex_Number = FEVV::make_vertex_property_map< HalfedgeGraph, int >(_pMesh);
91  Vertex_Sign = FEVV::make_vertex_property_map< HalfedgeGraph, int >(_pMesh);
93  FEVV::make_vertex_property_map< HalfedgeGraph, Vector >(_pMesh);
94  vertex_Q_Index = FEVV::make_vertex_property_map< HalfedgeGraph, int >(_pMesh);
95  vertex_Region_Number =
96  FEVV::make_vertex_property_map< HalfedgeGraph, int >(_pMesh);
97  vertex_Removal_Order =
98  FEVV::make_vertex_property_map< HalfedgeGraph, int >(_pMesh);
99 
100  facet_tag = FEVV::make_face_property_map< HalfedgeGraph, int >(_pMesh);
101  facet_Component_Number =
102  FEVV::make_face_property_map< HalfedgeGraph, int >(_pMesh);
103  Facet_Flag = FEVV::make_face_property_map< HalfedgeGraph, int >(_pMesh);
104  facet_normal = FEVV::make_face_property_map< HalfedgeGraph, Vector >(_pMesh);
105 
106 
107  // ELO in Mepp1, compute_normals() is called when the mesh is loaded ;
108  // ELO added here to ensure normals are computed before the processing
109  // ELO begins ; maybe this line should go in Global_Initialization() ?
110  compute_normals(_pMesh, _pm); // ELO+
111 
112  // start time measurement
113  auto time_start = std::chrono::steady_clock::now();
114 
115  // read size of input mesh (file size)
116  if(FILE *file = fopen(_Input_File_Name.c_str(), "r"))
117  {
118  fseek(file, 0, SEEK_END);
119  this->Initial_file_size = ftell(file);
120  fclose(file);
121  }
122  else
123  this->Initial_file_size = 0;
124 
125  // Use of bijection or not for the geometry encoding
126  this->Is_Bijection_Enabled = _Is_bijection_selected;
127 
128  unsigned Init_number_vertices = (unsigned)FEVV::size_of_vertices(_pMesh);
129 
130  // Initialization - Quantization, Color, Multiple components
131  this->Global_Initialization(_pMesh, _Qbit, _File_Name.c_str(), _pm, _v_cm);
132 
133 #ifdef DBG_Main_Function
134  DBG_print_mesh_vertexcolor(
135  _pMesh, _v_cm, "in Main_Function() after Global_Initialization()");
136 #endif
137 
138  // When use of adaptive quantization is selected
139  if(_Adaptive_quantization)
140  {
141  this->Adaptive_Quantization(_pMesh,
142  _pm,
143  _v_cm,
144  _NVertices,
145  _Normal_flipping,
146  _Use_metric,
147  _Metric_thread,
148  _Use_forget_metric,
149  _Forget_value,
150  _Qbit);
151  }
152  else
153  {
154  this->Simplification(_pMesh,
155  _pm,
156  _NVertices,
157  _Normal_flipping,
158  _Use_metric,
159  _Metric_thread,
160  _Use_forget_metric,
161  _Forget_value);
162  }
163 
164  unsigned Connectivity_size = 0, Color_size = 0, Total_size = 0;
165 
166  // Compression
167  if(_Compression_selected)
168  {
169  this->Compression(_pMesh,
170  _File_Name.c_str(),
171  _Qbit,
172  Connectivity_size,
173  Color_size,
174  Total_size,
175  _pm); //, this->Initial_file_size);
176  }
177 
178  unsigned Number_layers = this->GlobalCountOperation;
179  unsigned Final_number_vertices = (unsigned)FEVV::size_of_vertices(_pMesh);
180 
181  // stop time measurement
182  auto time_end = std::chrono::steady_clock::now();
183  std::chrono::duration< double > time_diff = time_end - time_start;
184 
185  // To show result
186  double Connectivity_rate = (double)Connectivity_size / Init_number_vertices;
187  double Color_rate = (double)Color_size / Init_number_vertices;
188  double Total_rate = (double)Total_size * 8 / Init_number_vertices;
189  double Geometry_rate = Total_rate - Connectivity_rate - Color_rate;
190 
191  std::ostringstream Res_tmp;
192  Res_tmp << "Base mesh : " << std::setw(3) << Final_number_vertices
193  << " vertices \n";
194  Res_tmp << "Connectivity : " << float(Connectivity_rate) << " b/v \n";
195  Res_tmp << "Geometry : " << float(Geometry_rate) << " b/v\n";
196  Res_tmp << "Color : " << float(Color_rate) << " b/v\n";
197  Res_tmp << "Total size : " << float(Total_rate) << " b/v\n";
198  if(this->Initial_file_size != 0)
199  Res_tmp << "Ratio : " << (float)Total_size / this->Initial_file_size * 100
200  << " % \n\n";
201  else
202  Res_tmp << "Ratio : "
203  << "unavailable\n";
204  Res_tmp << "Number of layers : " << Number_layers << "\n";
205  Res_tmp << "Calculation time : " << (float)time_diff.count() << " seconds \n";
206  std::string Res = Res_tmp.str();
207 
208  // ELO+beg
209  std::cout << Res << std::endl;
210 #ifdef DBG_Main_Function
211  DBG_print_mesh_geometry(_pMesh, _pm, "end of Main_Function()");
212  DBG_print_mesh_vertexcolor(_pMesh, _v_cm, "end of Main_Function()");
213 #endif
214  // ELO+end
215 
216  return Res;
217 }
218 
219 
220 // Description : To select the input gate.
221 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
222 void
224  Global_Initialization(HalfedgeGraph &_pMesh,
225  const int &_Qbit,
226  const char * /*_File_Name*/,
227  const PointMap *pm,
228  VertexColorMap *v_cm)
229 {
230  // (1) Determination if the mesh is colored.
231  // (2) Conversion of color space.
232  // (3) Quantization of converted colors into "vertex->color_int()"
233  // (4) Re-paint mesh with re_calculated rgb colors from quantized converted
234  // color. (5) Establish color palette. (6) Color quantization - Descrease of
235  // possible color numbers
236  this->Color_Initialization(_pMesh, v_cm);
237 
238  // Initialization of multiple components (quantization is performed separately
239  // for each component)
240  this->Multiple_Components_Initialization(_pMesh, pm, _Qbit);
241 
242  // Quantization of each component
243  this->Quantization(_pMesh, pm);
244 }
245 
246 
247 //#define DBG_Multiple_Components_Initialization
248 
249 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
250 void
252  Multiple_Components_Initialization(HalfedgeGraph &_pMesh,
253  const PointMap *pm,
254  int const &_Qbit)
255 {
256  typedef boost::graph_traits< HalfedgeGraph > GraphTraits;
257  typedef typename GraphTraits::vertex_iterator vertex_iterator;
258  typedef typename GraphTraits::face_iterator face_iterator;
262 
263  // Initialize vertex flags
264  auto vertex_iterator_pair = vertices(_pMesh);
265  vertex_iterator pVertex = vertex_iterator_pair.first;
266  vertex_iterator pVertex_end = vertex_iterator_pair.second;
267  for(; pVertex != pVertex_end; ++pVertex)
268  {
269  put(this->vertex_Seed_Edge, *pVertex, OTHER_COORDINATE);
270  put(this->vertex_Component_Number, *pVertex, -1);
271  }
272 
273  // Several components
274  // (1) To get the number of components;
275  // (2) To get the volume, area and the number of vertices of each component;
276  // (3) To know if each component is closed or not.
277  // (4) Tag vertices and facets to correspoding component number
278 
279  // Initialize face tag
280  auto face_iterator_pair = faces(_pMesh);
281  face_iterator pFacet_beg = face_iterator_pair.first;
282  face_iterator pFacet_end = face_iterator_pair.second;
283  for(face_iterator pFacet = pFacet_beg; pFacet != pFacet_end; ++pFacet)
284  {
285  put(this->facet_tag, *pFacet, -1);
286  }
287 
288  int Component_index = 0;
289 
290  for(face_iterator pFacet = pFacet_beg; pFacet != pFacet_end; ++pFacet)
291  {
292 
293  if(get(this->facet_tag, *pFacet) == -1)
294  {
295  bool Is_closed = true;
296  bool Is_seed_edge_found = false;
297 
298  float xmin = 50000., ymin = 50000., zmin = 50000.;
299  float xmax = -50000., ymax = -50000., zmax = -50000.;
300  double area = 0;
301  int Number_vertices = 0;
302 
303  put(this->facet_tag, *pFacet, Component_index);
304 
305  std::list< face_descriptor > facets;
306  facets.push_front(*pFacet);
307 
308  while(!facets.empty())
309  {
310  face_descriptor F = facets.front();
311  facets.pop_front();
312 
313  put(this->facet_tag, F, Component_index);
314 
315  // tag component number to facet
316  put(this->facet_Component_Number, F, Component_index);
317 
318  area += Area_Facet_Triangle(halfedge(F, _pMesh), _pMesh, pm);
319 
320 
321  CGAL::Halfedge_around_face_circulator< HalfedgeGraph > pHalfedge(
322  halfedge(F, _pMesh), _pMesh);
323  CGAL::Halfedge_around_face_circulator< HalfedgeGraph > end(pHalfedge);
324  do
325  {
326  // tag the vertex to its corresponding component number
327  if(get(this->vertex_Component_Number, target(*pHalfedge, _pMesh)) ==
328  -1)
329  {
330  put(this->vertex_Component_Number,
331  target(*pHalfedge, _pMesh),
332  Component_index);
333  Number_vertices++;
334  }
335 
336  // To calculate the bounding box of each component
337  Point3d p = get(*pm, target(*pHalfedge, _pMesh));
338  if(p[0] > xmax)
339  xmax = p[0];
340 
341  if(p[1] > ymax)
342  ymax = p[1];
343 
344  if(p[2] > zmax)
345  zmax = p[2];
346 
347  if(p[0] < xmin)
348  xmin = p[0];
349 
350  if(p[1] < ymin)
351  ymin = p[1];
352 
353  if(p[2] < zmin)
354  zmin = p[2];
355 
356  // To know if the component is closed or not
357  if(CGAL::is_border_edge(*pHalfedge, _pMesh))
358  Is_closed = false;
359 
360  if(!Is_seed_edge_found)
361  {
362  if(((!CGAL::is_border_edge(*pHalfedge, _pMesh)) &&
363  (!Is_Border_Vertex(*pHalfedge, _pMesh)) &&
364  (!Is_Border_Vertex(opposite(*pHalfedge, _pMesh), _pMesh))) ||
365  (out_degree(target(next(*pHalfedge, _pMesh), _pMesh), _pMesh) !=
366  6))
367  {
368  Is_seed_edge_found = true;
369 
370  // Seed edge of each component
371  put(this->vertex_Seed_Edge,
372  target(*pHalfedge, _pMesh),
373  2 * Component_index);
374  put(this->vertex_Seed_Edge,
375  target(opposite(*pHalfedge, _pMesh), _pMesh),
376  2 * Component_index + 1);
377  }
378  }
379 
380  face_descriptor pNFacet = face(opposite(*pHalfedge, _pMesh), _pMesh);
381  if(pNFacet != boost::graph_traits< HalfedgeGraph >::null_face() &&
382  get(this->facet_tag, pNFacet) == -1)
383  {
384  facets.push_front(pNFacet);
385  put(this->facet_tag, pNFacet, Component_index);
386  put(this->facet_Component_Number, pNFacet, Component_index);
387  }
388  } while(++pHalfedge != end);
389  }
390 
391  this->xmin.push_back(xmin);
392  this->ymin.push_back(ymin);
393  this->zmin.push_back(zmin);
394 
395  this->xmax.push_back(xmax);
396  this->ymax.push_back(ymax);
397  this->zmax.push_back(zmax);
398 
399  double HighestBB = -5000;
400  if(xmax - xmin > HighestBB)
401  HighestBB = xmax - xmin;
402  if(ymax - ymin > HighestBB)
403  HighestBB = ymax - ymin;
404  if(zmax - zmin > HighestBB)
405  HighestBB = zmax - zmin;
406 
407  this->HighestLengthBB.push_back(HighestBB);
408 
409  // volume, area, number of vertices of each component
410  Vector e1(xmax - xmin, 0., 0.);
411  Vector e2(0., ymax - ymin, 0.);
412 
415  double base_area = FEVV::Math::Vector::l2_distance<
417  double volume = base_area * (zmax - zmin);
418 
419  // For quasi-optimal determination of quantization precision.
420  // Originally, the highest dimension of bounding box was considered as 10.
421  // We shoud take this point into account.
422  volume *= std::pow(((double)10.0 / (double)HighestBB), 3.0);
423  area *= std::pow(((double)10.0 / (double)HighestBB), 2.0);
424 
425  // Stock information for each component
426  this->ComponentVolume.push_back(volume);
427  this->ComponentArea.push_back(area);
428  this->ComponentNumberVertices.push_back(Number_vertices);
429 
430  // To know if each component is open or closed.
431  this->IsClosed.push_back(Is_closed);
432 
433  Component_index++;
434  }
435  }
436 
437  this->NumberComponents = Component_index;
438 
439  std::list< int > li;
440  std::list< Point_Int > pi;
441  std::list< Color_Unit > cu;
442 
443  // Initilization of containers for each component
444  for(int i = 0; i < this->NumberComponents; i++)
445  {
446  // operation (decimation or quantization)
447  this->ListOperation.push_back(li);
448 
449  // connectivity
450  this->Connectivity.push_back(li);
451 
452  // geometry
453  this->Geometry.push_back(pi);
454 
455  // vertex color
456  this->VertexColor.push_back(cu);
457 
458  // Number of connectivity and geometry symbols
459  this->NumberSymbol.push_back(li);
460  this->NumberVertices.push_back(li);
461 
462  // Range of alpha and gamma
463  this->AlphaRange.push_back(li);
464  this->AlphaOffset.push_back(li);
465  this->GammaRange.push_back(li);
466  this->GammaOffset.push_back(li);
467 
468  // Number of operations for each component
469  this->ComponentOperations.push_back(0);
470 
471  // Number of decimations for each component
472  this->NumberDecimation.push_back(0);
473 
474  // Number of under quantization
475  this->NumberChangeQuantization.push_back(0);
476  this->NumberColorQuantization.push_back(0);
477 
478  // Qbit for each component
479  this->Qbit.push_back(_Qbit);
480 
481  // Displacement vector for under quantization for each component
482  this->QuantizationCorrectVector.push_back(li);
483 
484  // The number of vertices for each under_quantization
485  this->NumberQuantizationLayer.push_back(li);
486 
487  // For color quantization change
488  this->NumberProcessedVertices.push_back(li);
489  this->ColorChildcellIndex.push_back(li);
490  this->ColorEncoderIndex.push_back(li);
491  }
492 
493 #ifdef DBG_Multiple_Components_Initialization
494  {
495  std::cout << "DBG "
496  << "--- function " << __func__ << std::endl;
497  std::cout << "DBG "
498  << "this->NumberComponents=" << this->NumberComponents
499  << std::endl;
500 
501  {
502  std::cout << "DBG "
503  << "vertex->Seed_Edge=" << std::endl;
504 
505  auto vertex_iterator_pair = vertices(_pMesh);
506  vertex_iterator pVertex = vertex_iterator_pair.first;
507  vertex_iterator pVertex_end = vertex_iterator_pair.second;
508  for(; pVertex != pVertex_end; ++pVertex)
509  {
510  auto s = get(this->vertex_Seed_Edge, *pVertex);
511  std::cout << "DBG " << s << std::endl;
512  }
513  }
514 
515  {
516  std::cout << "DBG "
517  << "vertex->Component_Number=" << std::endl;
518 
519  auto vertex_iterator_pair = vertices(_pMesh);
520  vertex_iterator pVertex = vertex_iterator_pair.first;
521  vertex_iterator pVertex_end = vertex_iterator_pair.second;
522  for(; pVertex != pVertex_end; ++pVertex)
523  {
524  auto n = get(this->vertex_Component_Number, *pVertex);
525  std::cout << "DBG " << n << std::endl;
526  }
527  }
528 
529  {
530  std::cout << "DBG "
531  << "face->tag=" << std::endl;
532 
533  auto face_iterator_pair = faces(_pMesh);
534  face_iterator pFacet = face_iterator_pair.first;
535  face_iterator pFacet_end = face_iterator_pair.second;
536  for(; pFacet != pFacet_end; ++pFacet)
537  {
538  auto t = get(this->facet_tag, *pFacet);
539  std::cout << "DBG " << t << std::endl;
540  }
541  }
542 
543  {
544  std::cout << "DBG "
545  << "face->Component_Number=" << std::endl;
546 
547  auto face_iterator_pair = faces(_pMesh);
548  face_iterator pFacet = face_iterator_pair.first;
549  face_iterator pFacet_end = face_iterator_pair.second;
550  for(; pFacet != pFacet_end; ++pFacet)
551  {
552  auto n = get(this->facet_Component_Number, *pFacet);
553  std::cout << "DBG " << n << std::endl;
554  }
555  }
556  }
557 #endif
558 }
559 
560 //#define DBG_Quantization
561 
562 /*
563  Description : Quantize all vertices so that the new positions
564  are reguliraly spaced in the 3D space. */
565 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
566 void
568  Quantization(HalfedgeGraph &_pMesh, const PointMap *pm)
569 {
570  typedef boost::graph_traits< HalfedgeGraph > GraphTraits;
571  typedef typename GraphTraits::vertex_iterator vertex_iterator;
573 
574  // Quantization step for each component
575  for(int i = 0; i < this->NumberComponents; i++)
576  {
577  float max = this->xmax[i] - this->xmin[i];
578 
579  if(this->ymax[i] - this->ymin[i] > max)
580  max = this->ymax[i] - this->ymin[i];
581 
582  if(this->zmax[i] - this->zmin[i] > max)
583  max = this->zmax[i] - this->zmin[i];
584 
585  int NbInteraval = std::pow(2., (int)this->Qbit[i]);
586 
587  float Q_Step = max / (float)NbInteraval;
588  this->Quantization_Step.push_back(Q_Step);
589  }
590 
591  // Vertex quantization
592  auto vertex_iterator_pair = vertices(_pMesh);
593  vertex_iterator pVert_beg = vertex_iterator_pair.first;
594  vertex_iterator pVert_end = vertex_iterator_pair.second;
595  for(vertex_iterator pVert = pVert_beg; pVert != pVert_end; ++pVert)
596  {
597  Point3d point = get(*pm, *pVert);
598 #if 0
599  //TODO-elo-restore ?
600  double x = point[0];
601  double y = point[1];
602  double z = point[2];
603 #else
604  // ELO+
605  // ELO simulate reading points coordinates in floats
606  // ELO then converting to double as it is done by Mepp1
607  float xtmp = point[0];
608  float ytmp = point[1];
609  float ztmp = point[2];
610  double x = xtmp;
611  double y = ytmp;
612  double z = ztmp;
613 #endif
614 
615  int Component_ID = get(this->vertex_Component_Number, *pVert);
616 
617  int Qx = (int)(ceil((x - (double)this->xmin[Component_ID]) /
618  (double)this->Quantization_Step[Component_ID])) -
619  1;
620  if(Qx == -1)
621  Qx = 0;
622  int Qy = (int)(ceil((y - (double)this->ymin[Component_ID]) /
623  (double)this->Quantization_Step[Component_ID])) -
624  1;
625  if(Qy == -1)
626  Qy = 0;
627  int Qz = (int)(ceil((z - (double)this->zmin[Component_ID]) /
628  (double)this->Quantization_Step[Component_ID])) -
629  1;
630  if(Qz == -1)
631  Qz = 0;
632 
633  put(*pm,
634  *pVert,
635  Point3d(this->xmin[Component_ID] +
636  (Qx + 0.5) * this->Quantization_Step[Component_ID],
637  this->ymin[Component_ID] +
638  (Qy + 0.5) * this->Quantization_Step[Component_ID],
639  this->zmin[Component_ID] +
640  (Qz + 0.5) * this->Quantization_Step[Component_ID]));
641  }
642 
643 #ifdef DBG_Quantization
644  {
645  std::cout << "DBG "
646  << "--- function " << __func__ << std::endl;
647 
648  {
649  std::cout << "DBG " << __func__ << " "
650  << "vertex->point()=" << std::endl;
651 
652  auto vertex_iterator_pair = vertices(_pMesh);
653  vertex_iterator pVertex = vertex_iterator_pair.first;
654  vertex_iterator pVertex_end = vertex_iterator_pair.second;
655  for(; pVertex != pVertex_end; ++pVertex)
656  {
657  auto p3d = get(*pm, *pVertex);
658  std::cout << "DBG " << __func__ << " " << p3d[0] << " " << p3d[1] << " "
659  << p3d[2] << std::endl;
660  }
661  }
662  }
663 #endif
664 }
665 
666 //#define DBG_Color_Initialization
667 
668 // this->ColorArray -> contains all initial colors present in the input mesh.
669 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
670 void
672  Color_Initialization(HalfedgeGraph &_pMesh, VertexColorMap *v_cm)
673 {
674  typedef boost::graph_traits< HalfedgeGraph > GraphTraits;
675  typedef typename GraphTraits::vertex_iterator vertex_iterator;
676  typedef typename boost::property_traits< VertexColorMap >::value_type Color;
677 
678  // (1) To determine if the mesh is colored.
679  // We consider the mesh is colored if a colormap is provided.
680  if(v_cm != nullptr)
681  {
682  this->IsColored = true;
683 
684  auto vertex_iterator_pair = vertices(_pMesh);
685  vertex_iterator vi = vertex_iterator_pair.first;
686  vertex_iterator vi_end = vertex_iterator_pair.second;
687 
688  // keep the first color in case there is a unique color
689  Color c = get(*v_cm, *vi);
690  this->OnlyColor[0] = c[0];
691  this->OnlyColor[1] = c[1];
692  this->OnlyColor[2] = c[2];
693 
694  // check if color is unique for the whole mesh
695  this->IsOneColor = true;
696  for(; vi != vi_end; ++vi) // loop over vertices
697  {
698  Color c = get(*v_cm, *vi);
699  if(c[0] != this->OnlyColor[0] || c[1] != this->OnlyColor[1] ||
700  c[2] != this->OnlyColor[2])
701  {
702  this->IsOneColor = false;
703  break;
704  }
705  }
706  }
707 
708  // (2) If the mesh is colored -> Color initialization.
709  // Conversion to Lab colors and determine max and min for each components.
710  if((this->IsColored) && (!this->IsOneColor))
711  {
712  float Temp_color[3];
713 
714  float C0_min = 5000, C1_min = 5000, C2_min = 5000;
715  float C0_max = -5000, C1_max = -5000, C2_max = -5000;
716 
717  // calculate new color and find min values.
718  auto vertex_iterator_pair = vertices(_pMesh);
719  vertex_iterator pVertex = vertex_iterator_pair.first;
720  vertex_iterator pVertex_end = vertex_iterator_pair.second;
721  for(; pVertex != pVertex_end; ++pVertex)
722  {
723  Color c = get(*v_cm, *pVertex);
724  Temp_color[0] = c[0];
725  Temp_color[1] = c[1];
726  Temp_color[2] = c[2];
727 
728  // Color space conversion.
729  float New_color[3];
730  RGB_To_LAB(Temp_color[0], Temp_color[1], Temp_color[2], New_color);
731 
732  // assignment of color in new color space in order to quantize later.
733  put(*v_cm, *pVertex, Color(New_color[0], New_color[1], New_color[2]));
734 
735  // calculate min and max to identify quantization step.
736  if(New_color[0] > C0_max)
737  C0_max = New_color[0];
738  if(New_color[0] < C0_min)
739  C0_min = New_color[0];
740 
741  if(New_color[1] > C1_max)
742  C1_max = New_color[1];
743  if(New_color[1] < C1_min)
744  C1_min = New_color[1];
745 
746  if(New_color[2] > C2_max)
747  C2_max = New_color[2];
748  if(New_color[2] < C2_min)
749  C2_min = New_color[2];
750  }
751 
752  const int Nb_interaval = (int)std::pow(2.0, C0_QUANTIZATION) - 1;
753 
754  float Color_max = C0_max - C0_min;
755  if(C1_max - C1_min > Color_max)
756  Color_max = C1_max - C1_min;
757  if(C2_max - C2_min > Color_max)
758  Color_max = C2_max - C2_min;
759 
760  // Information needed to quantize converted color.
761  this->C0_Min = C0_min;
762  this->C1_Min = C1_min;
763  this->C2_Min = C2_min;
764 
765  // Step size of color quantization
766  this->Color_Quantization_Step = (float)((Color_max) / Nb_interaval);
767 
768  // Enter quantized color valued into "vertex->color_int" to use lated.
769  // Also, recalculate vertex color using these quantized color values.
770  Color_Unit Resulting_color;
771  float New_vertex_color[3];
772  float Reconstructed_color[3];
773 
774  // int Color_index = 0;
775  pVertex = vertex_iterator_pair.first;
776  for(; pVertex != pVertex_end; ++pVertex)
777  {
778  Color c = get(*v_cm, *pVertex);
779  Temp_color[0] = c[0];
780  Temp_color[1] = c[1];
781  Temp_color[2] = c[2];
782 
783  int Qc0 = (int)(floor(
784  (Temp_color[0] - C0_min) / this->Color_Quantization_Step + 0.5));
785  int Qc1 = (int)(floor(
786  (Temp_color[1] - C1_min) / this->Color_Quantization_Step + 0.5));
787  int Qc2 = (int)(floor(
788  (Temp_color[2] - C2_min) / this->Color_Quantization_Step + 0.5));
789 
790  Resulting_color.c0 = Qc0;
791  Resulting_color.c1 = Qc1;
792  Resulting_color.c2 = Qc2;
793  put(this->vertex_color_int,
794  *pVertex,
795  Color_Unit(
796  Resulting_color.c0, Resulting_color.c1, Resulting_color.c2));
797 
798  New_vertex_color[0] =
799  this->C0_Min + Resulting_color.c0 * this->Color_Quantization_Step;
800  New_vertex_color[1] =
801  this->C1_Min + Resulting_color.c1 * this->Color_Quantization_Step;
802  New_vertex_color[2] =
803  this->C2_Min + Resulting_color.c2 * this->Color_Quantization_Step;
804 
805  LAB_To_RGB(New_vertex_color[0],
806  New_vertex_color[1],
807  New_vertex_color[2],
808  Reconstructed_color);
809  for(int i = 0; i < 3; i++)
810  {
811  if(Reconstructed_color[i] < 0.)
812  Reconstructed_color[i] = 0.;
813  if(Reconstructed_color[i] > 1.)
814  Reconstructed_color[i] = 1.;
815  }
816 
817  // re-paint the input mesh with reconstructed colors from Lab to RGB
818  // transformation.
819  put(*v_cm,
820  *pVertex,
821  Color(Reconstructed_color[0],
822  Reconstructed_color[1],
823  Reconstructed_color[2]));
824  }
825  }
826 
827 #ifdef DBG_Color_Initialization
828  {
829  std::cout << "DBG "
830  << "--- function " << __func__ << std::endl;
831  std::cout << "DBG "
832  << "this->IsColored=" << this->IsColored << std::endl;
833  std::cout << "DBG "
834  << "this->IsOneColor=" << this->IsOneColor << std::endl;
835 
836  if(this->IsColored)
837  {
838  std::cout << "DBG "
839  << "vertex->color()=" << std::endl;
840 
841  auto vertex_iterator_pair = vertices(_pMesh);
842  vertex_iterator pVertex = vertex_iterator_pair.first;
843  vertex_iterator pVertex_end = vertex_iterator_pair.second;
844  for(; pVertex != pVertex_end; ++pVertex)
845  {
846  Color c = get(*v_cm, *pVertex);
847  std::cout << "DBG " << c[0] << " " << c[1] << " " << c[2]
848  << std::endl;
849  }
850  }
851 
852  if((this->IsColored) && (!this->IsOneColor))
853  {
854  std::cout << "DBG "
855  << "vertex->color_int()=" << std::endl;
856 
857  auto vertex_iterator_pair = vertices(_pMesh);
858  vertex_iterator pVertex = vertex_iterator_pair.first;
859  vertex_iterator pVertex_end = vertex_iterator_pair.second;
860  for(; pVertex != pVertex_end; ++pVertex)
861  {
862  Color_Unit c = get(this->vertex_color_int, *pVertex);
863  std::cout << "DBG " << c.c0 << " " << c.c1 << " " << c.c2
864  << std::endl;
865  }
866  }
867  }
868 #endif
869 }
870 
871 
872 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
873 void
875  Adaptive_Quantization(HalfedgeGraph &_pMesh,
876  PointMap *_pm,
877  VertexColorMap *_v_cm,
878  const int &_NVertices,
879  const bool _Normal_flipping,
880  const bool _Use_metric,
881  const float &_Metric_thread,
882  const bool _Use_forget_metric,
883  const int &_Forget_value,
884  const int &/*_Qbit*/)
885 {
886 
887 
888  if(!this->IsColored)
889  {
890  // bool Is_any_vertex_removed = true;
891  unsigned Last_Number = 0;
892  unsigned Current_Number = FEVV::size_of_vertices(_pMesh);
893  int Operation_choice = -1;
894 
895  // int Old_Q;
896  // double mrms, mrmswrtBB, hausdorff, hausdorffwrtBB;
897  bool Continue;
898  do
899  {
900  Last_Number = Current_Number;
901  Continue = false;
902 
903  for(int Component_ID = 0; Component_ID < this->NumberComponents;
904  Component_ID++)
905  {
906  // if the ith component did not remove any vertex in last loop, it is
907  // not necessary to simplifiy it.
908  if(this->ComponentOperations[Component_ID] ==
909  this->GlobalCountOperation)
910  {
911  int temp = 0;
912 
913  // Calculate area of each component.
914  this->Recalculate_Component_Area(_pMesh, _pm, Component_ID, temp);
915 
916  // Estimated quantization precision of geometry
917  int QG = Estimate_Geometry_Quantization(
918  this->ComponentVolume[Component_ID],
919  this->ComponentArea[Component_ID],
920  this->ComponentNumberVertices[Component_ID]);
921 
922  if(QG < 4)
923  QG = 4;
924 
925  // if the current precision is > QG then we apply decrease of
926  // quantization precision
927  if(QG < (int)this->Qbit[Component_ID]) // MT
928  {
929  Continue = true;
930  Operation_choice = 1;
931 
932  // Reducing of quantization precision of 1 bit.
933  this->Diminush_Geometry_Quantization_Precision(
934  _pMesh, Component_ID, _pm);
935 
936  this->Qbit[Component_ID]--;
937  this->NumberChangeQuantization[Component_ID]++;
938 
939  this->ComponentOperations[Component_ID]++;
940  this->ListOperation[Component_ID].push_front(Operation_choice);
941  }
942  // else -> Decimation
943  else
944  {
945  Operation_choice = 0;
946 
947  unsigned Initial_number_vertices = FEVV::size_of_vertices(_pMesh);
948 
949  // Decimation and regulation conquests.
950  this->Decimation_Conquest(_pMesh,
951  _pm,
952  _Normal_flipping,
953  _Use_metric,
954  _Metric_thread,
955  _Use_forget_metric,
956  _Forget_value,
957  Component_ID);
958  this->Regulation(_pMesh,
959  _Normal_flipping,
960  _Use_metric,
961  _Metric_thread,
962  _Use_forget_metric,
963  _Forget_value,
964  Component_ID,
965  _pm);
966 
967  this->NumberDecimation[Component_ID] += 1;
968  this->ComponentOperations[Component_ID] += 1;
969  this->ListOperation[Component_ID].push_front(Operation_choice);
970 
971  unsigned Diff_number_vertices =
972  FEVV::size_of_vertices(_pMesh) - Initial_number_vertices;
973  this->ComponentNumberVertices[Component_ID] += Diff_number_vertices;
974 
975  if(Diff_number_vertices == 0)
976  this->Remove_Last_Phase_Elements(Component_ID);
977 
978  else
979  Continue = true;
980  }
981  }
982  }
983 
984  Current_Number = FEVV::size_of_vertices(_pMesh);
985 
986  if(Continue)
987  this->GlobalCountOperation++;
988 
989 
990  if(Current_Number < (unsigned)_NVertices) // MT
991  break;
992 
993  } while((Current_Number != Last_Number) || (Continue));
994 
995  compute_normals(_pMesh, _pm);
996  }
997 
998  // if mesh is colored
999  else
1000  {
1001  FILE *Operation_order = fopen("Operation_order.txt", "w");
1002  fclose(Operation_order);
1003 
1004  // bool Is_any_vertex_removed = true;
1005  unsigned Last_Number = 0;
1006  unsigned Current_Number = FEVV::size_of_vertices(_pMesh);
1007  int Operation_choice = -1;
1008 
1009  std::vector< int > QC_Initials;
1010  std::vector< int > QC_Finals;
1011 
1012  // To get QC_Initial and QC_Final
1013  for(int Component_ID = 0; Component_ID < this->NumberComponents;
1014  Component_ID++)
1015  {
1016  double Max_color, Mean_color;
1017  int Number_vertices = 0;
1018 
1019  // Calculate max and mean color error.
1020  this->Calculate_Edge_Color_Difference(
1021  _pMesh, Component_ID, Max_color, Mean_color, Number_vertices);
1022  double Mean_Max = Mean_color / Max_color;
1023 
1024  // int QC_Initial = floor(-56.334*Mean_Max*Mean_Max +4.6838*Mean_Max
1025  // +7.8632 + 0.5); int QC_Final = floor(-0.893 * log(Mean_Max*Area)
1026  // + 8.0957 + 0.5);
1027 
1028  int QC_init = floor(-57.966 * Mean_Max * Mean_Max + 5.311 * Mean_Max +
1029  7.8062 + 0.5);
1030  int QC_fin = floor(84.548 * Mean_Max * Mean_Max - 33.723 * Mean_Max +
1031  7.8222 + 0.5);
1032 
1033  QC_Initials.push_back(QC_init);
1034  QC_Finals.push_back(QC_fin);
1035  }
1036 
1037 
1038  bool Continue;
1039  do
1040  {
1041  Last_Number = Current_Number;
1042  Continue = false;
1043 
1044  for(int Component_ID = 0; Component_ID < this->NumberComponents;
1045  Component_ID++)
1046  {
1047  // if the i-th component did not remove any vertex in last loop, it is
1048  // not necessary to simplifiy it.
1049  if(this->ComponentOperations[Component_ID] ==
1050  this->GlobalCountOperation)
1051  {
1052  int temp = 0;
1053  this->Recalculate_Component_Area(_pMesh, _pm, Component_ID, temp);
1054  int Number_of_vertices = 0;
1055  double Max_color = 0., Mean_color = 0.;
1056  this->Calculate_Edge_Color_Difference(
1057  _pMesh, Component_ID, Max_color, Mean_color, Number_of_vertices);
1058  double Mean_Max = Mean_color / Max_color;
1059 
1060  // Estimated color quantization(QC) and geometry quantization (QG)
1061  int QC =
1062  floor(-1.181 * log(Mean_Max * this->ComponentArea[Component_ID] /
1063  (double)Number_of_vertices) +
1064  0.3281 + 0.5);
1065  int QG = Estimate_Geometry_Quantization(
1066  this->ComponentVolume[Component_ID],
1067  this->ComponentArea[Component_ID],
1068  this->ComponentNumberVertices[Component_ID]);
1069 
1070  // If the current color quantization precision > QC_INIT -> Decrease
1071  // one bit from color quantization resolution.
1072  if((8 - this->NumberColorQuantization[Component_ID] >
1073  QC_Initials[Component_ID]) &&
1074  (!this->IsOneColor)) // && (QC_Final < 8 -
1075  // this->NumberColorQuantization))
1076  {
1077  Operation_choice = 2;
1078  Continue = true;
1079 
1080  // Reducing color quantization precision of 1 bit.
1081  this->Diminush_Color_Quantization_Precision(
1082  _pMesh, Component_ID, _v_cm);
1083 
1084  this->NumberColorQuantization[Component_ID]++;
1085  this->ComponentOperations[Component_ID]++;
1086  this->ListOperation[Component_ID].push_front(Operation_choice);
1087  }
1088  // If the current color quantization precision > Estimated precision
1089  // -> Decrease
1090  else if(((8 - this->NumberColorQuantization[Component_ID] > QC) &&
1091  (QC >= QC_Finals[Component_ID])) &&
1092  (!this->IsOneColor))
1093  {
1094  Operation_choice = 2;
1095  Continue = true;
1096 
1097  // Reducing color quantization precision of 1 bit.
1098  this->Diminush_Color_Quantization_Precision(
1099  _pMesh, Component_ID, _v_cm);
1100 
1101  this->NumberColorQuantization[Component_ID]++;
1102  this->ComponentOperations[Component_ID]++;
1103  this->ListOperation[Component_ID].push_front(Operation_choice);
1104  }
1105 
1106  // Geometry quantization precision decrease
1107  else if(((int)this->Qbit[Component_ID] > QG) && (QG >= 5))
1108  {
1109  Continue = true;
1110  Operation_choice = 1;
1111 
1112  // Reducuing geometry quantization precision of 1 bit.
1113  this->Diminush_Geometry_Quantization_Precision(
1114  _pMesh, Component_ID, _pm);
1115 
1116  this->Qbit[Component_ID]--;
1117  this->NumberChangeQuantization[Component_ID]++;
1118 
1119  this->ComponentOperations[Component_ID]++;
1120  this->ListOperation[Component_ID].push_front(Operation_choice);
1121  }
1122 
1123  // Else we perform decimation
1124  else
1125  {
1126  Operation_choice = 0;
1127 
1128  unsigned Initial_number_vertices = FEVV::size_of_vertices(_pMesh);
1129 
1130  // Decimation and regulation conquests.
1131  this->Decimation_Conquest(_pMesh,
1132  _pm,
1133  _Normal_flipping,
1134  _Use_metric,
1135  _Metric_thread,
1136  _Use_forget_metric,
1137  _Forget_value,
1138  Component_ID);
1139  this->Regulation(_pMesh,
1140  _Normal_flipping,
1141  _Use_metric,
1142  _Metric_thread,
1143  _Use_forget_metric,
1144  _Forget_value,
1145  Component_ID,
1146  _pm);
1147 
1148  this->NumberDecimation[Component_ID] += 1;
1149  unsigned Diff_number_vertices =
1150  FEVV::size_of_vertices(_pMesh) - Initial_number_vertices;
1151 
1152  this->ComponentOperations[Component_ID] += 1;
1153  this->ListOperation[Component_ID].push_front(Operation_choice);
1154 
1155  this->ComponentNumberVertices[Component_ID] += Diff_number_vertices;
1156 
1157  if(Diff_number_vertices == 0)
1158  this->Remove_Last_Phase_Elements(Component_ID);
1159 
1160  else
1161  Continue = true;
1162  }
1163  FILE *Operation_order = fopen("Operation_order.txt", "a");
1164  fprintf(Operation_order,
1165  "Component_ID = %d Operation = %d \n",
1166  Component_ID,
1167  Operation_choice);
1168  fclose(Operation_order);
1169  }
1170  }
1171 
1172  Current_Number = FEVV::size_of_vertices(_pMesh);
1173 
1174  if(Continue)
1175  this->GlobalCountOperation++;
1176 
1177 
1178  if(Current_Number < (unsigned)_NVertices) // MT
1179  break;
1180 
1181  } while((Current_Number != Last_Number) || (Continue));
1182 
1183  compute_normals(_pMesh, _pm);
1184  }
1185 }
1186 
1187 
1188 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
1189 void
1191  HalfedgeGraph &mesh)
1192 {
1193  typedef boost::graph_traits< HalfedgeGraph > GraphTraits;
1194  typedef typename GraphTraits::vertex_iterator vertex_iterator;
1195  typedef typename GraphTraits::face_iterator face_iterator;
1196 
1197  // vertices flags initialization
1198  int i = 0;
1199  // Initialize vertex flags
1200  auto vertex_iterator_pair = vertices(mesh);
1201  vertex_iterator pVertex_beg = vertex_iterator_pair.first;
1202  vertex_iterator pVertex_end = vertex_iterator_pair.second;
1203  for(vertex_iterator pVertex = pVertex_beg; pVertex != pVertex_end;
1204  ++pVertex, ++i)
1205  {
1206  put(this->Vertex_Flag, *pVertex, FREE);
1207  put(this->Vertex_Number, *pVertex, i);
1208  put(this->Vertex_Sign, *pVertex, NOSIGN);
1209  }
1210 
1211  // facets flag initialization.
1212  auto face_iterator_pair = faces(mesh);
1213  face_iterator pFacet_beg = face_iterator_pair.first;
1214  face_iterator pFacet_end = face_iterator_pair.second;
1215  for(face_iterator pFacet = pFacet_beg; pFacet != pFacet_end; ++pFacet)
1216  {
1217  put(this->Facet_Flag, *pFacet, FREE);
1218  }
1219 }
1220 
1221 
1222 #if 1 // DBG-ELO+beg
1223 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
1224 void
1226  print_halfedge(const std::string &title,
1227  const halfedge_descriptor &h,
1228  const HalfedgeGraph &_pMesh,
1229  const PointMap *_pm)
1230 {
1231  vertex_descriptor vtarget = target(h, _pMesh);
1232  vertex_descriptor vsource = source(h, _pMesh);
1233 
1234  Point3d psource = get(*_pm, vsource);
1235  Point3d ptarget = get(*_pm, vtarget);
1236 
1237  std::cout << title << " :" << std::endl;
1238  std::cout << " psource = " << psource[0] << ", " << psource[1] << ", "
1239  << psource[2] << std::endl;
1240  std::cout << " ptarget = " << ptarget[0] << ", " << ptarget[1] << ", "
1241  << ptarget[2] << std::endl;
1242  bool is_border_edge =
1243  (face(h, _pMesh) == boost::graph_traits< HalfedgeGraph >::null_face());
1244  std::cout << " is_border = " << std::boolalpha << is_border_edge
1245  << std::endl;
1246 }
1247 
1248 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
1249 void
1251  print_vertex(const std::string &title,
1252  const vertex_descriptor &v,
1253  const PointMap *_pm)
1254 {
1255  Point3d p = get(*_pm, v);
1256  std::cout << title << " = " << p[0] << ", " << p[1] << ", " << p[2]
1257  << std::endl;
1258 }
1259 
1260 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
1261 std::string
1263  vertex_to_string(const vertex_descriptor &v, const PointMap *_pm)
1264 {
1265  Point3d p = get(*_pm, v);
1266  std::ostringstream s;
1267  s << "(" << p[0] << ", " << p[1] << ", " << p[2] << ")";
1268  return s.str();
1269 }
1270 #endif // DBG-ELO+end
1271 
1272 
1273 #if 1 // DBG-ELO+beg
1274 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
1275 std::string
1278  const HalfedgeGraph &_pMesh,
1279  const PointMap *_pm)
1280 {
1281  vertex_descriptor vtarget = target(h, _pMesh);
1282  vertex_descriptor vsource = source(h, _pMesh);
1283 
1284  std::ostringstream s;
1285  s << vertex_to_string(vsource, _pm) << "->" << vertex_to_string(vtarget, _pm);
1286  return s.str();
1287 }
1288 #endif // DBG-ELO+end
1289 
1290 
1291 #if 1 // DBG-ELO+beg
1292 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
1293 bool
1295  v_inf_to_v(const vertex_descriptor &v1,
1296  const vertex_descriptor &v2,
1297  const PointMap *_pm)
1298 {
1299  Point3d p1 = get(*_pm, v1);
1300  Point3d p2 = get(*_pm, v2);
1301 
1302  if(p1[0] < p2[0])
1303  return true;
1304  else if((p1[0] == p2[0]) && (p1[1] < p2[1]))
1305  return true;
1306  else if((p1[0] == p2[0]) && (p1[1] == p2[1]) && (p1[2] < p2[2]))
1307  return true;
1308  else
1309  return false;
1310 }
1311 
1312 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
1313 std::string
1316  const HalfedgeGraph &_pMesh,
1317  const PointMap *_pm)
1318 {
1319  vertex_descriptor vtarget = target(h, _pMesh);
1320  vertex_descriptor vsource = source(h, _pMesh);
1321 
1322  std::ostringstream s;
1323  if(v_inf_to_v(vsource, vtarget, _pm))
1324  s << vertex_to_string(vsource, _pm) << "->"
1325  << vertex_to_string(vtarget, _pm);
1326  else
1327  s << vertex_to_string(vtarget, _pm) << "->"
1328  << vertex_to_string(vsource, _pm);
1329 
1330  return s.str();
1331 }
1332 #endif // DBG-ELO+end
1333 
1334 
1335 //#define DBG_Decimation_Conquest
1336 
1337 // Description : This function select a set of independent vertices to be
1338 // removed
1339 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
1340 int
1342  Decimation_Conquest(HalfedgeGraph &_pMesh,
1343  const PointMap *_pm,
1344  const bool Normal_flipping,
1345  const bool Use_metric,
1346  const float &Metric_thread,
1347  const bool Use_forget_metric,
1348  const int &Forget_value,
1349  const int &Component_ID)
1350 {
1351  typedef boost::graph_traits< HalfedgeGraph > GraphTraits;
1352  typedef typename GraphTraits::halfedge_iterator halfedge_iterator;
1353 
1354 #ifdef DBG_Decimation_Conquest
1355  static unsigned int Decimation_Conquest_call_cnt = 0;
1356  Decimation_Conquest_call_cnt++;
1357  std::cout << "Decimation_Conquest_call_cnt = " << Decimation_Conquest_call_cnt
1358  << std::endl;
1359 #endif
1360 
1361  // Calculate mean color and meah area for color metric
1362  double Max_color, Mean_color;
1363  int Temp_NV = 0;
1364  int Number_facets;
1365  this->Calculate_Edge_Color_Difference(
1366  _pMesh, Component_ID, Max_color, Mean_color, Temp_NV);
1367  this->Recalculate_Component_Area(_pMesh, _pm, Component_ID, Number_facets);
1368  double Mean_area =
1369  (double)this->ComponentArea[Component_ID] / (double)Number_facets;
1370 
1371 
1372  // Initialize vertex and face flags.
1373  this->Init(_pMesh);
1374 
1375  // to count number of independent vertices and number of symbol of
1376  // connectivity.
1377  int Number_vertices = 0;
1378  int Number_symbol = 0;
1379 
1380  // To find first edge.
1381  auto halfedge_iterator_pair = halfedges(_pMesh);
1382  halfedge_iterator hi = halfedge_iterator_pair.first;
1383 
1384  while(
1385  (get(this->vertex_Seed_Edge, target(*hi, _pMesh)) != 2 * Component_ID) ||
1386  (get(this->vertex_Seed_Edge, target(opposite(*hi, _pMesh), _pMesh)) !=
1387  2 * Component_ID + 1))
1388  hi++;
1389 
1390  halfedge_descriptor First_halfedge = *hi;
1391 #ifdef DBG_Decimation_Conquest
1392  std::cout << "marker #1" << std::endl;
1393  print_halfedge("First_halfedge", First_halfedge, _pMesh, _pm);
1394  int loop_counter = 0;
1395 #endif
1396 
1397  // Two vertices of seed edge are flaged CONQUERED
1398  put(this->Vertex_Flag, target(First_halfedge, _pMesh), CONQUERED);
1399  put(this->Vertex_Flag,
1400  target(opposite(First_halfedge, _pMesh), _pMesh),
1401  CONQUERED);
1402 
1403  // These vertices are also flaged with sign flags for retriangulation
1404  put(this->Vertex_Sign, target(First_halfedge, _pMesh), PLUS);
1405  put(this->Vertex_Sign,
1406  target(opposite(First_halfedge, _pMesh), _pMesh),
1407  MINUS);
1408 
1409  std::queue< halfedge_descriptor > Halfedges; // halfedge queue.
1410  Halfedges.push(First_halfedge); // push the first halfedge in the queue.
1411 
1412  halfedge_descriptor h; // The current gate
1413 
1415  while(!Halfedges.empty())
1416  {
1417 #ifdef DBG_Decimation_Conquest
1418  std::cout << "marker #2" << std::endl;
1419  std::cout << "loop " << ++loop_counter << std::endl;
1420 #endif
1421  h = Halfedges.front();
1422 #ifdef DBG_Decimation_Conquest
1423  print_halfedge("h #2", h, _pMesh, _pm);
1424 #endif
1425  Halfedges.pop();
1426 
1427  unsigned type = 0; // define type of retriangulation
1428 
1429  int valence = (int)out_degree(target(next(h, _pMesh), _pMesh),
1430  _pMesh); // valence
1431 
1432  if(CGAL::is_border(h, _pMesh) == true)
1433  continue;
1434 #ifdef DBG_Decimation_Conquest
1435  std::cout << "marker #3" << std::endl;
1436  std::cout << "(h->next()->vertex()->Vertex_Flag == FREE)"
1437  << (get(this->Vertex_Flag, target(next(h, _pMesh), _pMesh)) ==
1438  FREE)
1439  << std::endl;
1440  std::cout << "(valence >= 3)" << (valence >= 3) << std::endl;
1441  std::cout << "(valence <= 4)" << (valence <= 4) << std::endl;
1442  std::cout << "(Is_Border_Vertex(h->next()) == true)"
1443  << (Is_Border_Vertex(next(h, _pMesh), _pMesh) == true)
1444  << std::endl;
1445 #endif
1446 
1447  // if its front face is not tagged CONQUERED nor TO_BE_REMOVED, do nothing!!
1448  if((get(this->Facet_Flag, face(h, _pMesh)) == CONQUERED) ||
1449  (get(this->Facet_Flag, face(h, _pMesh)) == TO_BE_REMOVED))
1450  {
1451 #ifdef DBG_Decimation_Conquest
1452  std::cout << "marker #4" << std::endl;
1453 #endif
1454  continue;
1455  }
1456  // if its front vertex is free and has a valence <= 6 and it is not a border
1457  // vertex.
1458  else if((get(this->Vertex_Flag, target(next(h, _pMesh), _pMesh)) == FREE) &&
1459  (valence >= 3) && (valence <= 6) &&
1460  (!Is_Border_Vertex(next(h, _pMesh), _pMesh)))
1461  {
1462 #ifdef DBG_Decimation_Conquest
1463  std::cout << "marker #5" << std::endl;
1464 #endif
1465 
1466  type = Find_Type(_pMesh, h, valence);
1467 
1468  // Check if the manifold property is violated.
1469  bool Manifold_condition =
1470  Is_Manifold_Property_Violated(_pMesh, h, type, valence);
1471 
1472  bool Normal_flipping_condition = false;
1473 
1474  if(Normal_flipping)
1475  Normal_flipping_condition =
1476  Is_Normal_Flipping_Occured(_pMesh, _pm, h, valence);
1477 
1478  // calculate error caused by the removal. This metric decides if the
1479  // vertex can be removed or not.
1480  bool Geometric_metric_condition = false;
1481 
1482  if(Use_metric)
1483  {
1484  if(Use_forget_metric)
1485  {
1486  if(FEVV::size_of_vertices(_pMesh) > (unsigned)Forget_value)
1487  Geometric_metric_condition = false;
1488  else
1489  Geometric_metric_condition = Is_Geometric_Metric_Violated(
1490  _pMesh, _pm, h, type, valence, Metric_thread);
1491  }
1492  else
1493  Geometric_metric_condition = Is_Geometric_Metric_Violated(
1494  _pMesh, _pm, h, type, valence, Metric_thread);
1495  }
1496  bool Is_Color_Too_Important = false;
1497 
1498 #ifdef USE_COLOR_METRIC
1499  if(this->IsColored)
1500  Is_Color_Too_Important = this->Error_Projected_Surface(
1501  _pMesh, _pm, h, Component_ID, Mean_color, Mean_area);
1502 #endif
1503 #ifdef DBG_Decimation_Conquest
1504  std::cout << "Is_Color_Too_Important = " << Is_Color_Too_Important
1505  << std::endl;
1506 #endif
1507 
1508  // remove the front vertex if its removal does not viloate the manifold
1509  // property and some metrics
1510  bool Check_all_condition = false;
1511 
1512  if((!Manifold_condition) && (!Geometric_metric_condition) &&
1513  (!Normal_flipping_condition) && (!Is_Color_Too_Important))
1514  Check_all_condition = true;
1515 
1516  if(Check_all_condition) // All conditions are good. -> Remove the center
1517  // vertex.
1518  {
1519 #ifdef DBG_Decimation_Conquest
1520  std::cout << "marker #6" << std::endl;
1521 #endif
1522 
1523  // increase number of vertices and symbols
1524  Number_vertices++;
1525  Number_symbol++;
1526 
1527  halfedge_descriptor g = h;
1528 
1529  Point3d Coordinates_removed_vertex =
1530  get(*_pm, target(next(g, _pMesh), _pMesh));
1531  Point_Int CRV =
1532  Change_Real_Int(Coordinates_removed_vertex, Component_ID);
1533 
1534  // encoding of vertex color
1535  if((this->IsColored) && (!this->IsOneColor))
1536  {
1537  Color_Unit Removed_vertex_color;
1538  Removed_vertex_color = Get_Vertex_Color(next(g, _pMesh), _pMesh);
1539 
1540  Color_Unit Average_color;
1541 
1542  Average_color = Get_Average_Vertex_Color_Lee(g, valence, _pMesh);
1543 
1544 
1545  // Color difference from average color of neighbors
1546  Color_Unit Color_diff = Removed_vertex_color - Average_color;
1547  this->InterVertexColor.push_front(Color_diff);
1548  }
1549 
1550 
1551  // Enter symbol 'VALENCE CODE' into the list of symbols
1552  this->InterConnectivity.push_front(valence - 3);
1553 
1554  // Calculate the position of barycenter.
1555  Point3d Barycenter = Barycenter_Patch_Before_Removal(g, _pMesh, _pm);
1556 
1557  Point_Int BC = Change_Real_Int(Barycenter, Component_ID);
1558 
1559  // remove the front vertex
1560 #ifdef DBG_Decimation_Conquest
1561  print_halfedge("remove vertex", next(g, _pMesh), _pMesh, _pm);
1562 #endif
1563  CGAL::Euler::remove_center_vertex(next(g, _pMesh), _pMesh);
1564 
1565  g = h;
1566  put(this->Facet_Flag, face(g, _pMesh), TEMP_FLAG);
1567 
1568  // Flags and fill queue
1569  for(int j = 0; j < (valence - 1); j++)
1570  {
1571  g = next(g, _pMesh);
1572  put(this->Vertex_Flag, target(g, _pMesh), CONQUERED);
1573 
1574  put(this->Vertex_Flag,
1575  target(opposite(g, _pMesh), _pMesh),
1576  CONQUERED);
1577 
1578  if(!(CGAL::is_border_edge(g, _pMesh)))
1579  Halfedges.push(opposite(g, _pMesh));
1580  }
1581  g = h;
1582 
1583  Retriangulation(_pMesh, g, valence, 0, Component_ID, _pm);
1584 
1585  Vector normal = Normal_Patch(g, valence, _pMesh, _pm);
1586  Vector T2 = Vector(0.0, 0.0, 0.0);
1587  Vector T1 = Calculate_T1_T2(h, normal, T2, _pMesh, _pm);
1588 
1589  if(normal == Vector(0.0, 0.0, 0.0))
1590  {
1591  T1 = Vector(1., 0., 0.);
1592  T2 = Vector(0., 1., 0.);
1593  normal = Vector(0., 0., 1.);
1594  }
1595  else if(T1 == Vector(0.0, 0.0, 0.0))
1596  {
1597  T1 = Vector(1., 0., 0.);
1598  T2 = Vector(0., 1., 0.);
1599  normal = Vector(0., 0., 1.);
1600  }
1601  else if(T2 == Vector(0.0, 0.0, 0.0))
1602  {
1603  T1 = Vector(1., 0., 0.);
1604  T2 = Vector(0., 1., 0.);
1605  normal = Vector(0., 0., 1.);
1606  }
1607 
1608  Point_Int Dist = CRV - BC;
1609  Point_Int Frenet_Coordinates;
1610  // Bijection
1611  if(this->Is_Bijection_Enabled)
1612  Frenet_Coordinates = Frenet_Rotation(Dist, T1, T2, normal);
1613  else
1614  Frenet_Coordinates = Dist;
1615 
1616  this->InterGeometry.push_front(Frenet_Coordinates);
1617  }
1618 
1619  // Conditions are not satisfied -> NULL CODE
1620  else
1621  {
1622 #ifdef DBG_Decimation_Conquest
1623  std::cout << "marker #7" << std::endl;
1624 #endif
1625  // Enter symbol 'NULL PATCH' into the list of symbols
1626  this->InterConnectivity.push_front(4);
1627 
1628  Number_symbol++;
1629  put(this->Facet_Flag, face(h, _pMesh), CONQUERED);
1630  put(this->Vertex_Flag, target(next(h, _pMesh), _pMesh), CONQUERED);
1631 
1632  if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
1633  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
1634  MINUS))
1635  {
1636  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
1637  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), PLUS);
1638  }
1639  else if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
1640  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
1641  PLUS))
1642  {
1643  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
1644  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), PLUS);
1645  }
1646  else if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
1647  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
1648  PLUS))
1649  {
1650  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
1651  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), MINUS);
1652  }
1653  else if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
1654  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
1655  MINUS))
1656  {
1657  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
1658  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), PLUS);
1659  }
1660 
1661  if(!CGAL::is_border_edge(next(h, _pMesh), _pMesh))
1662  Halfedges.push(opposite(next(h, _pMesh), _pMesh));
1663 
1664  if(!CGAL::is_border_edge(prev(h, _pMesh), _pMesh))
1665  Halfedges.push(opposite(prev(h, _pMesh), _pMesh));
1666  }
1667  }
1668 
1669 
1670  // border edge.
1671  else if((get(this->Vertex_Flag, target(next(h, _pMesh), _pMesh)) == FREE) &&
1672  (valence >= 3) && (valence <= 4) &&
1673  (Is_Border_Vertex(next(h, _pMesh), _pMesh) == true))
1674  {
1675 #ifdef DBG_Decimation_Conquest
1676  std::cout << "marker #8" << std::endl;
1677 #endif
1678  /***** conditions of vertex removal (based on area) will be added
1679  * *****/
1680  /***** conditions of vertex removal (based on area) will be added
1681  * *****/
1682 
1683  type = Find_Type(_pMesh, h, valence);
1684 #ifdef DBG_Decimation_Conquest
1685  print_halfedge("h #8", h, _pMesh, _pm);
1686 #endif
1687 
1688  halfedge_descriptor g = h;
1689 
1690  bool Check_border_structure = true;
1691 
1692  halfedge_descriptor First_border_edge;
1693  halfedge_descriptor Standard_edge;
1694 
1695 
1696  // To find first border edge.
1697  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc(
1698  target(next(g, _pMesh), _pMesh), _pMesh);
1699  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc_end = Hvc;
1700 
1701  int Number_neighboring_border_vertices = 0;
1702  CGAL_For_all(Hvc, Hvc_end)
1703  {
1704  // ELO in this loop the halfedges are not traversed in the same order
1705  // ELO as in Mepp1 ; the direction of rotation is the same
1706 
1707  if(Is_Border_Vertex(opposite(*Hvc, _pMesh), _pMesh))
1708  {
1709  Number_neighboring_border_vertices++;
1710  }
1711 
1712  if(CGAL::is_border(*Hvc, _pMesh))
1713  {
1714  First_border_edge = *Hvc;
1715  }
1716  }
1717 #ifdef DBG_Decimation_Conquest
1718  print_halfedge("First_border_edge", First_border_edge, _pMesh, _pm);
1719  std::cout << "Number_neighboring_border_vertices = "
1720  << Number_neighboring_border_vertices << std::endl;
1721 #endif
1722 
1723  if(Number_neighboring_border_vertices > 2)
1724  Check_border_structure = false;
1725 
1726  if(Is_Manifold_Property_Violated(_pMesh, g, type, valence))
1727  Check_border_structure = false;
1728  // Added by Adrien Maglo.
1729  // Test if we are not in the case of a mesh pimple.
1730  if(Check_border_structure)
1731  {
1732 #ifdef DBG_Decimation_Conquest
1733  std::cout << "marker #9" << std::endl;
1734  // Get the two patch border vertices.
1735  print_halfedge("First_border_edge", First_border_edge, _pMesh, _pm);
1736 #endif
1737  vertex_descriptor vh1 = target(next(First_border_edge, _pMesh), _pMesh);
1738  vertex_descriptor vh2 =
1739  target(opposite(First_border_edge, _pMesh), _pMesh);
1740  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > vh_it =
1741  CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(vh1,
1742  _pMesh);
1743  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > vh_it_end =
1744  vh_it;
1745 
1746  // Test if the two patch border vertices are not connected
1747  // by an edge.
1748  CGAL_For_all(vh_it, vh_it_end)
1749  {
1750  if(target(opposite(*vh_it, _pMesh), _pMesh) == vh2)
1751  {
1752  Check_border_structure = false;
1753  break;
1754  }
1755  }
1756 #ifdef DBG_Decimation_Conquest
1757  std::cout << "Check_border_structure = " << std::boolalpha
1758  << Check_border_structure << std::endl;
1759 #endif
1760  }
1761 
1762 
1763  // if the hole is a triangle(Count_border_edges == 3), we should not
1764  // remove the vertex.
1765  int Count_border_edges = 1;
1766  Standard_edge = First_border_edge;
1767  First_border_edge = next(First_border_edge, _pMesh);
1768 
1769  for(; First_border_edge != Standard_edge;
1770  First_border_edge = next(First_border_edge, _pMesh))
1771  {
1772  Count_border_edges++;
1773  if(Count_border_edges > 5)
1774  break;
1775  }
1776 
1777  if(Count_border_edges <= 3)
1778  Check_border_structure = false;
1779 
1780  // Exception which causes a manifold violation
1781  if(Count_border_edges == 4)
1782  if(out_degree(
1783  target(opposite(prev(Standard_edge, _pMesh), _pMesh), _pMesh),
1784  _pMesh) == 2)
1785  Check_border_structure = false;
1786 
1787 
1788  /*if (Check_border_structure)
1789  {
1790  if(valence == 3)
1791  {
1792  if(Is_Border_Vertex(g))
1793  {
1794  if(g->opposite()->vertex_degree() == 3)
1795  Check_border_structure = false;
1796  }
1797  else
1798  {
1799  if(g->vertex_degree() == 3)
1800  Check_border_structure = false;
1801  }
1802  }
1803  }*/
1804 
1805 
1806  if(Check_border_structure)
1807  {
1808 #ifdef DBG_Decimation_Conquest
1809  std::cout << "marker #10" << std::endl;
1810 #endif
1811  Number_vertices++;
1812  Number_symbol++;
1813 
1814  // Connectivity Code = 5 for border valence 3 vertex
1815  // " = 6 for border valence 4 vertex
1816  this->InterConnectivity.push_front(valence + 2);
1817 
1818  Point3d Real_vertex_position =
1819  get(*_pm, target(next(h, _pMesh), _pMesh));
1820  Point_Int Vertex_position =
1821  Change_Real_Int(Real_vertex_position, Component_ID);
1822 
1823  Color_Unit Removed_vertex_color;
1824  // int Vertex_color_index = -1;
1825  if((this->IsColored) && (!this->IsOneColor))
1826  {
1827  Removed_vertex_color = Get_Vertex_Color(next(h, _pMesh), _pMesh);
1828  }
1829 
1830 
1831  std::vector< halfedge_descriptor > Border_edges;
1832  int Number_jump = 0;
1833 
1834  while(CGAL::is_border_edge(next(g, _pMesh), _pMesh) == false)
1835  {
1836  g = next(opposite(next(g, _pMesh), _pMesh), _pMesh);
1837  Number_jump++;
1838  }
1839 
1840  Border_edges.push_back(opposite(g, _pMesh));
1841 #ifdef DBG_Decimation_Conquest
1843  "Border_edges.push_back 1", opposite(g, _pMesh), _pMesh, _pm);
1844 #endif
1845  for(int i = 0; i < (valence - 2); i++)
1846  {
1847  g = prev(opposite(prev(g, _pMesh), _pMesh), _pMesh);
1848  Border_edges.push_back(opposite(g, _pMesh));
1849 #ifdef DBG_Decimation_Conquest
1851  "Border_edges.push_back 2", opposite(g, _pMesh), _pMesh, _pm);
1852 #endif
1853  }
1854 
1855  for(int i = 0; i < (valence - 1); i++)
1856  {
1857  halfedge_descriptor Temp = Border_edges[i];
1858  Temp = opposite(Temp, _pMesh);
1859 
1860  CGAL_assertion(!CGAL::is_border(Temp, _pMesh));
1861 #ifdef DBG_Decimation_Conquest
1862  std::cout << "remove face" << std::endl;
1863 #endif
1864  CGAL::Euler::remove_face(Temp, _pMesh);
1865  }
1866 
1867  if(valence == 3)
1868  {
1869 #ifdef DBG_Decimation_Conquest
1870  std::cout << "marker #11" << std::endl;
1871 #endif
1872  halfedge_descriptor Retriangulation_edge =
1873  prev(opposite(Border_edges[valence - 2], _pMesh), _pMesh);
1874 
1875 
1876  // One triangle has to be created to smooth the mesh boundary
1877 #ifdef DBG_Decimation_Conquest
1878  {
1879  bool is_border_Retriangulation_edge =
1880  (face(Retriangulation_edge, _pMesh) ==
1881  boost::graph_traits< HalfedgeGraph >::null_face());
1882 
1883  print_halfedge("Border_edges[valence - 2]",
1884  Border_edges[valence - 2],
1885  _pMesh,
1886  _pm);
1888  "Retriangulation_edge", Retriangulation_edge, _pMesh, _pm);
1889  }
1890  std::cout << "add face" << std::endl;
1891 #endif
1892  CGAL::Euler::add_face_to_border(
1893  Retriangulation_edge, opposite(Border_edges[0], _pMesh), _pMesh);
1894 
1895  halfedge_descriptor Input_gate =
1896  opposite(Border_edges[Number_jump], _pMesh);
1897 
1898  // its front face is tagged CONQUERED
1899  put(this->Facet_Flag, face(Input_gate, _pMesh), CONQUERED);
1900  put(this->Vertex_Flag,
1901  target(next(Input_gate, _pMesh), _pMesh),
1902  CONQUERED);
1903 
1904  if((type == 1) || (type == 2) || (type == 4))
1905  {
1906  if(get(this->Vertex_Sign,
1907  target(next(Input_gate, _pMesh), _pMesh)) == NOSIGN)
1908  put(this->Vertex_Sign,
1909  target(next(Input_gate, _pMesh), _pMesh),
1910  PLUS);
1911  }
1912  else if(type == 3)
1913  {
1914  if(get(this->Vertex_Sign,
1915  target(next(Input_gate, _pMesh), _pMesh)) == NOSIGN)
1916  put(this->Vertex_Sign,
1917  target(next(Input_gate, _pMesh), _pMesh),
1918  MINUS);
1919  }
1920 
1921 
1922  Point3d Barycenter =
1923  Barycenter_Patch_After_Removal(Input_gate, valence, _pMesh, _pm);
1924  Point_Int BC = Change_Real_Int(Barycenter, Component_ID);
1925 
1926  if((this->IsColored) && (!this->IsOneColor))
1927  {
1928  Color_Unit Average_color;
1929 
1930  Average_color = Get_Average_Vertex_Color_After_Removal(
1931  g, valence, _pMesh); // g is the most left placed edge
1932  Color_Unit Color_diff = Removed_vertex_color - Average_color;
1933 
1934  this->InterVertexColor.push_front(Color_diff);
1935  }
1936 
1937  halfedge_descriptor g = Input_gate;
1938  Vector normal = Normal_Patch(g, valence, _pMesh, _pm);
1939  Vector T2 = Vector(0.0, 0.0, 0.0);
1940 
1941  Vector T1 = Calculate_T1_T2(g, normal, T2, _pMesh, _pm);
1942 
1943  if(normal == Vector(0.0, 0.0, 0.0))
1944  {
1945  normal = Vector(0, 0, 1);
1946  T1 = Vector(1, 0, 0);
1947  T2 = Vector(0, 1, 0);
1948  }
1949 
1950  Point_Int Dist = Vertex_position - BC;
1951 
1952  // bijection
1953 
1954  Point_Int Frenet_Coordinates;
1955  if(this->Is_Bijection_Enabled)
1956  Frenet_Coordinates = Frenet_Rotation(Dist, T1, T2, normal);
1957  else
1958  Frenet_Coordinates = Dist;
1959 
1960 
1961  // Point_Int Frenet_Coordinates = Frenet_Rotation(Dist,T1,T2,normal);
1962 
1963  this->InterGeometry.push_front(Frenet_Coordinates);
1964 
1965  if(Number_jump == 0)
1966  Halfedges.push(Border_edges[1]);
1967  else
1968  Halfedges.push(Border_edges[0]);
1969  }
1970 
1971  else if(valence == 4)
1972  {
1973 #ifdef DBG_Decimation_Conquest
1974  std::cout << "marker #12" << std::endl;
1975 #endif
1976  halfedge_descriptor Retriangulation_edge =
1977  prev(opposite(Border_edges[valence - 2], _pMesh), _pMesh);
1978 
1979  if(((Number_jump == 0) && ((type == 5) || (type == 8))) ||
1980  ((Number_jump == 1) && ((type == 6) || (type == 7))) ||
1981  ((Number_jump == 2) && ((type == 5) || (type == 8))))
1982 
1983  {
1984 #ifdef DBG_Decimation_Conquest
1985  std::cout << "add face" << std::endl;
1986 #endif
1987  CGAL::Euler::add_face_to_border(Retriangulation_edge,
1988  opposite(Border_edges[1], _pMesh),
1989  _pMesh);
1990  put(this->Facet_Flag,
1991  face(opposite(Border_edges[1], _pMesh), _pMesh),
1992  CONQUERED);
1993 
1994 #ifdef DBG_Decimation_Conquest
1995  std::cout << "add face" << std::endl;
1996 #endif
1997  CGAL::Euler::add_face_to_border(Retriangulation_edge,
1998  opposite(Border_edges[0], _pMesh),
1999  _pMesh);
2000  put(this->Facet_Flag,
2001  face(opposite(Border_edges[0], _pMesh), _pMesh),
2002  CONQUERED);
2003  }
2004 
2005  else if(((Number_jump == 0) && ((type == 6) || (type == 7))) ||
2006  ((Number_jump == 1) && ((type == 5) || (type == 8))) ||
2007  ((Number_jump == 2) && ((type == 6) || (type == 7))))
2008  {
2009 #ifdef DBG_Decimation_Conquest
2010  std::cout << "add face" << std::endl;
2011 #endif
2012  CGAL::Euler::add_face_to_border(opposite(Border_edges[2], _pMesh),
2013  opposite(Border_edges[0], _pMesh),
2014  _pMesh);
2015  put(this->Facet_Flag,
2016  face(opposite(Border_edges[1], _pMesh), _pMesh),
2017  CONQUERED);
2018  halfedge_descriptor Temp_border =
2019  next(opposite(Border_edges[2], _pMesh), _pMesh);
2020 
2021 #ifdef DBG_Decimation_Conquest
2022  std::cout << "add face" << std::endl;
2023 #endif
2024  CGAL::Euler::add_face_to_border(
2025  Retriangulation_edge, Temp_border, _pMesh);
2026  put(this->Facet_Flag,
2027  face(opposite(Border_edges[2], _pMesh), _pMesh),
2028  CONQUERED);
2029  }
2030 
2031  halfedge_descriptor Input_gate =
2032  opposite(Border_edges[Number_jump], _pMesh);
2033 
2034 
2035  // Vertex Signs
2036  if((type == 5) || (type == 8))
2037  {
2038  halfedge_descriptor g = Input_gate;
2039  g = next(opposite(prev(g, _pMesh), _pMesh), _pMesh);
2040  if(get(this->Vertex_Sign, target(g, _pMesh)) == NOSIGN)
2041  put(this->Vertex_Sign, target(g, _pMesh), MINUS);
2042  if(get(this->Vertex_Sign, target(opposite(g, _pMesh), _pMesh)) ==
2043  NOSIGN)
2044  put(this->Vertex_Sign, target(opposite(g, _pMesh), _pMesh), PLUS);
2045  }
2046  else if((type == 6) || (type == 7))
2047  {
2048  halfedge_descriptor g = Input_gate;
2049  g = prev(opposite(next(g, _pMesh), _pMesh), _pMesh);
2050  if(get(this->Vertex_Sign, target(g, _pMesh)) == NOSIGN)
2051  put(this->Vertex_Sign, target(g, _pMesh), PLUS);
2052  if(get(this->Vertex_Sign, target(opposite(g, _pMesh), _pMesh)) ==
2053  NOSIGN)
2054  put(this->Vertex_Sign,
2055  target(opposite(g, _pMesh), _pMesh),
2056  MINUS);
2057  }
2058 
2059  // Vertex Flags + Fill Halfedges queue.
2060  for(int i = 0; i < valence - 1; i++)
2061  {
2062  put(this->Vertex_Flag, target(Border_edges[i], _pMesh), CONQUERED);
2063  put(this->Vertex_Flag,
2064  target(opposite(Border_edges[i], _pMesh), _pMesh),
2065  CONQUERED);
2066 
2067  if((unsigned)i != (unsigned)Number_jump)
2068  Halfedges.push(Border_edges[i]);
2069  }
2070 
2071  if((this->IsColored) && (!this->IsOneColor))
2072  {
2073  Color_Unit Average_color;
2074 
2075  Color_Unit Color_0 =
2076  Get_Vertex_Color(opposite(Border_edges[0], _pMesh), _pMesh);
2077  Color_Unit Color_1 = Get_Vertex_Color(Border_edges[0], _pMesh);
2078  Color_Unit Color_2 = Get_Vertex_Color(Border_edges[1], _pMesh);
2079  Color_Unit Color_3 = Get_Vertex_Color(Border_edges[2], _pMesh);
2080  Average_color.c0 =
2081  (int)(Color_0.c0 + Color_1.c0 + Color_2.c0 + Color_3.c0) / 4.0;
2082  Average_color.c1 =
2083  (int)(Color_0.c1 + Color_1.c1 + Color_2.c1 + Color_3.c1) / 4.0;
2084  Average_color.c2 =
2085  (int)(Color_0.c2 + Color_1.c2 + Color_2.c2 + Color_3.c2) / 4.0;
2086 
2087  Color_Unit Color_diff = Removed_vertex_color - Average_color;
2088 
2089  this->InterVertexColor.push_front(Color_diff);
2090  }
2091 
2092 
2093  // encoding of geometry
2094  Point3d P0, P1, P2, P3;
2095 
2096  P0 = get(*_pm, target(opposite(Border_edges[0], _pMesh), _pMesh));
2097  P1 = get(*_pm, target(Border_edges[0], _pMesh));
2098  P2 = get(*_pm, target(Border_edges[1], _pMesh));
2099  P3 = get(*_pm, target(Border_edges[2], _pMesh));
2100 
2101  Point3d Barycenter((P0[0] + P1[0] + P2[0] + P3[0]) / 4,
2102  (P0[1] + P1[1] + P2[1] + P3[1]) / 4,
2103  (P0[2] + P1[2] + P2[2] + P3[2]) / 4);
2104 
2105  Point_Int BC = Change_Real_Int(Barycenter, Component_ID);
2106 
2107  halfedge_descriptor g = Input_gate;
2108  Vector normal = Normal_Patch(g, valence, _pMesh, _pm);
2109 
2110  Vector T2 = Vector(0.0, 0.0, 0.0);
2111  Vector T1 = Calculate_T1_T2(g, normal, T2, _pMesh, _pm);
2112 
2113  if(normal == Vector(0.0, 0.0, 0.0))
2114  {
2115  T1 = Vector(1, 0, 0);
2116  T2 = Vector(0, 1, 0);
2117  normal = Vector(0, 0, 1);
2118  }
2119 
2120  Point_Int Dist = Vertex_position - BC;
2121  Point_Int Frenet_Coordinates;
2122  if(this->Is_Bijection_Enabled)
2123  Frenet_Coordinates = Frenet_Rotation(Dist, T1, T2, normal);
2124  else
2125  Frenet_Coordinates = Dist;
2126 
2127  this->InterGeometry.push_front(Frenet_Coordinates);
2128  }
2129  }
2130 
2131  else // Border vertex can not be removed
2132  {
2133 #ifdef DBG_Decimation_Conquest
2134  std::cout << "marker #13" << std::endl;
2135 #endif
2136  Number_symbol++;
2137  this->InterConnectivity.push_front(4);
2138 
2139  put(this->Facet_Flag, face(h, _pMesh), CONQUERED);
2140  put(this->Vertex_Flag, target(next(h, _pMesh), _pMesh), CONQUERED);
2141 
2142  if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
2143  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
2144  MINUS))
2145  {
2146  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
2147  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), PLUS);
2148  }
2149  else if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
2150  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
2151  PLUS))
2152  {
2153  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
2154  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), PLUS);
2155  }
2156  else if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
2157  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
2158  PLUS))
2159  {
2160  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
2161  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), MINUS);
2162  }
2163  else if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
2164  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
2165  MINUS))
2166  {
2167  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
2168  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), PLUS);
2169  }
2170 
2171  if(!CGAL::is_border_edge(next(h, _pMesh), _pMesh))
2172  Halfedges.push(opposite(next(h, _pMesh), _pMesh));
2173 
2174  if(!CGAL::is_border_edge(prev(h, _pMesh), _pMesh))
2175  Halfedges.push(opposite(prev(h, _pMesh), _pMesh));
2176  }
2177  }
2178 
2179 
2180  // if its front face sholud be labelled as NULL PATCH
2181  else
2182  {
2183 #ifdef DBG_Decimation_Conquest
2184  std::cout << "marker #14" << std::endl;
2185 #endif
2186  // Enter symbol 'NULL PATCH' into the list of symbols
2187  this->InterConnectivity.push_front(4);
2188  Number_symbol++;
2189 
2190  // its front face is tagged CONQUERED
2191  put(this->Facet_Flag, face(h, _pMesh), CONQUERED);
2192  put(this->Vertex_Flag,
2193  target(next(h, _pMesh), _pMesh),
2194  CONQUERED);
2195 
2196  if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
2197  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) == MINUS))
2198  {
2199  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
2200  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), PLUS);
2201  }
2202  else if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
2203  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
2204  PLUS))
2205  {
2206  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
2207  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), PLUS);
2208  }
2209  else if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
2210  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
2211  PLUS))
2212  {
2213  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
2214  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), MINUS);
2215  }
2216  else if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
2217  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
2218  MINUS))
2219  {
2220  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
2221  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), PLUS);
2222  }
2223 
2224  // two other output gates are pused into the fifo queue.
2225  if(CGAL::is_border_edge(next(h, _pMesh), _pMesh) == false)
2226  Halfedges.push(opposite(next(h, _pMesh), _pMesh));
2227 
2228  if(CGAL::is_border_edge(prev(h, _pMesh), _pMesh) == false)
2229  Halfedges.push(opposite(prev(h, _pMesh), _pMesh));
2230  }
2231  }
2232  if((this->IsColored) && (!this->IsOneColor))
2233  {
2234 #ifdef DBG_Decimation_Conquest
2235  std::cout << "marker #15" << std::endl;
2236 #endif
2237  while(!this->InterVertexColor.empty())
2238  {
2239  Color_Unit Col = this->InterVertexColor.front();
2240  this->InterVertexColor.pop_front();
2241  this->VertexColor[Component_ID].push_front(Col);
2242  }
2243  }
2244  // InterConnectivity is the intermediate connectivity symbol container.
2245  // We put all symbols in the main container which is this->Connectivity
2246  while(!InterConnectivity.empty())
2247  {
2248 #ifdef DBG_Decimation_Conquest
2249  std::cout << "marker #16" << std::endl;
2250 #endif
2251  int Symbol = InterConnectivity.front();
2252  InterConnectivity.pop_front();
2253  this->Connectivity[Component_ID].push_front(Symbol);
2254  }
2255 
2256  // same operation than connectivity.
2257  while(!InterGeometry.empty())
2258  {
2259 #ifdef DBG_Decimation_Conquest
2260  std::cout << "marker #17" << std::endl;
2261 #endif
2262  Point_Int Geo = InterGeometry.front();
2263  InterGeometry.pop_front();
2264  this->Geometry[Component_ID].push_front(Geo);
2265  }
2266 
2267  this->NumberVertices[Component_ID].push_front(Number_vertices);
2268  this->NumberSymbol[Component_ID].push_front(Number_symbol);
2269 
2270  // if this decimation didn't remove any vertex, we should remove all
2271  // connectivity symbols. for that we store number of symbols.
2272  this->DumpSymbolDecimation = Number_symbol;
2273 
2274 
2275  return Number_vertices;
2276 }
2277 
2278 
2279 // Description : Decoding of the regulation conquest
2280 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
2281 void
2283  Un_Regulation(HalfedgeGraph &_pMesh,
2284  Arithmetic_Codec &Decoder,
2285  const int &Component_ID,
2286  PointMap *_pm,
2287  VertexColorMap *_v_cm)
2288 {
2289  Init(_pMesh);
2290 
2291  Adaptive_Data_Model Connectivity(2);
2292 
2293  halfedge_iterator hi = halfedges(_pMesh).first;
2294  std::queue< halfedge_descriptor > Halfedges;
2295 
2296  unsigned Qbit =
2297  this->Qbit[Component_ID] + this->NumberChangeQuantization[Component_ID];
2298 
2299  int Alpha_range = Decoder.get_bits(Qbit + 1);
2300  int Alpha_offset = Decoder.get_bits(Qbit + 1);
2301  int Gamma_range = Decoder.get_bits(Qbit + 1);
2302  int Gamma_offset = Decoder.get_bits(Qbit + 1);
2303 
2304  if(this->Smallest_Alpha < 0)
2305  Alpha_offset = Alpha_offset + this->Smallest_Alpha;
2306 
2307  if(this->Smallest_Gamma < 0)
2308  Gamma_offset = Gamma_offset + this->Smallest_Gamma;
2309 
2310  bool check_alpha = false;
2311  bool check_gamma = false;
2312 
2313  if((Alpha_range == 0) || (Alpha_range == 1))
2314  {
2315  check_alpha = true;
2316  Alpha_range = 2;
2317  }
2318 
2319  if((Gamma_range == 0) || (Gamma_range == 1))
2320  {
2321  check_gamma = true;
2322  Gamma_range = 2;
2323  }
2324 
2325  float Color_step = 0.0;
2326  if(this->NumberColorQuantization[Component_ID] == 0)
2327  Color_step = this->Color_Quantization_Step;
2328  else
2329  Color_step = this->Color_Quantization_Step *
2330  std::pow(2.0, this->NumberColorQuantization[Component_ID]);
2331 
2332  Adaptive_Data_Model alpha(Alpha_range);
2333  Adaptive_Data_Model gamma(Gamma_range);
2334 
2335  while(
2336  (get(this->vertex_Seed_Edge, target(*hi, _pMesh)) != 2 * Component_ID) ||
2337  (get(this->vertex_Seed_Edge, target(opposite(*hi, _pMesh), _pMesh)) !=
2338  2 * Component_ID + 1))
2339  hi++;
2340 
2341  put(this->Vertex_Flag, target(*hi, _pMesh), CONQUERED);
2342  put(this->Vertex_Flag, target(opposite(*hi, _pMesh), _pMesh), CONQUERED);
2343  Halfedges.push(*hi);
2344 
2346 
2347  while(!Halfedges.empty())
2348  {
2349  h = Halfedges.front();
2350  Halfedges.pop();
2351 
2352  if((get(this->Facet_Flag, face(h, _pMesh)) == CONQUERED) ||
2353  (get(this->Facet_Flag, face(h, _pMesh)) ==
2354  TO_BE_REMOVED)) // already visited.
2355  continue;
2356 
2357  // read connectivity information
2358  int valence = Decoder.decode(Connectivity) + 3;
2359 
2360  // if valence is 3, remove the front vertex.
2361  if(valence == 3)
2362  {
2363  halfedge_descriptor g = h;
2364 
2365  // Insertion of a vertex
2366  halfedge_descriptor pass = h;
2367 
2368  std::vector< Point3d > Vertices; // contains 1-ring and 2-rings vertices
2369  Point3d Barycenter = Barycenter_Patch_After_Removal(pass, 3, _pMesh, _pm);
2370  Point_Int BC = Change_Real_Int(Barycenter, Component_ID);
2371 
2372  Vector normal = Triangle_Normal(_pMesh, _pm, pass);
2373  Vector T2 = Vector(0.0, 0.0, 0.0);
2374  Vector T1 = Calculate_T1_T2(pass, normal, T2, _pMesh, _pm);
2375 
2376  if(T1 == Vector(0.0, 0.0, 0.0))
2377  {
2378  T1 = Vector(1, 0, 0);
2379  T2 = Vector(0, 1, 0);
2380  normal = Vector(0, 0, 1);
2381  }
2382 
2383  else if(normal == Vector(0.0, 0.0, 0.0))
2384  {
2385  T1 = Vector(1, 0, 0);
2386  T2 = Vector(0, 1, 0);
2387  normal = Vector(0, 0, 1);
2388  }
2389  else if(T2 == Vector(0.0, 0.0, 0.0))
2390  {
2391  T1 = Vector(1, 0, 0);
2392  T2 = Vector(0, 1, 0);
2393  normal = Vector(0, 0, 1);
2394  }
2395 
2396  Point_Int Frenet;
2397 
2398  if(check_alpha == false)
2399  {
2400  Frenet.x = Decoder.decode(alpha);
2401  Frenet.y = Decoder.decode(alpha);
2402  }
2403  else
2404  {
2405  Frenet.x = 0;
2406  Frenet.y = 0;
2407  }
2408 
2409  if(check_gamma == false)
2410  Frenet.z = Decoder.decode(gamma);
2411 
2412  else
2413  Frenet.z = 0;
2414 
2415  Frenet.x -= Alpha_offset;
2416  Frenet.y -= Alpha_offset;
2417  Frenet.z -= Gamma_offset;
2418 
2419  Point_Int Diff;
2420  if(this->Is_Bijection_Enabled)
2421  Diff = Inverse_Frenet_Rotation(Frenet, T1, T2, normal);
2422  else
2423  Diff = Frenet;
2424  Point_Int Center = BC + Diff;
2425 
2426  Point3d Center_vertex = this->Change_Int_Real(Center, Component_ID);
2427 
2428 
2429  // Assign the region number to inserted vertex
2430  halfedge_descriptor reg = h;
2431 
2432  int Selected_region = 500000;
2433  // int Number_vertices = 500000;
2434  std::vector< int > T_Bin;
2435  std::vector< int > T_Number;
2436 
2437  for(int i = 0; i < valence; i++)
2438  {
2439  int N1 = get(this->vertex_Region_Number, target(reg, _pMesh));
2440  bool Is_existed = false;
2441  for(unsigned int j = 0; j < T_Bin.size(); j++)
2442  {
2443  if(N1 == T_Bin[j])
2444  {
2445  T_Number[j]++;
2446  Is_existed = true;
2447  }
2448  }
2449  if(!Is_existed)
2450  {
2451  T_Bin.push_back(N1);
2452  T_Number.push_back(1);
2453  }
2454  reg = next(reg, _pMesh);
2455  }
2456  int Max = -5000;
2457  for(unsigned int i = 0; i < T_Number.size(); i++)
2458  {
2459  if(T_Number[i] > Max)
2460  Max = T_Number[i];
2461  }
2462  std::vector< int > T_possible_bin;
2463  for(unsigned int i = 0; i < T_Number.size(); i++)
2464  {
2465  if(T_Number[i] == Max)
2466  T_possible_bin.push_back(T_Bin[i]);
2467  }
2468 
2469  if(T_possible_bin.size() == 1)
2470  {
2471  Selected_region = T_possible_bin[0];
2472  }
2473  else
2474  {
2475  Selected_region = 5000;
2476  for(unsigned int i = 0; i < T_possible_bin.size(); i++)
2477  {
2478  if(T_possible_bin[i] < Selected_region)
2479  Selected_region = T_possible_bin[i];
2480  }
2481  }
2482 
2483 
2484  // Vertex insertion
2485  g = CGAL::Euler::add_center_vertex(g, _pMesh);
2486  init_vertex_attributes(target(g, _pMesh));
2487 
2488  put(*_pm, target(g, _pMesh), Center_vertex);
2489  put(this->vertex_Seed_Edge, target(g, _pMesh), -1);
2490 
2491  int RO = this->GlobalCountOperation - Decompress_count;
2492 
2493  put(this->vertex_Removal_Order, target(g, _pMesh), RO);
2494 
2495  put(this->vertex_Region_Number, target(g, _pMesh), Selected_region);
2496 
2497  if(Selected_region != -1)
2498  this->m_Number_Vertices_Per_Regions[Selected_region]++;
2499 
2500  // Vertex flags
2501  put(this->Vertex_Flag, target(g, _pMesh), CONQUERED);
2502  g = h;
2503  put(this->Facet_Flag, face(g, _pMesh), CONQUERED);
2504  g = next(g, _pMesh);
2505  g = prev(opposite(g, _pMesh), _pMesh);
2506  put(this->Vertex_Flag, target(opposite(g, _pMesh), _pMesh), CONQUERED);
2507  put(this->Facet_Flag, face(g, _pMesh), CONQUERED);
2508  if(!CGAL::is_border_edge(prev(g, _pMesh), _pMesh))
2509  {
2510  halfedge_descriptor h1 = opposite(prev(g, _pMesh), _pMesh);
2511  put(this->Facet_Flag, face(h1, _pMesh), CONQUERED);
2512  put(this->Vertex_Flag, target(next(h1, _pMesh), _pMesh), CONQUERED);
2513  if(!CGAL::is_border_edge(next(h1, _pMesh), _pMesh))
2514  Halfedges.push(opposite(next(h1, _pMesh), _pMesh));
2515  if(!CGAL::is_border_edge(prev(h1, _pMesh), _pMesh))
2516  Halfedges.push(opposite(prev(h1, _pMesh), _pMesh));
2517  }
2518  g = prev(opposite(g, _pMesh), _pMesh);
2519  put(this->Facet_Flag, face(g, _pMesh), CONQUERED);
2520  put(this->Vertex_Flag, target(opposite(g, _pMesh), _pMesh), CONQUERED);
2521  if(!CGAL::is_border_edge(prev(g, _pMesh), _pMesh))
2522  {
2523  halfedge_descriptor h2 = opposite(prev(g, _pMesh), _pMesh);
2524  put(this->Facet_Flag, face(h2, _pMesh), CONQUERED);
2525  put(this->Vertex_Flag, target(next(h2, _pMesh), _pMesh), CONQUERED);
2526  if(!CGAL::is_border_edge(next(h2, _pMesh), _pMesh))
2527  Halfedges.push(opposite(next(h2, _pMesh), _pMesh));
2528  if(!CGAL::is_border_edge(prev(h2, _pMesh), _pMesh))
2529  Halfedges.push(opposite(prev(h2, _pMesh), _pMesh));
2530  }
2531 
2532 
2533  if((this->IsColored) && (!this->IsOneColor))
2534  {
2535  g = h;
2536 
2537  Color_Unit Predicted_color;
2538 
2539  Predicted_color = Get_Average_Vertex_Color_Lee(g, valence, _pMesh);
2540 
2541  Color_Unit Color_difference;
2542  Color_difference.c0 =
2543  this->Decoder.decode(this->Color_0_Model) + this->Smallest_C0;
2544  Color_difference.c1 =
2545  this->Decoder.decode(this->Color_1_Model) + this->Smallest_C1;
2546  Color_difference.c2 =
2547  this->Decoder.decode(this->Color_2_Model) + this->Smallest_C2;
2548 
2549  Color_Unit CV = Predicted_color + Color_difference;
2550 
2551  put(this->vertex_color_int,
2552  target(next(g, _pMesh), _pMesh),
2553  Color_Unit(CV.c0, CV.c1, CV.c2));
2554 
2555  float LAB[3];
2556  LAB[0] = this->C0_Min + CV.c0 * Color_step;
2557  LAB[1] = this->C1_Min + CV.c1 * Color_step;
2558  LAB[2] = this->C2_Min + CV.c2 * Color_step;
2559 
2560  float RGB[3];
2561  LAB_To_RGB(LAB[0], LAB[1], LAB[2], RGB);
2562 
2563  typedef
2564  typename boost::property_traits< VertexColorMap >::value_type Color;
2565  put(*_v_cm,
2566  target(next(g, _pMesh), _pMesh),
2567  Color(RGB[0], RGB[1], RGB[2]));
2568  }
2569 
2570  if((this->IsColored) && (this->IsOneColor))
2571  {
2572  g = next(h, _pMesh);
2573  typedef
2574  typename boost::property_traits< VertexColorMap >::value_type Color;
2575  put(*_v_cm,
2576  target(g, _pMesh),
2577  Color(this->OnlyColor[0], this->OnlyColor[1], this->OnlyColor[2]));
2578  }
2579  }
2580 
2581  else
2582  {
2583  put(this->Facet_Flag, face(h, _pMesh), CONQUERED);
2584  put(this->Vertex_Flag, target(next(h, _pMesh), _pMesh), CONQUERED);
2585  if(!CGAL::is_border_edge(next(h, _pMesh), _pMesh))
2586  Halfedges.push(opposite(next(h, _pMesh), _pMesh));
2587  if(!CGAL::is_border_edge(prev(h, _pMesh), _pMesh))
2588  Halfedges.push(opposite(prev(h, _pMesh), _pMesh));
2589  }
2590  }
2591 }
2592 
2593 
2594 //#define DBG_Un_Decimation_Conquest
2595 
2596 // Description : Decoding function of decimation conquest
2597 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
2598 void
2600  Un_Decimation_Conquest(HalfedgeGraph &_pMesh,
2601  Arithmetic_Codec &Decoder,
2602  const int &Component_ID,
2603  PointMap *_pm,
2604  VertexColorMap *_v_cm)
2605 {
2606 #ifdef DBG_Un_Decimation_Conquest
2607  static unsigned int Un_Decimation_Conquest_call_cnt = 0;
2608  std::cout << "__func__"
2609  << " Un_Decimation_Conquest_call_cnt = "
2610  << ++Un_Decimation_Conquest_call_cnt << std::endl;
2611 #endif
2612 
2613  Init(_pMesh);
2614 
2615  int Number_connectivity_symbols;
2616  if(this->IsClosed[Component_ID])
2617  Number_connectivity_symbols = 5;
2618  else
2619  Number_connectivity_symbols = 7;
2620 
2621  Adaptive_Data_Model Connectivity(Number_connectivity_symbols);
2622 
2623  halfedge_iterator hi = halfedges(_pMesh).first;
2624  std::queue< halfedge_descriptor > Halfedges;
2625 
2626  unsigned Qbit =
2627  this->Qbit[Component_ID] + this->NumberChangeQuantization[Component_ID];
2628 
2629  int Alpha_range = Decoder.get_bits(Qbit + 1);
2630  int Alpha_offset = Decoder.get_bits(Qbit + 1);
2631  int Gamma_range = Decoder.get_bits(Qbit + 1);
2632  int Gamma_offset = Decoder.get_bits(Qbit + 1);
2633 
2634  if(this->Smallest_Alpha < 0)
2635  Alpha_offset = Alpha_offset + this->Smallest_Alpha;
2636 
2637  if(this->Smallest_Gamma < 0)
2638  Gamma_offset = Gamma_offset + this->Smallest_Gamma;
2639 
2640  bool check_alpha = false;
2641  bool check_gamma = false;
2642 
2643  if((Alpha_range == 0) || (Alpha_range == 1))
2644  {
2645  check_alpha = true;
2646  Alpha_range = 2;
2647  }
2648 
2649  if((Gamma_range == 0) || (Gamma_range == 1))
2650  {
2651  check_gamma = true;
2652  Gamma_range = 2;
2653  }
2654 
2655 
2656  float Color_step = 0.0;
2657  if(this->NumberColorQuantization[Component_ID] == 0)
2658  Color_step = this->Color_Quantization_Step;
2659  else
2660  Color_step = this->Color_Quantization_Step *
2661  std::pow(2.0, this->NumberColorQuantization[Component_ID]);
2662 
2663 
2664  Adaptive_Data_Model alpha(Alpha_range);
2665  Adaptive_Data_Model gamma(Gamma_range);
2666 
2667  while(
2668  (get(this->vertex_Seed_Edge, target(*hi, _pMesh)) != 2 * Component_ID) ||
2669  (get(this->vertex_Seed_Edge, target(opposite(*hi, _pMesh), _pMesh)) !=
2670  2 * Component_ID + 1))
2671  hi++;
2672 
2673  // Two vertices of seed edges are flaged CONQUERED
2674  put(this->Vertex_Flag, target(*hi, _pMesh), CONQUERED);
2675  put(this->Vertex_Flag, target(opposite(*hi, _pMesh), _pMesh), CONQUERED);
2676 
2677  // These vertices are also flages with sign flags for retriangulation
2678  put(this->Vertex_Sign, target(*hi, _pMesh), PLUS);
2679  put(this->Vertex_Sign, target(opposite(*hi, _pMesh), _pMesh), MINUS);
2680 
2681  // Two vertices of seed edges are flaged CONQUERED
2682  Halfedges.push(*hi);
2683 
2685 
2686 #ifdef DBG_Un_Decimation_Conquest
2687  int dbg_loop_counter = 0;
2688 #endif
2689 
2690  while(!Halfedges.empty())
2691  {
2692 #ifdef DBG_Un_Decimation_Conquest
2693  std::cout << __func__ << " marker #2"
2694  << " loop " << ++dbg_loop_counter << std::endl;
2695  std::cout << __func__ << " Halfedges.size()=" << Halfedges.size()
2696  << std::endl;
2697 #endif
2698 
2699  h = Halfedges.front();
2700  Halfedges.pop();
2701 
2702 #ifdef DBG_Un_Decimation_Conquest
2703  if(Un_Decimation_Conquest_call_cnt == 2)
2704  print_halfedge("h", h, _pMesh, _pm);
2705 #endif
2706 
2707  unsigned int valence = 0, type = 0; // define type of retriangulation
2708 
2709  if(CGAL::is_border(h, _pMesh) == true)
2710  continue;
2711 
2712  // if its front face is not tagged CONQUERED nor TO_BE_REMOVED
2713  if((get(this->Facet_Flag, face(h, _pMesh)) == CONQUERED) ||
2714  (get(this->Facet_Flag, face(h, _pMesh)) == TO_BE_REMOVED))
2715  continue;
2716 
2717  valence = Decoder.decode(Connectivity) + 3;
2718 
2719  // if its front vertex is free
2720  if((valence >= 3) && (valence <= 6))
2721  {
2722  type = Find_Type(_pMesh, h, valence);
2723 
2724  // remove the front vertex if its removal does not viloate the manifold
2725  // property
2726  halfedge_descriptor pass = h;
2727  halfedge_descriptor g = h;
2728 
2729  Vector normal = Normal_Patch(pass, valence, _pMesh, _pm);
2730  Vector T2 = Vector(0.0, 0.0, 0.0);
2731  Vector T1 = Calculate_T1_T2(h, normal, T2, _pMesh, _pm);
2732 
2733  if(T1 == Vector(0.0, 0.0, 0.0))
2734  {
2735  T1 = Vector(1, 0, 0);
2736  T2 = Vector(0, 1, 0);
2737  normal = Vector(0, 0, 1);
2738  }
2739 
2740  else if(normal == Vector(0.0, 0.0, 0.0))
2741  {
2742  T1 = Vector(1, 0, 0);
2743  T2 = Vector(0, 1, 0);
2744  normal = Vector(0, 0, 1);
2745  }
2746  else if(T2 == Vector(0.0, 0.0, 0.0))
2747  {
2748  T1 = Vector(1, 0, 0);
2749  T2 = Vector(0, 1, 0);
2750  normal = Vector(0, 0, 1);
2751  }
2752 
2753  // remove edges to re_find polygon and (check. and attribute sign flag.)
2754  bool Check_Validity = Remove_Edges(_pMesh, g, type);
2755  Check_Validity = false;
2756 
2757  // Check_Validity = false;// * * * * * * * * * * *////
2758  if(Check_Validity == false)
2759  {
2760 #ifdef DBG_Un_Decimation_Conquest
2761  if(Un_Decimation_Conquest_call_cnt == 9 && dbg_loop_counter == 1044)
2762  bool dbg_dummy = true; // just to be able to set a breakpoint
2763 #endif
2764  g = h;
2765  halfedge_descriptor pass = h;
2766 
2767  std::vector< Point3d > Vertices; // contains 1-ring and 2-ring vertices;
2768  Point3d Barycenter =
2769  Barycenter_Patch_After_Removal(pass, valence, _pMesh, _pm);
2770  Point_Int BC = Change_Real_Int(Barycenter, Component_ID);
2771 
2772  Point_Int Frenet;
2773  if(check_alpha == false)
2774  {
2775  Frenet.x = Decoder.decode(alpha);
2776  Frenet.y = Decoder.decode(alpha);
2777  }
2778  else if(check_alpha == true)
2779  {
2780  Frenet.x = 0;
2781  Frenet.y = 0;
2782  }
2783  if(check_gamma == false)
2784  Frenet.z = Decoder.decode(gamma);
2785  else if(check_gamma == true)
2786  Frenet.z = 0;
2787 
2788  Frenet.x -= Alpha_offset;
2789  Frenet.y -= Alpha_offset;
2790  Frenet.z -= Gamma_offset;
2791 
2792  Point_Int Diff;
2793  if(this->Is_Bijection_Enabled)
2794  Diff = Inverse_Frenet_Rotation(Frenet, T1, T2, normal);
2795  else
2796  Diff = Frenet;
2797  /*Point_Int Center = BC + Diff;
2798  Point_Int Diff = Inverse_Frenet_Rotation(Frenet, T1, T2, normal);*/
2799 
2800  Point_Int Center = BC + Diff;
2801 
2802  Point3d Center_vertex = this->Change_Int_Real(Center, Component_ID);
2803 
2804  // Assign the region number to inserted vertex
2805  halfedge_descriptor reg = h;
2806 
2807  int Selected_region = 500000;
2808  // int Number_vertices = 500000;
2809  std::vector< int > T_Bin;
2810  std::vector< int > T_Number;
2811 
2812  for(int i = 0; i < (int)valence; i++)
2813  {
2814  int N1 = get(this->vertex_Region_Number, target(reg, _pMesh));
2815  bool Is_existed = false;
2816  for(unsigned int j = 0; j < T_Bin.size(); j++)
2817  {
2818  if(N1 == T_Bin[j])
2819  {
2820  T_Number[j]++;
2821  Is_existed = true;
2822  }
2823  }
2824  if(!Is_existed)
2825  {
2826  T_Bin.push_back(N1);
2827  T_Number.push_back(1);
2828  }
2829  reg = next(reg, _pMesh);
2830  }
2831  int Max = -5000;
2832  for(unsigned int i = 0; i < T_Number.size(); i++)
2833  {
2834  if(T_Number[i] > Max)
2835  Max = T_Number[i];
2836  }
2837  std::vector< int > T_possible_bin;
2838  for(unsigned int i = 0; i < T_Number.size(); i++)
2839  {
2840  if(T_Number[i] == Max)
2841  T_possible_bin.push_back(T_Bin[i]);
2842  }
2843 
2844  if(T_possible_bin.size() == 1)
2845  {
2846  Selected_region = T_possible_bin[0];
2847  }
2848  else
2849  {
2850  Selected_region = 5000;
2851  for(unsigned int i = 0; i < T_possible_bin.size(); i++)
2852  {
2853  if(T_possible_bin[i] < Selected_region)
2854  Selected_region = T_possible_bin[i];
2855  }
2856  }
2857 
2858  g = CGAL::Euler::add_center_vertex(g, _pMesh);
2859  init_vertex_attributes(target(g, _pMesh));
2860  put(*_pm, target(g, _pMesh), Center_vertex);
2861 #ifdef DBG_Un_Decimation_Conquest
2862  std::cout << __func__ << " marker PM#1"
2863  << " loop " << dbg_loop_counter << std::endl;
2864  std::cout << __func__
2865  << " vertex=" << vertex_to_string(target(g, _pMesh), _pm)
2866  << std::endl;
2867 #endif
2868 
2869  put(this->vertex_Region_Number, target(g, _pMesh), Selected_region);
2870 
2871  if(Selected_region != -1)
2872  this->m_Number_Vertices_Per_Regions[Selected_region]++;
2873 
2874  int RO = this->GlobalCountOperation - this->Decompress_count;
2875  put(this->vertex_Removal_Order, target(g, _pMesh), RO);
2876 
2877  put(this->Vertex_Flag, target(g, _pMesh), CONQUERED);
2878 
2879  g = h;
2880  put(this->Facet_Flag, face(g, _pMesh), TO_BE_REMOVED);
2881  put(this->Vertex_Flag, target(g, _pMesh), CONQUERED);
2882  put(this->Vertex_Flag, target(opposite(g, _pMesh), _pMesh), CONQUERED);
2883 
2884  for(unsigned int k = 0; k < (valence - 1); k++)
2885  {
2886  g = next(opposite(next(g, _pMesh), _pMesh), _pMesh);
2887  put(this->Facet_Flag, face(g, _pMesh), TO_BE_REMOVED);
2888  put(this->Vertex_Flag, target(g, _pMesh), CONQUERED);
2889  put(this->Vertex_Flag,
2890  target(opposite(g, _pMesh), _pMesh),
2891  CONQUERED);
2892  if(CGAL::is_border_edge(g, _pMesh) == false)
2893  Halfedges.push(opposite(g, _pMesh));
2894  }
2895 
2896  put(this->vertex_Seed_Edge, target(next(g, _pMesh), _pMesh), -1);
2897 
2898  if((this->IsColored) && (!this->IsOneColor))
2899  {
2900  g = h;
2901 
2902  Color_Unit Predicted_color;
2903  Predicted_color = Get_Average_Vertex_Color_Lee(g, valence, _pMesh);
2904 
2905  Color_Unit Color_difference;
2906  Color_difference.c0 =
2907  this->Decoder.decode(this->Color_0_Model) + this->Smallest_C0;
2908  Color_difference.c1 =
2909  this->Decoder.decode(this->Color_1_Model) + this->Smallest_C1;
2910  Color_difference.c2 =
2911  this->Decoder.decode(this->Color_2_Model) + this->Smallest_C2;
2912 
2913  Color_Unit CV = Predicted_color + Color_difference;
2914 
2915  put(this->vertex_color_int,
2916  target(next(g, _pMesh), _pMesh),
2917  Color_Unit(CV.c0, CV.c1, CV.c2));
2918 
2919  float LAB[3];
2920  LAB[0] = this->C0_Min + CV.c0 * Color_step;
2921  LAB[1] = this->C1_Min + CV.c1 * Color_step;
2922  LAB[2] = this->C2_Min + CV.c2 * Color_step;
2923 
2924  float RGB[3];
2925  LAB_To_RGB(LAB[0], LAB[1], LAB[2], RGB);
2926 
2927  typedef typename boost::property_traits< VertexColorMap >::value_type
2928  Color;
2929  put(*_v_cm,
2930  target(next(g, _pMesh), _pMesh),
2931  Color(RGB[0], RGB[1], RGB[2]));
2932 
2933 #ifdef DBG_Un_Decimation_Conquest
2934  std::cout << __func__ << " marker #3"
2935  << " loop " << dbg_loop_counter << std::endl;
2936  std::cout << __func__ << " vertex="
2937  << vertex_to_string(target(next(g, _pMesh), _pMesh), _pm)
2938  << std::endl;
2939  std::cout << __func__ << " Color=" << RGB[0] << " " << RGB[1] << " "
2940  << RGB[2] << std::endl;
2941 #endif
2942 
2943  //#endif
2944  }
2945  if((this->IsColored) && (this->IsOneColor))
2946  {
2947  g = next(h, _pMesh);
2948  typedef typename boost::property_traits< VertexColorMap >::value_type
2949  Color;
2950  put(*_v_cm,
2951  target(g, _pMesh),
2952  Color(
2953  this->OnlyColor[0], this->OnlyColor[1], this->OnlyColor[2]));
2954 
2955 #ifdef DBG_Un_Decimation_Conquest
2956  std::cout << __func__ << " marker #4"
2957  << " loop " << dbg_loop_counter << std::endl;
2958  std::cout << __func__
2959  << " vertex=" << vertex_to_string(target(g, _pMesh), _pm)
2960  << std::endl;
2961  std::cout << __func__ << " Color=" << this->OnlyColor[0] << " "
2962  << this->OnlyColor[1] << " " << this->OnlyColor[2]
2963  << std::endl;
2964 #endif
2965  }
2966  }
2967  }
2968  // In case of border edge.
2969  else if((valence == 8) || (valence == 9))
2970  {
2971 
2972  type = Find_Type(_pMesh, h, valence - 5);
2973 
2974  halfedge_descriptor pass = h;
2975 
2976  Vector normal = Normal_Patch(pass, valence - 5, _pMesh, _pm);
2977  Vector T2 = Vector(0.0, 0.0, 0.0);
2978  Vector T1 = Calculate_T1_T2(h, normal, T2, _pMesh, _pm);
2979 
2980  if(normal == Vector(0.0, 0.0, 0.0))
2981  {
2982  T1 = Vector(1, 0, 0);
2983  T2 = Vector(0, 1, 0);
2984  normal = Vector(0, 0, 1);
2985  }
2986 
2987  pass = h;
2988  Point_Int Frenet;
2989  if(check_alpha == false)
2990  {
2991  Frenet.x = Decoder.decode(alpha);
2992  Frenet.y = Decoder.decode(alpha);
2993  }
2994  else if(check_alpha == true)
2995  {
2996  Frenet.x = 0;
2997  Frenet.y = 0;
2998  }
2999 
3000  if(check_gamma == false)
3001  Frenet.z = Decoder.decode(gamma);
3002  else if(check_gamma == true)
3003  Frenet.z = 0;
3004 
3005  Frenet.x -= Alpha_offset;
3006  Frenet.y -= Alpha_offset;
3007  Frenet.z -= Gamma_offset;
3008 
3009  Point_Int Diff;
3010  if(this->Is_Bijection_Enabled)
3011  Diff = Inverse_Frenet_Rotation(Frenet, T1, T2, normal);
3012  else
3013  Diff = Frenet;
3014 
3015  // Point_Int Center = BC + Diff;
3016 
3017  // Point_Int Diff = Inverse_Frenet_Rotation(Frenet,T1,T2,normal);
3018  halfedge_descriptor g = h;
3019 
3020  Color_Unit Predicted_color;
3021  if((this->IsColored) && (!this->IsOneColor))
3022  {
3023  Predicted_color.c0 =
3024  Decoder.decode(this->Color_0_Model) + this->Smallest_C0;
3025  Predicted_color.c1 =
3026  Decoder.decode(this->Color_1_Model) + this->Smallest_C1;
3027  Predicted_color.c2 =
3028  Decoder.decode(this->Color_2_Model) + this->Smallest_C2;
3029  }
3030 
3031  // border edge with valence == 3
3032  if(valence == 8)
3033  {
3034  Point3d Barycenter =
3035  Barycenter_Patch_After_Removal(pass, 3, _pMesh, _pm);
3036  Point_Int BC = Change_Real_Int(Barycenter, Component_ID);
3037 
3038  Point_Int Center = BC + Diff;
3039  Point3d Center_vertex = this->Change_Int_Real(Center, Component_ID);
3040 
3041  //#ifdef PREDICTION_METHOD
3042  Color_Unit Average_color;
3043  if((this->IsColored) && (!this->IsOneColor))
3044  {
3045  Average_color = Get_Average_Vertex_Color_After_Removal(g, 3, _pMesh);
3046  }
3047  //#endif
3048 
3049  std::vector< halfedge_descriptor > Border_edges;
3050  int Number_jump = 0;
3051 
3052  if(CGAL::is_border_edge(next(g, _pMesh), _pMesh))
3053  Number_jump = 0;
3054  if(CGAL::is_border_edge(prev(g, _pMesh), _pMesh))
3055  {
3056  Number_jump = 1;
3057  g = next(g, _pMesh);
3058  }
3059 
3060  Border_edges.push_back(opposite(g, _pMesh));
3061 
3062  g = prev(g, _pMesh);
3063  Border_edges.push_back(opposite(g, _pMesh));
3064 
3065  CGAL::Euler::remove_face(g, _pMesh);
3066 
3067  halfedge_descriptor Prev_edge =
3068  prev(opposite(Border_edges[1], _pMesh), _pMesh);
3069 
3070  // g points the new vertex
3072  Prev_edge, opposite(Border_edges[1], _pMesh), _pMesh);
3073  init_vertex_attributes(target(g, _pMesh));
3074  put(*_pm, target(g, _pMesh), Center_vertex);
3075 #ifdef DBG_Un_Decimation_Conquest
3076  std::cout << __func__ << " marker PM#2"
3077  << " loop " << dbg_loop_counter << std::endl;
3078  std::cout << __func__
3079  << " vertex=" << vertex_to_string(target(g, _pMesh), _pm)
3080  << std::endl;
3081 #endif
3082  put(this->Vertex_Flag, target(g, _pMesh), CONQUERED);
3083 
3084  //#ifdef PREDICTION_METHOD
3085  Color_Unit CV;
3086  if((this->IsColored) && (!this->IsOneColor))
3087  {
3088  CV = Average_color + Predicted_color;
3089 
3090  put(this->vertex_color_int,
3091  target(g, _pMesh),
3092  Color_Unit(CV.c0, CV.c1, CV.c2));
3093 
3094  float LAB[3];
3095  LAB[0] = this->C0_Min + CV.c0 * this->Color_Quantization_Step;
3096  LAB[1] = this->C1_Min + CV.c1 * this->Color_Quantization_Step;
3097  LAB[2] = this->C2_Min + CV.c2 * this->Color_Quantization_Step;
3098 
3099  float RGB[3];
3100  LAB_To_RGB(LAB[0], LAB[1], LAB[2], RGB);
3101 
3102  typedef typename boost::property_traits< VertexColorMap >::value_type
3103  Color;
3104  put(*_v_cm, target(g, _pMesh), Color(RGB[0], RGB[1], RGB[2]));
3105 
3106 #ifdef DBG_Un_Decimation_Conquest
3107  std::cout << __func__ << " marker #5"
3108  << " loop " << dbg_loop_counter << std::endl;
3109  std::cout << __func__
3110  << " vertex=" << vertex_to_string(target(g, _pMesh), _pm)
3111  << std::endl;
3112  std::cout << __func__ << " Color=" << RGB[0] << " " << RGB[1] << " "
3113  << RGB[2] << std::endl;
3114 #endif
3115  }
3116  //#endif
3117 
3118  if((this->IsColored) && (this->IsOneColor))
3119  {
3120  typedef typename boost::property_traits< VertexColorMap >::value_type
3121  Color;
3122  put(*_v_cm,
3123  target(g, _pMesh),
3124  Color(
3125  this->OnlyColor[0], this->OnlyColor[1], this->OnlyColor[2]));
3126 
3127 #ifdef DBG_Un_Decimation_Conquest
3128  std::cout << __func__ << " marker #6"
3129  << " loop " << dbg_loop_counter << std::endl;
3130  std::cout << __func__
3131  << " vertex=" << vertex_to_string(target(g, _pMesh), _pm)
3132  << std::endl;
3133  std::cout << __func__ << " Color=" << this->OnlyColor[0] << " "
3134  << this->OnlyColor[1] << " " << this->OnlyColor[2]
3135  << std::endl;
3136 #endif
3137  }
3138 
3139 
3140  Prev_edge = next(Prev_edge, _pMesh);
3141  CGAL::Euler::add_face_to_border(
3142  Prev_edge, opposite(Border_edges[0], _pMesh), _pMesh);
3143 
3144  halfedge_descriptor Tag_handle;
3145 
3146  if(Number_jump == 0)
3147  Tag_handle = Border_edges[1];
3148  if(Number_jump == 1)
3149  Tag_handle = opposite(Border_edges[0], _pMesh);
3150  put(this->Vertex_Flag, target(Tag_handle, _pMesh), CONQUERED);
3151 
3152  if((type == 1) || (type == 2) || (type == 4))
3153  {
3154  if(get(this->Vertex_Sign, target(Tag_handle, _pMesh)) == NOSIGN)
3155  put(this->Vertex_Sign, target(Tag_handle, _pMesh), PLUS);
3156  }
3157  else if(type == 3)
3158  {
3159  if(get(this->Vertex_Sign, target(Tag_handle, _pMesh)) == NOSIGN)
3160  put(this->Vertex_Sign, target(Tag_handle, _pMesh), MINUS);
3161  }
3162  for(int i = 0; i < 2; i++)
3163  {
3164  put(this->Facet_Flag,
3165  face(opposite(Border_edges[i], _pMesh), _pMesh),
3166  CONQUERED);
3167  if(i != Number_jump)
3168  Halfedges.push(Border_edges[i]);
3169  }
3170  }
3171  // border edge with valence == 4
3172  else if(valence == 9)
3173  {
3174  int Number_jump = -1;
3175  std::vector< halfedge_descriptor > Border_edges;
3176 
3177  if((type == 5) || (type == 8))
3178  {
3179  // jump == 0;
3180  if(CGAL::is_border_edge(next(g, _pMesh), _pMesh))
3181  {
3182  Number_jump = 0;
3183 
3184  Border_edges.push_back(opposite(g, _pMesh));
3185 
3186  Border_edges.push_back(opposite(
3187  prev(opposite(prev(g, _pMesh), _pMesh), _pMesh), _pMesh));
3188  Border_edges.push_back(opposite(
3189  next(opposite(prev(g, _pMesh), _pMesh), _pMesh), _pMesh));
3190 
3191  CGAL::Euler::remove_face(opposite(Border_edges[0], _pMesh), _pMesh);
3192  CGAL::Euler::remove_face(opposite(Border_edges[1], _pMesh), _pMesh);
3193  }
3194 
3195  // jump == 1;
3196  else if(CGAL::is_border_edge(
3197  next(opposite(prev(g, _pMesh), _pMesh), _pMesh), _pMesh))
3198  {
3199  Number_jump = 1;
3200 
3201  Border_edges.push_back(opposite(next(g, _pMesh), _pMesh));
3202  Border_edges.push_back(opposite(g, _pMesh));
3203  Border_edges.push_back(opposite(
3204  prev(opposite(prev(g, _pMesh), _pMesh), _pMesh), _pMesh));
3205 
3206  CGAL::Euler::remove_face(opposite(Border_edges[2], _pMesh), _pMesh);
3207  CGAL::Euler::remove_face(opposite(Border_edges[0], _pMesh), _pMesh);
3208  }
3209 
3210  // jump == 2;
3211  else
3212  {
3213  Number_jump = 2;
3214 
3215  Border_edges.push_back(opposite(
3216  next(opposite(prev(g, _pMesh), _pMesh), _pMesh), _pMesh));
3217  Border_edges.push_back(opposite(next(g, _pMesh), _pMesh));
3218  Border_edges.push_back(opposite(g, _pMesh));
3219 
3220  CGAL::Euler::remove_face(opposite(Border_edges[0], _pMesh), _pMesh);
3221  CGAL::Euler::remove_face(opposite(Border_edges[1], _pMesh), _pMesh);
3222  }
3223  }
3224  else
3225  {
3226  if(CGAL::is_border_edge(prev(g, _pMesh), _pMesh))
3227  {
3228  Number_jump = 2;
3229 
3230  Border_edges.push_back(opposite(
3231  prev(opposite(next(g, _pMesh), _pMesh), _pMesh), _pMesh));
3232  Border_edges.push_back(opposite(
3233  next(opposite(next(g, _pMesh), _pMesh), _pMesh), _pMesh));
3234  Border_edges.push_back(opposite(g, _pMesh));
3235 
3236  CGAL::Euler::remove_face(opposite(Border_edges[2], _pMesh), _pMesh);
3237  CGAL::Euler::remove_face(opposite(Border_edges[1], _pMesh), _pMesh);
3238  }
3239 
3240  else if(CGAL::is_border_edge(
3241  prev(opposite(next(g, _pMesh), _pMesh), _pMesh), _pMesh))
3242  {
3243  Number_jump = 1;
3244 
3245  Border_edges.push_back(opposite(
3246  next(opposite(next(g, _pMesh), _pMesh), _pMesh), _pMesh));
3247  Border_edges.push_back(opposite(g, _pMesh));
3248  Border_edges.push_back(opposite(prev(g, _pMesh), _pMesh));
3249 
3250  CGAL::Euler::remove_face(opposite(Border_edges[0], _pMesh), _pMesh);
3251  CGAL::Euler::remove_face(opposite(Border_edges[1], _pMesh), _pMesh);
3252  }
3253  else
3254  {
3255  Number_jump = 0;
3256 
3257  Border_edges.push_back(opposite(g, _pMesh));
3258  Border_edges.push_back(opposite(prev(g, _pMesh), _pMesh));
3259  Border_edges.push_back(opposite(
3260  prev(opposite(next(g, _pMesh), _pMesh), _pMesh), _pMesh));
3261 
3262  CGAL::Euler::remove_face(opposite(Border_edges[2], _pMesh), _pMesh);
3263  CGAL::Euler::remove_face(opposite(Border_edges[1], _pMesh), _pMesh);
3264  }
3265  }
3266 
3267  g = h;
3268 
3269  Point3d p0 = get(*_pm, target(Border_edges[0], _pMesh));
3270  Point3d p1 =
3271  get(*_pm, target(opposite(Border_edges[0], _pMesh), _pMesh));
3272  Point3d p2 = get(*_pm, target(Border_edges[1], _pMesh));
3273  Point3d p3 = get(*_pm, target(Border_edges[2], _pMesh));
3274 
3275  Point3d Barycenter((p0[0] + p1[0] + p2[0] + p3[0]) / 4.,
3276  (p0[1] + p1[1] + p2[1] + p3[1]) / 4.,
3277  (p0[2] + p1[2] + p2[2] + p3[2]) / 4.);
3278 
3279  Point_Int BC = Change_Real_Int(Barycenter, Component_ID);
3280 
3281  Point_Int Center = BC + Diff;
3282 
3283  Point3d Center_vertex = this->Change_Int_Real(Center, Component_ID);
3284 
3285  // to create the new facets
3286  halfedge_descriptor Prev_edge =
3287  prev(opposite(Border_edges[2], _pMesh), _pMesh);
3289  Prev_edge, opposite(Border_edges[2], _pMesh), _pMesh);
3290  init_vertex_attributes(target(g, _pMesh));
3291  put(*_pm, target(g, _pMesh), Center_vertex);
3292 #ifdef DBG_Un_Decimation_Conquest
3293  std::cout << __func__ << " marker PM#3"
3294  << " loop " << dbg_loop_counter << std::endl;
3295  std::cout << __func__
3296  << " vertex=" << vertex_to_string(target(g, _pMesh), _pm)
3297  << std::endl;
3298 #endif
3299 
3300  //#ifdef PREDICTION_METHOD
3301  Color_Unit CV;
3302  if((this->IsColored) && (!this->IsOneColor))
3303  {
3304  Color_Unit Average_color;
3305 
3306  Color_Unit Color_0 =
3307  Get_Vertex_Color(opposite(Border_edges[0], _pMesh), _pMesh);
3308  Color_Unit Color_1 = Get_Vertex_Color(Border_edges[0], _pMesh);
3309  Color_Unit Color_2 = Get_Vertex_Color(Border_edges[1], _pMesh);
3310  Color_Unit Color_3 = Get_Vertex_Color(Border_edges[2], _pMesh);
3311 
3312  Average_color.c0 =
3313  (int)(Color_0.c0 + Color_1.c0 + Color_2.c0 + Color_3.c0) / 4.0;
3314  Average_color.c1 =
3315  (int)(Color_0.c1 + Color_1.c1 + Color_2.c1 + Color_3.c1) / 4.0;
3316  Average_color.c2 =
3317  (int)(Color_0.c2 + Color_1.c2 + Color_2.c2 + Color_3.c2) / 4.0;
3318 
3319  CV = Average_color + Predicted_color;
3320 
3321  put(this->vertex_color_int,
3322  target(g, _pMesh),
3323  Color_Unit(CV.c0, CV.c1, CV.c2));
3324 
3325  float LAB[3];
3326  LAB[0] = this->C0_Min + CV.c0 * this->Color_Quantization_Step;
3327  LAB[1] = this->C1_Min + CV.c1 * this->Color_Quantization_Step;
3328  LAB[2] = this->C2_Min + CV.c2 * this->Color_Quantization_Step;
3329 
3330  float RGB[3];
3331  LAB_To_RGB(LAB[0], LAB[1], LAB[2], RGB);
3332 
3333  typedef typename boost::property_traits< VertexColorMap >::value_type
3334  Color;
3335  put(*_v_cm, target(g, _pMesh), Color(RGB[0], RGB[1], RGB[2]));
3336 
3337 #ifdef DBG_Un_Decimation_Conquest
3338  std::cout << __func__ << " marker #7"
3339  << " loop " << dbg_loop_counter << std::endl;
3340  std::cout << __func__
3341  << " vertex=" << vertex_to_string(target(g, _pMesh), _pm)
3342  << std::endl;
3343  std::cout << __func__ << " Color=" << RGB[0] << " " << RGB[1] << " "
3344  << RGB[2] << std::endl;
3345 #endif
3346  }
3347  //#endif
3348  if((this->IsColored) && (this->IsOneColor))
3349  {
3350  typedef typename boost::property_traits< VertexColorMap >::value_type
3351  Color;
3352  put(*_v_cm,
3353  target(g, _pMesh),
3354  Color(
3355  this->OnlyColor[0], this->OnlyColor[1], this->OnlyColor[2]));
3356 
3357 #ifdef DBG_Un_Decimation_Conquest
3358  std::cout << __func__ << " marker #8"
3359  << " loop " << dbg_loop_counter << std::endl;
3360  std::cout << __func__
3361  << " vertex=" << vertex_to_string(target(g, _pMesh), _pm)
3362  << std::endl;
3363  std::cout << __func__ << " Color=" << this->OnlyColor[0] << " "
3364  << this->OnlyColor[1] << " " << this->OnlyColor[2]
3365  << std::endl;
3366 #endif
3367  }
3368  Prev_edge = next(Prev_edge, _pMesh);
3369  CGAL::Euler::add_face_to_border(
3370  Prev_edge, opposite(Border_edges[1], _pMesh), _pMesh);
3371  CGAL::Euler::add_face_to_border(
3372  Prev_edge, opposite(Border_edges[0], _pMesh), _pMesh);
3373 
3374 
3375  // vertex_tag
3376  if(Number_jump == 0)
3377  {
3378  if((type == 5) || (type == 8))
3379  {
3380  if(get(this->Vertex_Sign, target(Border_edges[2], _pMesh)) ==
3381  NOSIGN)
3382  put(this->Vertex_Sign, target(Border_edges[2], _pMesh), PLUS);
3383  if(get(this->Vertex_Sign,
3384  target(opposite(Border_edges[2], _pMesh), _pMesh)) == NOSIGN)
3385  put(this->Vertex_Sign,
3386  target(opposite(Border_edges[2], _pMesh), _pMesh),
3387  MINUS);
3388  }
3389  else
3390  {
3391  if(get(this->Vertex_Sign, target(Border_edges[2], _pMesh)) ==
3392  NOSIGN)
3393  put(this->Vertex_Sign, target(Border_edges[2], _pMesh), MINUS);
3394  if(get(this->Vertex_Sign,
3395  target(opposite(Border_edges[2], _pMesh), _pMesh)) == NOSIGN)
3396  put(this->Vertex_Sign,
3397  target(opposite(Border_edges[2], _pMesh), _pMesh),
3398  PLUS);
3399  }
3400  }
3401 
3402  else if(Number_jump == 1)
3403  {
3404  if((type == 5) || (type == 8))
3405  {
3406  if(get(this->Vertex_Sign, target(Border_edges[2], _pMesh)) ==
3407  NOSIGN)
3408  put(this->Vertex_Sign, target(Border_edges[2], _pMesh), MINUS);
3409  if(get(this->Vertex_Sign,
3410  target(opposite(Border_edges[0], _pMesh), _pMesh)) == NOSIGN)
3411  put(this->Vertex_Sign,
3412  target(opposite(Border_edges[0], _pMesh), _pMesh),
3413  PLUS);
3414  }
3415  else
3416  {
3417  if(get(this->Vertex_Sign, target(Border_edges[2], _pMesh)) ==
3418  NOSIGN)
3419  put(this->Vertex_Sign, target(Border_edges[2], _pMesh), PLUS);
3420  if(get(this->Vertex_Sign,
3421  target(opposite(Border_edges[0], _pMesh), _pMesh)) == NOSIGN)
3422  put(this->Vertex_Sign,
3423  target(opposite(Border_edges[0], _pMesh), _pMesh),
3424  MINUS);
3425  }
3426  }
3427  else // jump == 2
3428  {
3429  if((type == 5) || (type == 8))
3430  {
3431  if(get(this->Vertex_Sign, target(Border_edges[0], _pMesh)) ==
3432  NOSIGN)
3433  put(this->Vertex_Sign, target(Border_edges[0], _pMesh), PLUS);
3434  if(get(this->Vertex_Sign,
3435  target(opposite(Border_edges[0], _pMesh), _pMesh)) == NOSIGN)
3436  put(this->Vertex_Sign,
3437  target(opposite(Border_edges[0], _pMesh), _pMesh),
3438  MINUS);
3439  }
3440  else
3441  {
3442  if(get(this->Vertex_Sign, target(Border_edges[0], _pMesh)) ==
3443  NOSIGN)
3444  put(this->Vertex_Sign, target(Border_edges[0], _pMesh), MINUS);
3445  if(get(this->Vertex_Sign,
3446  target(opposite(Border_edges[0], _pMesh), _pMesh)) == NOSIGN)
3447  put(this->Vertex_Sign,
3448  target(opposite(Border_edges[0], _pMesh), _pMesh),
3449  PLUS);
3450  }
3451  }
3452 
3453  for(int i = 0; i < 3; i++)
3454  {
3455  put(this->Facet_Flag,
3456  face(opposite(Border_edges[i], _pMesh), _pMesh),
3457  CONQUERED);
3458 
3459  put(this->Vertex_Flag, target(Border_edges[i], _pMesh), CONQUERED);
3460  put(this->Vertex_Flag,
3461  target(opposite(Border_edges[i], _pMesh), _pMesh),
3462  CONQUERED);
3463 
3464  if(i != Number_jump)
3465  Halfedges.push(Border_edges[i]);
3466  }
3467  }
3468  }
3469 
3470 
3471  // the symbol == N
3472  else if(valence == 7)
3473  {
3474  // its front face is tagged CONQUERED
3475  put(this->Facet_Flag, face(h, _pMesh), CONQUERED);
3476  put(this->Vertex_Flag, target(next(h, _pMesh), _pMesh), CONQUERED);
3477 
3478  if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
3479  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) == MINUS))
3480  {
3481  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
3482  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), PLUS);
3483  }
3484  else if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
3485  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
3486  PLUS))
3487  {
3488  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
3489  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), PLUS);
3490  }
3491  else if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
3492  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
3493  PLUS))
3494  {
3495  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
3496  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), MINUS);
3497  }
3498  else if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
3499  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
3500  MINUS))
3501  {
3502  if(get(this->Vertex_Sign, target(next(h, _pMesh), _pMesh)) == NOSIGN)
3503  put(this->Vertex_Sign, target(next(h, _pMesh), _pMesh), PLUS);
3504  }
3505 
3506  if(CGAL::is_border_edge(next(h, _pMesh), _pMesh) == false)
3507  Halfedges.push(opposite(next(h, _pMesh), _pMesh));
3508 
3509  if(CGAL::is_border_edge(prev(h, _pMesh), _pMesh) == false)
3510  Halfedges.push(opposite(prev(h, _pMesh), _pMesh));
3511  }
3512  }
3513 }
3514 
3515 
3516 // When the last loop doen not remove any vertex, all information are deleted
3517 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
3518 void
3520  Remove_Last_Phase_Elements(const int &Component_ID)
3521 {
3522  this->NumberDecimation[Component_ID] -=
3523  1; // this->NumberDecimation[Component_ID] - 1;
3524  this->ComponentOperations[Component_ID] -= 1;
3525  this->ListOperation[Component_ID].pop_front();
3526 
3527  for(int i = 0; i < (this->DumpSymbolDecimation + this->DumpSymbolRegulation);
3528  i++)
3529  this->Connectivity[Component_ID].pop_front();
3530 
3531  for(int i = 0; i < 2; i++)
3532  {
3533  this->NumberSymbol[Component_ID].pop_front();
3534  this->NumberVertices[Component_ID].pop_front();
3535  }
3536 }
3537 
3538 
3539 // To store information needed for the reconstruction of the base mesh.
3540 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
3541 void
3543  Write_Base_Mesh(const HalfedgeGraph &_pMesh,
3544  Arithmetic_Codec &enc,
3545  unsigned &Connectivity_size,
3546  unsigned &Color_size,
3547  const int &/*Num_color_base_mesh*/,
3548  const PointMap *_pm)
3549 {
3550 
3551  unsigned int Max_Qbit = 0;
3552  for(int i = 0; i < this->NumberComponents; i++)
3553  {
3554  enc.put_bits(this->ComponentOperations[i], 8); // number of operations < 256
3555  enc.put_bits(this->Qbit[i] - 4, 4); // quantization bit < 16
3556  enc.put_bits(this->NumberChangeQuantization[i],
3557  4); // number of decrease of quantization resolution
3558  enc.put_bits(this->NumberColorQuantization[i], 3);
3559 
3560  if(this->Qbit[i] > Max_Qbit)
3561  Max_Qbit = this->Qbit[i];
3562  }
3563 
3564  enc.put_bits(FEVV::size_of_vertices(_pMesh),
3565  15); // number of vertices of base mesh < 4096
3566  enc.put_bits(FEVV::size_of_faces(_pMesh),
3567  16); // number of facets of base mesh < 8192
3568 
3569  // int Base_color_index_bit = 0;
3570 
3571  int Basemesh_vertex_number = 0;
3572  std::vector< int > Seed_edges(2 * this->NumberComponents, -1);
3573 
3574 
3575  // Encoding of vertex information of base mesh //
3576  for(vertex_iterator pVertex = vertices(_pMesh).first;
3577  pVertex != vertices(_pMesh).second;
3578  Basemesh_vertex_number++, pVertex++)
3579  {
3580  put(this->Vertex_Number, *pVertex, Basemesh_vertex_number);
3581 
3582  // int SEDD = pVertex->Seed_Edge;
3583 
3584  if(get(this->vertex_Seed_Edge, *pVertex) != OTHER_COORDINATE)
3585  Seed_edges[get(this->vertex_Seed_Edge, *pVertex)] =
3586  Basemesh_vertex_number;
3587 
3588  // int cid = pVertex->Component_Number;
3589 
3590  Point_Int Vertex = Change_Real_Int(
3591  get(*_pm, *pVertex), get(this->vertex_Component_Number, *pVertex));
3592 
3593 
3594  enc.put_bits(Vertex.x, Max_Qbit + 1);
3595  enc.put_bits(Vertex.y, Max_Qbit + 1);
3596  enc.put_bits(Vertex.z, Max_Qbit + 1);
3597 
3598  if((this->IsColored) && (!this->IsOneColor))
3599  {
3600  //#ifdef PREDICTION_METHOD
3601  Color_Unit color = get(this->vertex_color_int, *pVertex);
3602  int C0 = color.c0;
3603  int C1 = color.c1;
3604  int C2 = color.c2;
3605 
3606  enc.put_bits(C0, C0_QUANTIZATION);
3607  enc.put_bits(C1, C1_QUANTIZATION);
3608  enc.put_bits(C2, C2_QUANTIZATION);
3609 
3610  Color_size += 3 * C0_QUANTIZATION;
3611  //#endif
3612  }
3613  }
3614 
3615  // Bits needed for each edge.
3616  int Facet_index_bit = (int)ceil(
3617  log((double)(FEVV::size_of_vertices(_pMesh) + 1)) / log((double)2));
3618 
3619  int Count_facet_index = 0;
3620  for(face_iterator pFacet = faces(_pMesh).first;
3621  pFacet != faces(_pMesh).second;
3622  pFacet++)
3623  {
3624  Count_facet_index++;
3625 
3626  halfedge_descriptor pHalfedge = halfedge(*pFacet, _pMesh);
3627  do
3628  {
3629  enc.put_bits(get(this->Vertex_Number, target(pHalfedge, _pMesh)),
3630  Facet_index_bit);
3631  pHalfedge = next(pHalfedge, _pMesh);
3632 
3633 
3634  } while(pHalfedge != halfedge(*pFacet, _pMesh));
3635  }
3636 
3637  // Store seed edge information.
3638  for(int i = 0; i < (int)Seed_edges.size(); i++) // MT
3639  enc.put_bits(Seed_edges[i], Facet_index_bit);
3640 
3641  Connectivity_size +=
3642  Facet_index_bit * (Count_facet_index + Seed_edges.size());
3643 }
3644 
3645 
3646 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
3647 void
3650 {
3651  for(int Component_ID = 0; Component_ID < this->NumberComponents;
3652  Component_ID++)
3653  {
3654  std::list< int >::iterator Number_iterator =
3655  this->NumberVertices[Component_ID].begin();
3656  std::list< Point_Int >::iterator Vertex_iterator =
3657  this->Geometry[Component_ID].begin();
3658 
3659  unsigned Number_phases = this->NumberVertices[Component_ID].size();
3660 
3661 
3662  for(unsigned i = 0; i < Number_phases; i++)
3663  {
3664  int Number_vertices_layer = *Number_iterator;
3665  Number_iterator++;
3666 
3667  int alpha_max = -10000;
3668  int alpha_min = 10000;
3669  int gamma_max = -10000;
3670  int gamma_min = 10000;
3671  int alpha = 0, beta = 0, gamma = 0;
3672 
3673 
3674  if(Number_vertices_layer != 0)
3675  {
3676  for(int j = 0; j < Number_vertices_layer; j++)
3677  {
3678  alpha = Vertex_iterator->x;
3679  if(alpha > alpha_max)
3680  alpha_max = alpha;
3681  if(alpha < alpha_min)
3682  alpha_min = alpha;
3683 
3684  beta = Vertex_iterator->y;
3685  if(beta > alpha_max)
3686  alpha_max = beta;
3687  if(beta < alpha_min)
3688  alpha_min = beta;
3689 
3690  gamma = Vertex_iterator->z;
3691  if(gamma > gamma_max)
3692  gamma_max = gamma;
3693  if(gamma < gamma_min)
3694  gamma_min = gamma;
3695 
3696  Vertex_iterator++;
3697  }
3698 
3699  this->AlphaRange[Component_ID].push_back(alpha_max - alpha_min + 1);
3700  this->AlphaOffset[Component_ID].push_back(-alpha_min);
3701 
3702  this->GammaRange[Component_ID].push_back(gamma_max - gamma_min + 1);
3703  this->GammaOffset[Component_ID].push_back(-gamma_min);
3704  }
3705  else
3706  {
3707  this->AlphaRange[Component_ID].push_back(0);
3708  this->AlphaOffset[Component_ID].push_back(0);
3709 
3710  this->GammaRange[Component_ID].push_back(0);
3711  this->GammaOffset[Component_ID].push_back(0);
3712  }
3713  }
3714  }
3715 
3716 
3717  /* Calculate alpha_min and gamma_min of all coefficients
3718  * in order to prevent negative symbols.Compression is not possible. */
3719  std::list< int >::iterator it_gamma, it_alpha;
3720  for(int Component_ID = 0; Component_ID < this->NumberComponents;
3721  Component_ID++)
3722  {
3723  for(it_alpha = this->AlphaOffset[Component_ID].begin();
3724  it_alpha != this->AlphaOffset[Component_ID].end();
3725  it_alpha++)
3726  {
3727  if(*it_alpha < this->Smallest_Alpha)
3728  this->Smallest_Alpha = *it_alpha;
3729  }
3730  for(it_gamma = this->GammaOffset[Component_ID].begin();
3731  it_gamma != this->GammaOffset[Component_ID].end();
3732  it_gamma++)
3733  {
3734  if(*it_gamma < this->Smallest_Gamma)
3735  this->Smallest_Gamma = *it_gamma;
3736  }
3737  }
3738 
3739 
3740  if(this->IsColored)
3741  {
3742 
3743  int C0_min = 50000, C1_min = 50000, C2_min = 50000;
3744  int C0_max = -50000, C1_max = -50000, C2_max = -50000;
3745 
3746  for(int Component_ID = 0; Component_ID < this->NumberComponents;
3747  Component_ID++)
3748  {
3749  //#ifdef PREDICTION_METHOD
3750  std::list< Color_Unit >::iterator Vertex_color_iterator;
3751  for(Vertex_color_iterator = this->VertexColor[Component_ID].begin();
3752  Vertex_color_iterator != this->VertexColor[Component_ID].end();
3753  Vertex_color_iterator++)
3754  //#endif
3755  {
3756  if(Vertex_color_iterator->c0 < C0_min)
3757  C0_min = Vertex_color_iterator->c0;
3758  if(Vertex_color_iterator->c0 > C0_max)
3759  C0_max = Vertex_color_iterator->c0;
3760 
3761  if(Vertex_color_iterator->c1 < C1_min)
3762  C1_min = Vertex_color_iterator->c1;
3763  if(Vertex_color_iterator->c1 > C1_max)
3764  C1_max = Vertex_color_iterator->c1;
3765 
3766  if(Vertex_color_iterator->c2 < C2_min)
3767  C2_min = Vertex_color_iterator->c2;
3768  if(Vertex_color_iterator->c2 > C2_max)
3769  C2_max = Vertex_color_iterator->c2;
3770  }
3771  }
3772 
3773 
3774  this->C0_Range = C0_max - C0_min + 1;
3775  this->C1_Range = C1_max - C1_min + 1;
3776  this->C2_Range = C2_max - C2_min + 1;
3777 
3778  if(this->C0_Range <= 1)
3779  this->C0_Range = 2;
3780  if(this->C1_Range <= 1)
3781  this->C1_Range = 2;
3782  if(this->C2_Range <= 1)
3783  this->C2_Range = 2;
3784 
3785  this->Smallest_C0 = C0_min;
3786  this->Smallest_C1 = C1_min;
3787  this->Smallest_C2 = C2_min;
3788  }
3789 }
3790 
3791 
3792 //#define DBG_Simplification
3793 
3794 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
3795 void
3797  Simplification(HalfedgeGraph &_pMesh,
3798  const PointMap *_pm,
3799  const int &NVertices,
3800  const bool Normal_flipping,
3801  const bool Use_metric,
3802  const float &Metric_thread,
3803  const bool Use_forget_metric,
3804  const int &Forget_value)
3805 {
3806 
3807 
3808  // bool Is_any_vertex_removed = true;
3809 
3810  unsigned Last_Number = 0;
3811  unsigned Current_Number = FEVV::size_of_vertices(_pMesh);
3812 
3813  // int Operation_choice = -1;
3814 
3815  do
3816  {
3817  Last_Number = Current_Number;
3818 
3819  // Simplify component by component
3820  for(int Component_ID = 0; Component_ID < this->NumberComponents;
3821  Component_ID++)
3822  {
3823  // if the ith component did not remove any vertex in last loop, it is not
3824  // necessary to simplifiy it.
3825  if(this->ComponentOperations[Component_ID] == this->GlobalCountOperation)
3826  {
3827  unsigned Initial_number_vertices = FEVV::size_of_vertices(_pMesh);
3828 
3829 #ifdef DBG_Simplification
3830  std::cout << "in " << __func__
3831  << ", before Decimation_Conquest, num_vertices(_pMesh) = "
3832  << FEVV::size_of_vertices(_pMesh) << std::endl;
3833 #endif
3834 
3835  this->Decimation_Conquest(_pMesh,
3836  _pm,
3837  Normal_flipping,
3838  Use_metric,
3839  Metric_thread,
3840  Use_forget_metric,
3841  Forget_value,
3842  Component_ID);
3843 
3844 #ifdef DBG_Simplification
3845  std::cout << "in " << __func__
3846  << ", after Decimation_Conquest, num_vertices(_pMesh) = "
3847  << FEVV::size_of_vertices(_pMesh) << std::endl;
3848 #endif
3849 
3850  this->Regulation(_pMesh,
3851  Normal_flipping,
3852  Use_metric,
3853  Metric_thread,
3854  Use_forget_metric,
3855  Forget_value,
3856  Component_ID,
3857  _pm);
3858 
3859  int Diff_number_vertices =
3860  FEVV::size_of_vertices(_pMesh) - Initial_number_vertices;
3861 
3862  this->ComponentOperations[Component_ID] += 1;
3863  this->NumberDecimation[Component_ID] += 1;
3864 
3865  this->ListOperation[Component_ID].push_front(0);
3866 
3867  if(Diff_number_vertices == 0)
3868  this->Remove_Last_Phase_Elements(Component_ID);
3869  }
3870  }
3871 
3872  Current_Number = FEVV::size_of_vertices(_pMesh);
3873 
3874 #ifdef DBG_Simplification
3875  // DBG-ELO+beg
3876  {
3877  // count real vertices number
3878  vertex_iterator v_begin = vertices(_pMesh).first;
3879  vertex_iterator v_end = vertices(_pMesh).second;
3880  unsigned int real_vertex_count = 0;
3881  for(vertex_iterator vi = v_begin; vi != v_end; ++vi)
3882  real_vertex_count++;
3883  assert((Current_Number == real_vertex_count));
3884  }
3885  // DBG-ELO+end
3886 #endif
3887 
3888  if(Current_Number != Last_Number)
3889  this->GlobalCountOperation++;
3890 
3891  if(Current_Number < (unsigned)NVertices) // MT
3892  break;
3893 
3894  } while((Current_Number != Last_Number));
3895 
3896  compute_normals(_pMesh, _pm);
3897 }
3898 
3899 
3900 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
3901 void
3903  Compression(HalfedgeGraph &_pMesh,
3904  const char *File_Name,
3905  const int &_Qbit,
3906  unsigned &Connectivity_size,
3907  unsigned &Color_size,
3908  unsigned &Total_size,
3909  const PointMap *_pm)
3910 // const unsigned & Initial_file_size)
3911 {
3912  // Calculate offset and range for the compression.
3913  this->Calculate_Geometry_Color_Offset_Range();
3914 
3915  FILE *fp =
3916  fopen(File_Name, "wb"); // Main FILE to save compression information.
3917 
3918  int res;
3919 
3920  res = fwrite(&this->Smallest_Alpha,
3921  sizeof(int),
3922  1,
3923  fp); // smallest value of alpha (to save the negative value)
3924  res = fwrite(&this->Smallest_Gamma,
3925  sizeof(int),
3926  1,
3927  fp); // smallest value of gamma (to save the negative value)
3928  res = fwrite(
3929  &this->Initial_file_size,
3930  sizeof(unsigned),
3931  1,
3932  fp); // Intial size of the input file (To visualize during decompression)
3933  res = fwrite(&this->NumberComponents, sizeof(int), 1, fp);
3934 
3935  for(int i = 0; i < this->NumberComponents; i++)
3936  {
3937  res = fwrite(&this->Quantization_Step[i],
3938  sizeof(float),
3939  1,
3940  fp); // Quantization_Step(step of quantization)
3941  res = fwrite(&this->xmin[i], sizeof(float), 1, fp); // xmin value
3942  res = fwrite(&this->ymin[i], sizeof(float), 1, fp); // ymin value
3943  res = fwrite(&this->zmin[i], sizeof(float), 1, fp); // zmin value
3944  }
3945 
3946 
3947  // Type of mesh
3948  char Colored;
3949  char OneColor;
3950 
3951  if(this->IsColored)
3952  {
3953  Colored = 1;
3954  if(this->IsOneColor)
3955  OneColor = 1;
3956  else
3957  OneColor = 0;
3958  }
3959  else
3960  Colored = 0;
3961 
3962  res = fwrite(&Colored, sizeof(char), 1, fp);
3963  if(this->IsColored)
3964  res = fwrite(&OneColor, sizeof(char), 1, fp);
3965 
3966 
3967  int Num_color_base_mesh = 0;
3968  if((this->IsColored) && (!this->IsOneColor))
3969  {
3970 
3971  res = fwrite(&this->Color_Quantization_Step, sizeof(float), 1, fp);
3972 
3973  // En-tete pour la couleur
3974  res = fwrite(&this->C0_Min, sizeof(float), 1, fp); // smallest value of c0
3975  res = fwrite(&this->C1_Min, sizeof(float), 1, fp); // smallest value of c1
3976  res = fwrite(&this->C2_Min, sizeof(float), 1, fp); // smallest value of c2
3977 
3978  res = fwrite(&this->Smallest_C0, sizeof(int), 1, fp);
3979  res = fwrite(&this->Smallest_C1, sizeof(int), 1, fp);
3980  res = fwrite(&this->Smallest_C2, sizeof(int), 1, fp);
3981 
3982  Color_size += sizeof(int) * 8 * 9;
3983  }
3984 
3985  if((this->IsColored) && (this->IsOneColor))
3986  {
3987 
3988  res = fwrite(
3989  &this->OnlyColor[0], sizeof(float), 1, fp); // smallest value of c0
3990  res = fwrite(
3991  &this->OnlyColor[1], sizeof(float), 1, fp); // smallest value of c1
3992  res = fwrite(
3993  &this->OnlyColor[2], sizeof(float), 1, fp); // smallest value of c2
3994  }
3995 
3996  res += 0; // just to avoid gcc 4.6 warning
3997 
3998  // Declaration du codeur.
4000  enc.start_encoder();
4001 
4002  // To calculate connectivity rate
4003  Arithmetic_Codec Connectivity_encoder(AC_BUFFER);
4004  Connectivity_encoder.start_encoder();
4005 
4006  for(int i = 0; i < this->NumberComponents; i++)
4007  {
4008  if(this->IsClosed[i])
4009  enc.put_bits(0, 1);
4010 
4011  else
4012  enc.put_bits(1, 1);
4013  }
4014 
4015  if(this->Is_Bijection_Enabled)
4016  enc.put_bits(1, 1);
4017  else
4018  enc.put_bits(0, 1);
4019 
4020  /* Write information of base mesh.
4021  geometry + connectivity + color information(if the mesh is colored).
4022  */
4023  this->Write_Base_Mesh(
4024  _pMesh, enc, Connectivity_size, Color_size, Num_color_base_mesh, _pm);
4025 
4026  // To calculate color rate
4027  Arithmetic_Codec Color_enc(AC_BUFFER);
4028  Color_enc.start_encoder();
4029 
4030 
4031  //#ifdef PREDICTION_METHOD
4032 
4033  Adaptive_Data_Model C0_model;
4034  Adaptive_Data_Model C1_model;
4035  Adaptive_Data_Model C2_model;
4036 
4037  // To calculate color rate
4038  Adaptive_Data_Model PC_C0_model;
4039  Adaptive_Data_Model PC_C1_model;
4040  Adaptive_Data_Model PC_C2_model;
4041 
4042  if((this->IsColored) && (!this->IsOneColor))
4043  {
4044  enc.put_bits(this->C0_Range, C0_QUANTIZATION + 1);
4045  enc.put_bits(this->C1_Range, C1_QUANTIZATION + 1);
4046  enc.put_bits(this->C2_Range, C2_QUANTIZATION + 1);
4047 
4048  C0_model.set_alphabet(this->C0_Range);
4049  C1_model.set_alphabet(this->C1_Range);
4050  C2_model.set_alphabet(this->C2_Range);
4051 
4052  // To calculate color rate
4053  Color_enc.put_bits(this->C0_Range, C0_QUANTIZATION + 1);
4054  Color_enc.put_bits(this->C1_Range, C1_QUANTIZATION + 1);
4055  Color_enc.put_bits(this->C2_Range, C2_QUANTIZATION + 1);
4056 
4057  PC_C0_model.set_alphabet(this->C0_Range);
4058  PC_C1_model.set_alphabet(this->C1_Range);
4059  PC_C2_model.set_alphabet(this->C2_Range);
4060  }
4061 
4062  this->DM_JCW_MOVE_ERROR.set_alphabet(3);
4063 
4064  // Main loop of compression //
4065  for(int i = 0; i < this->GlobalCountOperation; i++)
4066  {
4067 
4068  for(int Component_ID = 0; Component_ID < this->NumberComponents;
4069  Component_ID++)
4070  {
4071  if(i < this->ComponentOperations[Component_ID])
4072  {
4073  int Number_connectivity_symbols;
4074 
4075  if(this->IsClosed[Component_ID])
4076  Number_connectivity_symbols = 5;
4077  else
4078  Number_connectivity_symbols = 7;
4079 
4080  int Type_operation = this->ListOperation[Component_ID].front();
4081  this->ListOperation[Component_ID].pop_front();
4082 
4083  // decimation is chosen to be applied.
4084  if(Type_operation == 0)
4085  {
4086  enc.put_bits(0, 2);
4087 
4088  for(int j = 0; j < 2; j++) // Decimation and regulation
4089  {
4090  Adaptive_Data_Model Connectivity;
4091 
4092  if(j == 0)
4093  Connectivity.set_alphabet(2);
4094  else
4095  Connectivity.set_alphabet(Number_connectivity_symbols);
4096 
4097  Adaptive_Data_Model Temp_connectivity;
4098  if(j == 0)
4099  Temp_connectivity.set_alphabet(2);
4100  else
4101  Temp_connectivity.set_alphabet(Number_connectivity_symbols);
4102 
4103  int Alpha_range = this->AlphaRange[Component_ID].front();
4104  this->AlphaRange[Component_ID].pop_front();
4105  int Alpha_offset = this->AlphaOffset[Component_ID].front();
4106  this->AlphaOffset[Component_ID].pop_front();
4107 
4108  int Gamma_range = this->GammaRange[Component_ID].front();
4109  this->GammaRange[Component_ID].pop_front();
4110  int Gamma_offset = this->GammaOffset[Component_ID].front();
4111  this->GammaOffset[Component_ID].pop_front();
4112 
4113  enc.put_bits(Alpha_range, _Qbit + 1);
4114  if(this->Smallest_Alpha < 0)
4115  enc.put_bits(Alpha_offset - this->Smallest_Alpha, _Qbit + 1);
4116  else
4117  enc.put_bits(Alpha_offset, _Qbit + 1);
4118 
4119  enc.put_bits(Gamma_range, _Qbit + 1);
4120  if(this->Smallest_Gamma < 0)
4121  enc.put_bits(Gamma_offset - this->Smallest_Gamma, _Qbit + 1);
4122  else
4123  enc.put_bits(Gamma_offset, _Qbit + 1);
4124 
4125  bool check_alpha = false;
4126  bool check_gamma = false;
4127 
4128  if((Alpha_range == 0) || (Alpha_range == 1))
4129  {
4130  check_alpha = true;
4131  Alpha_range = 2;
4132  }
4133  if((Gamma_range == 0) || (Gamma_range == 1))
4134  {
4135  check_gamma = true;
4136  Gamma_range = 2;
4137  }
4138 
4139  Adaptive_Data_Model alpha(Alpha_range);
4140  Adaptive_Data_Model gamma(Gamma_range);
4141 
4142  int Number_symbols = this->NumberSymbol[Component_ID].front();
4143  this->NumberSymbol[Component_ID].pop_front();
4144 
4145  for(unsigned k = 0; k < (unsigned)Number_symbols; k++) // MT
4146  {
4147  unsigned symbol = this->Connectivity[Component_ID].front();
4148  this->Connectivity[Component_ID].pop_front();
4149 
4150  enc.encode(symbol, Connectivity);
4151 
4152  // To calculare connectivity rate
4153  Connectivity_encoder.encode(symbol, Temp_connectivity);
4154 
4155  if(((j == 0) && (symbol != 1)) || ((j == 1) && (symbol != 4)))
4156  {
4157  Point_Int Coeff = this->Geometry[Component_ID].front();
4158  this->Geometry[Component_ID].pop_front();
4159 
4160  int x = Coeff.x + Alpha_offset;
4161  int y = Coeff.y + Alpha_offset;
4162  int z = Coeff.z + Gamma_offset;
4163 
4164  if(check_alpha == false)
4165  {
4166  enc.encode(x, alpha);
4167  enc.encode(y, alpha);
4168  }
4169  if(check_gamma == false)
4170  {
4171  enc.encode(z, gamma);
4172  }
4173 
4174 
4175  //#ifdef PREDICTION_METHOD
4176  if((this->IsColored) && (!this->IsOneColor))
4177  {
4178  Color_Unit VC = this->VertexColor[Component_ID].front();
4179  this->VertexColor[Component_ID].pop_front();
4180 
4181  enc.encode(VC.c0 - this->Smallest_C0, C0_model);
4182  enc.encode(VC.c1 - this->Smallest_C1, C1_model);
4183  enc.encode(VC.c2 - this->Smallest_C2, C2_model);
4184 
4185  // To calculate color rate
4186  Color_enc.encode(VC.c0 - this->Smallest_C0, PC_C0_model);
4187  Color_enc.encode(VC.c1 - this->Smallest_C1, PC_C1_model);
4188  Color_enc.encode(VC.c2 - this->Smallest_C2, PC_C2_model);
4189  }
4190  //#endif
4191  }
4192  }
4193  alpha.reset();
4194  gamma.reset();
4195  }
4196 
4197  if(!this->m_N_Errors.empty())
4198  {
4199  int tt_count = this->m_N_Errors.front();
4200  this->m_N_Errors.pop_front();
4201 
4202  // if(!this->m_JCW_Move_Error.empty())
4203  for(int tt_i = 0; tt_i < tt_count; tt_i++)
4204  {
4205  std::vector< int > Temp_error = this->m_JCW_Move_Error.front();
4206  this->m_JCW_Move_Error.pop_front();
4207 
4208  for(int m = 0; m < 3; m++)
4209  {
4210  int Te = Temp_error[m];
4211 
4212  if(Te == -1)
4213  Te = 2;
4214 
4215  enc.encode(Te, this->DM_JCW_MOVE_ERROR);
4216  }
4217  }
4218  }
4219  }
4220 
4221  // Decrease of geometry quantization resolution.
4222  else if(Type_operation == 1)
4223  {
4224  enc.put_bits(1, 2);
4225 
4226  int Number_vertices =
4227  this->NumberQuantizationLayer[Component_ID].front();
4228  this->NumberQuantizationLayer[Component_ID].pop_front();
4229 
4230  Adaptive_Data_Model Under_quantization_model(8);
4231 
4232  for(int i = 0; i < Number_vertices; i++)
4233  {
4234  int Under_quantization_coeff =
4235  this->QuantizationCorrectVector[Component_ID].front();
4236  this->QuantizationCorrectVector[Component_ID].pop_front();
4237 
4238  enc.encode(Under_quantization_coeff, Under_quantization_model);
4239  }
4240  }
4241 
4242  // Decrease of color quantization resolution.
4243  else
4244  {
4245  enc.put_bits(2, 2);
4246  Arithmetic_Codec Color_enc(AC_BUFFER);
4247  Color_enc.start_encoder();
4248 
4249  int Number_vertices =
4250  this->NumberProcessedVertices[Component_ID].front();
4251  this->NumberProcessedVertices[Component_ID].pop_front();
4252 
4253  Adaptive_Data_Model *Color_quantization_model =
4255  for(int i = 0; i < COLOR_NUMBER; i++)
4256  Color_quantization_model[i].set_alphabet(8);
4257 
4258  // To measure color rates
4259  Adaptive_Data_Model *Temp_quantization_model =
4261  for(int i = 0; i < COLOR_NUMBER; i++)
4262  Temp_quantization_model[i].set_alphabet(8);
4263 
4264  for(int i = 0; i < Number_vertices; i++)
4265  {
4266  int Color_index = this->ColorEncoderIndex[Component_ID].front();
4267  this->ColorEncoderIndex[Component_ID].pop_front();
4268 
4269  int Childcell_index =
4270  this->ColorChildcellIndex[Component_ID].front();
4271  this->ColorChildcellIndex[Component_ID].pop_front();
4272 
4273  enc.encode(Childcell_index, Color_quantization_model[Color_index]);
4274 
4275  Color_enc.encode(Childcell_index,
4276  Temp_quantization_model[Color_index]);
4277  }
4278  Color_size += Color_enc.stop_encoder() * 8;
4279 
4280  delete[] Color_quantization_model;
4281  delete[] Temp_quantization_model;
4282  }
4283  }
4284  }
4285  }
4286 
4287  Connectivity_size += Connectivity_encoder.stop_encoder() * 8;
4288  Color_size += Color_enc.stop_encoder() * 8;
4289 
4290  enc.write_to_file(fp);
4291  fclose(fp);
4292 
4293  FILE *f_size = fopen(File_Name, "rb");
4294  fseek(f_size, 0, SEEK_END);
4295  Total_size = ftell(f_size);
4296 }
4297 
4298 
4299 //#define DBG_Calculate_Edge_Color_Difference
4300 //#define DBG_Calculate_Edge_Color_Difference_VERBOSE
4301 
4302 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
4303 void
4305  Calculate_Edge_Color_Difference(HalfedgeGraph &_pMesh,
4306  const int &_Component_ID,
4307  double &_Max_color,
4308  double &_Mean_color,
4309  int &Number_of_vertices)
4310 {
4311  typedef boost::graph_traits< HalfedgeGraph > GraphTraits;
4312  typedef typename GraphTraits::vertex_iterator vertex_iterator;
4313  typedef typename GraphTraits::halfedge_iterator halfedge_iterator;
4314 
4315 #ifdef DBG_Calculate_Edge_Color_Difference
4316  static unsigned int Calculate_Edge_Color_Difference_call_cnt = 0;
4317  Calculate_Edge_Color_Difference_call_cnt++;
4318  std::string dbg_header =
4319  std::string("in ") + std::string(__func__) + std::string(", call_cnt=") +
4320  std::to_string(Calculate_Edge_Color_Difference_call_cnt);
4321  std::cout << dbg_header << ", this->C0_Min = " << this->C0_Min << std::endl;
4322  std::cout << dbg_header << ", this->C1_Min = " << this->C1_Min << std::endl;
4323  std::cout << dbg_header << ", this->C2_Min = " << this->C2_Min << std::endl;
4324  vertex_iterator vi_beg_dbg = vertices(_pMesh).first;
4325  vertex_iterator vi_end_dbg = vertices(_pMesh).second;
4326  for(vertex_iterator vi = vi_beg_dbg; vi != vi_end_dbg; ++vi)
4327  {
4328  std::cout << dbg_header
4329  << ", vertex_Seed_Edge = " << get(this->vertex_Seed_Edge, *vi)
4330  << std::endl;
4331  Color_Unit color_int;
4332  color_int = get(this->vertex_color_int, *vi);
4333  std::cout << dbg_header << ", vertex_color_int = " << color_int.c0 << ","
4334  << color_int.c1 << "," << color_int.c2 << std::endl;
4335  }
4336  PointMap pm = get(boost::vertex_point, _pMesh);
4337  PointMap *_pm = &pm;
4338 #endif
4339 
4340  float C0_min = this->C0_Min;
4341  float C1_min = this->C1_Min;
4342  float C2_min = this->C2_Min;
4343 
4344  float Color_small_step = 0.0;
4345 
4346  if(this->NumberColorQuantization[_Component_ID] == 0)
4347  {
4348  Color_small_step = this->Color_Quantization_Step;
4349  }
4350 
4351  else
4352  {
4353  Color_small_step =
4354  this->Color_Quantization_Step *
4355  std::pow(2.0, this->NumberColorQuantization[_Component_ID]);
4356  }
4357 #ifdef DBG_Calculate_Edge_Color_Difference
4358  std::cout << dbg_header << ", Color_small_step = " << Color_small_step
4359  << std::endl;
4360 #endif
4361 
4362  // To find first points to start the conquest.
4363  auto halfedge_iterator_pair = halfedges(_pMesh);
4364  halfedge_iterator hi = halfedge_iterator_pair.first;
4365 
4366  while(
4367  (get(this->vertex_Seed_Edge, target(*hi, _pMesh)) != 2 * _Component_ID) ||
4368  (get(this->vertex_Seed_Edge, target(opposite(*hi, _pMesh), _pMesh)) !=
4369  2 * _Component_ID + 1))
4370  {
4371  hi++;
4372  }
4373 #ifdef DBG_Calculate_Edge_Color_Difference
4375  "in Calculate_Edge_Color_Difference, *hi = ", *hi, _pMesh, _pm);
4376 #endif
4377 
4378  // Vertex_Flag est donnee free a tous les sommets
4379  auto vertex_iterator_pair = vertices(_pMesh);
4380  vertex_iterator vi_beg = vertex_iterator_pair.first;
4381  vertex_iterator vi_end = vertex_iterator_pair.second;
4382  for(vertex_iterator pVert = vi_beg; pVert != vi_end; pVert++)
4383  {
4384  put(this->Vertex_Flag, *pVert, FREE);
4385  put(this->Vertex_Number, *pVert, -1);
4386  }
4387 
4388  std::queue< vertex_descriptor > vertices;
4389 
4390  // push a input gate to begin loop
4391  // in order to treat all vertices.
4392  vertices.push(target(*hi, _pMesh));
4393  vertices.push(target(opposite(*hi, _pMesh), _pMesh));
4394 
4395  // To count number of vertices;;
4396  int Count_vertices = 0;
4397  double Max_color = -5000.;
4398  double Mean_color = 0.;
4399  double L_min = 5000, A_min = 5000, B_min = 5000;
4400  double L_max = -5000, A_max = -5000, B_max = -5000;
4401 
4402  //unsigned int while_loop_cnt = 0;
4403  while(!vertices.empty())
4404  {
4405 #ifdef DBG_Calculate_Edge_Color_Difference_VERBOSE
4406  std::cout << dbg_header << ", while_loop_cnt = " << ++while_loop_cnt
4407  << std::endl;
4408  std::cout << dbg_header << ", vertices.size = " << vertices.size()
4409  << std::endl;
4410 #endif
4411  vertex_descriptor v = vertices.front();
4412  vertices.pop();
4413 #ifdef DBG_Calculate_Edge_Color_Difference_VERBOSE
4414  print_vertex("in Calculate_Edge_Color_Difference, pop v = ", v, _pm);
4415 #endif
4416 
4417 
4418  if(get(this->Vertex_Flag, v) == CONQUERED)
4419  {
4420 #ifdef DBG_Calculate_Edge_Color_Difference_VERBOSE
4421  // std::cout << "in " << __func__ << "_mark_#1" << std::endl;
4422 #endif
4423  continue;
4424  }
4425  else
4426  {
4427 #ifdef DBG_Calculate_Edge_Color_Difference_VERBOSE
4428  // std::cout << "in " << __func__ << "_mark_#2" << std::endl;
4429  std::vector< std::string > dbg_diff_per_he;
4430 #endif
4431  put(this->Vertex_Flag, v, CONQUERED);
4432  put(this->Vertex_Number, v, Count_vertices);
4433 
4434  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > hvc(v, _pMesh);
4435  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > phvc(hvc);
4436 
4437  //int neighbour_cnt = 0;
4438  double Mean = 0.0;
4439  int Count = 0;
4440  CGAL_For_all(hvc, phvc)
4441  {
4442 #ifdef DBG_Calculate_Edge_Color_Difference_VERBOSE
4443  // print_halfedge("in Calculate_Edge_Color_Difference, *hvc = ", *hvc,
4444  // _pMesh, _pm); if( vertex_to_string(v, _pm) == "(0.000483196,
4445  // 0.0101471, 0.714355)")
4446  //{
4447  // std::cout << "in " << __func__ << ", v=" << vertex_to_string(v, _pm)
4448  // << " neighbour=" << ++neighbour_cnt << " v0=" <<
4449  // vertex_to_string(target(*hvc, _pMesh), _pm) << " v1=" <<
4450  // vertex_to_string(target(opposite(*hvc, _pMesh), _pMesh), _pm) << "
4451  // Vertex_Flag=" << (get(this->Vertex_Flag, target(opposite(*hvc,
4452  // _pMesh), _pMesh)) == FREE) << std::endl;
4453  //}
4454 #endif
4455 
4456  if(get(this->Vertex_Flag, target(opposite(*hvc, _pMesh), _pMesh)) ==
4457  FREE)
4458  {
4459 #ifdef DBG_Calculate_Edge_Color_Difference_VERBOSE
4460  // std::cout << "in " << __func__ << "_mark_#3" << std::endl;
4461 #endif
4462  Color_Unit Color_0, Color_1;
4463  Color_0 = get(this->vertex_color_int, target(*hvc, _pMesh));
4464 
4465  Color_1 = get(this->vertex_color_int,
4466  target(opposite(*hvc, _pMesh), _pMesh));
4467 
4468  double LAB_0[3], LAB_1[3];
4469 
4470  LAB_0[0] = C0_min + Color_0.c0 * Color_small_step;
4471  LAB_0[1] = C1_min + Color_0.c1 * Color_small_step;
4472  LAB_0[2] = C2_min + Color_0.c2 * Color_small_step;
4473 
4474  LAB_1[0] = C0_min + Color_1.c0 * Color_small_step;
4475  LAB_1[1] = C1_min + Color_1.c1 * Color_small_step;
4476  LAB_1[2] = C2_min + Color_1.c2 * Color_small_step;
4477 
4478  if(LAB_0[0] > L_max)
4479  L_max = LAB_0[0];
4480  if(LAB_0[1] > A_max)
4481  A_max = LAB_0[1];
4482  if(LAB_0[2] > B_max)
4483  B_max = LAB_0[2];
4484 
4485  if(LAB_1[0] > L_max)
4486  L_max = LAB_1[0];
4487  if(LAB_1[1] > A_max)
4488  A_max = LAB_1[1];
4489  if(LAB_1[2] > B_max)
4490  B_max = LAB_1[2];
4491 
4492  if(LAB_0[0] < L_min)
4493  L_min = LAB_0[0];
4494  if(LAB_0[1] < A_min)
4495  A_min = LAB_0[1];
4496  if(LAB_0[2] < B_min)
4497  B_min = LAB_0[2];
4498 
4499  if(LAB_1[0] < L_min)
4500  L_min = LAB_1[0];
4501  if(LAB_1[1] < A_min)
4502  A_min = LAB_1[1];
4503  if(LAB_1[2] < B_min)
4504  B_min = LAB_1[2];
4505  double diff = 0.0;
4506  for(int i = 0; i < 3; i++)
4507  {
4508  diff += (LAB_0[i] - LAB_1[i]) * (LAB_0[i] - LAB_1[i]);
4509  }
4510 
4511  diff = std::sqrt(diff);
4512 #ifdef DBG_Calculate_Edge_Color_Difference_VERBOSE
4513  // std::cout << "in " << __func__ << ", v0 = " <<
4514  // vertex_to_string(target(*hvc, _pMesh), _pm) << " v1 = " <<
4515  // vertex_to_string(target(opposite(*hvc, _pMesh), _pMesh), _pm) << "
4516  // diff = " << diff << std::endl;
4517  char dbg_buffer[20];
4518  snprintf(dbg_buffer, sizeof(dbg_buffer), "%f", diff);
4519  dbg_diff_per_he.push_back(edge_to_string(*hvc, _pMesh, _pm) +
4520  " diff=" + dbg_buffer);
4521 #endif
4522 
4523  Mean += diff;
4524  Count++;
4525 
4526 #ifdef DBG_Calculate_Edge_Color_Difference_VERBOSE
4527  // if( vertex_to_string(v, _pm) == "(0.000483196, 0.0101471,
4528  // 0.714355)")
4529  //{
4530  // std::cout << "in " << __func__ << ", v=" << vertex_to_string(v,
4531  // _pm) << " v0=" << vertex_to_string(target(*hvc, _pMesh), _pm) << "
4532  // v1=" << vertex_to_string(target(opposite(*hvc, _pMesh), _pMesh),
4533  // _pm) << " diff=" << diff << " Mean=" << Mean << " Count=" <<
4534  // Count << std::endl;
4535  //}
4536 #endif
4537  }
4538  }
4539 #ifdef DBG_Calculate_Edge_Color_Difference_VERBOSE
4540  // std::cout << "in " << __func__ << ", Mean = " << Mean << std::endl;
4541  // std::cout << "in " << __func__ << ", Count = " << Count << std::endl;
4542  for(int i = 0; i < dbg_diff_per_he.size(); i++)
4543  std::cout << dbg_header << " " << dbg_diff_per_he[i]
4544  << " Count=" << Count << std::endl;
4545 #endif
4546 
4547  if(Count != 0)
4548  {
4549  Mean /= Count;
4550  Mean_color += Mean;
4551  }
4552 #ifdef DBG_Calculate_Edge_Color_Difference_VERBOSE
4553  std::cout << dbg_header << ", v = " << vertex_to_string(v, _pm)
4554  << " Mean = " << Mean << std::endl;
4555  std::cout << dbg_header << ", v = " << vertex_to_string(v, _pm)
4556  << " Mean_color = " << Mean_color << std::endl;
4557 #endif
4558 
4559  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h(v, _pMesh);
4560  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h2(h);
4561  CGAL_For_all(h, h2)
4562  {
4563 #ifdef DBG_Calculate_Edge_Color_Difference_VERBOSE
4564  // print_halfedge("in Calculate_Edge_Color_Difference, *h = ", *h,
4565  // _pMesh, _pm);
4566 #endif
4567  if(get(this->Vertex_Flag, target(opposite(*h, _pMesh), _pMesh)) == FREE)
4568  {
4569 #ifdef DBG_Calculate_Edge_Color_Difference
4570  std::cout << dbg_header << ", v = " << vertex_to_string(v, _pm)
4571  << " push vertex "
4572  << vertex_to_string(target(opposite(*h, _pMesh), _pMesh),
4573  _pm)
4574  << std::endl;
4575 #endif
4576  vertices.push(target(opposite(*h, _pMesh), _pMesh));
4577  }
4578  }
4579 
4580  // increment number of vertices;
4581  Count_vertices++;
4582  }
4583  }
4584 #ifdef DBG_Calculate_Edge_Color_Difference
4585  std::cout << dbg_header << ", after while loop Mean_color = " << Mean_color
4586  << std::endl;
4587 #endif
4588 
4589  Max_color = (L_max - L_min) * (L_max - L_min) +
4590  (A_max - A_min) * (A_max - A_min) +
4591  (B_max - B_min) * (B_max - B_min);
4592 
4593  Max_color = std::sqrt(Max_color);
4594  _Max_color = Max_color;
4595  _Mean_color = 3 * Mean_color / Count_vertices;
4596  Number_of_vertices = Count_vertices;
4597 
4598 #ifdef DBG_Calculate_Edge_Color_Difference
4599  for(vertex_iterator vi = vi_beg_dbg; vi != vi_end_dbg; ++vi)
4600  {
4601  std::cout << dbg_header << ", Vertex_Flag = " << get(this->Vertex_Flag, *vi)
4602  << std::endl;
4603  std::cout << dbg_header
4604  << ", Vertex_Number = " << get(this->Vertex_Number, *vi)
4605  << std::endl;
4606  // note: Vertex_Number is the order in which the vertices are processed, so
4607  // it's different in Mepp1 and Mepp2
4608  }
4609  std::cout << dbg_header << ", _Mean_color = " << _Mean_color << std::endl;
4610  std::cout << dbg_header << ", _Max_color = " << _Max_color << std::endl;
4611  std::cout << dbg_header << ", Number_of_vertices = " << Number_of_vertices
4612  << std::endl;
4613 #endif
4614 }
4615 
4616 // Differentes histogrammes pour chaque couleur.
4617 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
4618 void
4620  Diminush_Color_Quantization_Precision(HalfedgeGraph &_pMesh,
4621  const int _Component_ID,
4622  VertexColorMap *_v_cm)
4623 {
4624  typedef typename boost::property_traits< VertexColorMap >::value_type Color;
4625 
4626  // int N = 16; // Number of neighboring colors to use;
4627  // float Color_diff_seuil = 30.0;
4628 
4629  /*float C0_min = this->C0_Min;
4630  float C1_min = this->C1_Min;
4631  float C2_min = this->C2_Min;*/
4632 
4633  float Color_small_step = 0.0;
4634 
4635  if(this->NumberColorQuantization[_Component_ID] == 0)
4636  Color_small_step = this->Color_Quantization_Step;
4637 
4638  else
4639  Color_small_step =
4640  this->Color_Quantization_Step *
4641  std::pow(2.0, this->NumberColorQuantization[_Component_ID]);
4642 
4643  double Color_large_step = Color_small_step * 2;
4644 
4645  // To find first points to start the conquest.
4646  auto halfedge_iterator_pair = halfedges(_pMesh);
4647  halfedge_iterator hi = halfedge_iterator_pair.first;
4648 
4649  while(
4650  (get(this->vertex_Seed_Edge, target(*hi, _pMesh)) != 2 * _Component_ID) ||
4651  (get(this->vertex_Seed_Edge, target(opposite(*hi, _pMesh), _pMesh)) !=
4652  2 * _Component_ID + 1))
4653  hi++;
4654 
4655  // Vertex_Flag est donnee free a tous les sommets
4656  for(vertex_iterator pVert = vertices(_pMesh).first;
4657  pVert != vertices(_pMesh).second;
4658  pVert++)
4659  {
4660  put(this->Vertex_Flag, *pVert, FREE);
4661  put(this->Vertex_Number, *pVert, -1);
4662  }
4663 
4664  // premiere passe pour sous quantifier et donne l'indice de symbol a chaque
4665  // sommet
4666  for(vertex_iterator pVert = vertices(_pMesh).first;
4667  pVert != vertices(_pMesh).second;
4668  pVert++)
4669  {
4670  if(get(vertex_Component_Number, *pVert) == _Component_ID)
4671  {
4672  Color_Unit color = get(this->vertex_color_int, *pVert);
4673  int LAB_init_C0 = color.c0;
4674  int LAB_init_C1 = color.c1;
4675  int LAB_init_C2 = color.c2;
4676 
4677  // Les coordonnees apres under-quantization
4678  int LAB_final_C0 = LAB_init_C0 / 2;
4679  int LAB_final_C1 = LAB_init_C1 / 2;
4680  int LAB_final_C2 = LAB_init_C2 / 2;
4681 
4682  int i = LAB_init_C0 % 2;
4683  int j = LAB_init_C1 % 2;
4684  int k = LAB_init_C2 % 2;
4685 
4686  int Q_index = Get_Correct_Vector(i, j, k);
4687 
4688  put(this->vertex_color_int,
4689  *pVert,
4690  Color_Unit(LAB_final_C0, LAB_final_C1, LAB_final_C2));
4691  put(this->vertex_Q_Index, *pVert, Q_index);
4692 
4693  float RGB[3];
4694 
4695  // To re-colorify the vertex with decreased color precision
4696  std::vector< float > LAB;
4697 
4698  LAB.push_back(this->C0_Min + LAB_final_C0 * Color_large_step);
4699  LAB.push_back(this->C1_Min + LAB_final_C1 * Color_large_step);
4700  LAB.push_back(this->C2_Min + LAB_final_C2 * Color_large_step);
4701 
4702  LAB_To_RGB(LAB[0], LAB[1], LAB[2], RGB);
4703 
4704  put(*_v_cm, *pVert, Color(RGB[0], RGB[1], RGB[2]));
4705  }
4706  }
4707 
4708  std::queue< vertex_descriptor > vertices;
4709 
4710  std::list< int > Inter_color_quantization;
4711  std::list< int > Inter_index_per_color;
4712 
4713  // push a input gate to begin loop
4714  // in order to treat all vertices.
4715  vertices.push(target(*hi, _pMesh));
4716  vertices.push(target(opposite(*hi, _pMesh), _pMesh));
4717 
4718  int Vertex_index = 0;
4719 
4720  // Color table which stocks all present colors
4721  std::vector< std::vector< int > > Color_table;
4722 
4723  while(!vertices.empty())
4724  {
4725  vertex_descriptor v = vertices.front();
4726  vertices.pop();
4727 
4728  if(get(this->Vertex_Flag, v) == CONQUERED)
4729  continue;
4730 
4731  else
4732  {
4733  put(this->Vertex_Flag, v, CONQUERED);
4734  put(this->Vertex_Number, v, Vertex_index);
4735 
4736  int Q_index = get(this->vertex_Q_Index, v);
4737  std::vector< int > LAB;
4738 
4739  LAB.push_back((get(this->vertex_color_int, v)).c0);
4740  LAB.push_back((get(this->vertex_color_int, v)).c1);
4741  LAB.push_back((get(this->vertex_color_int, v)).c2);
4742 
4743  bool Is_existed_color = false;
4744 
4745  // C'est une couleur deja existante?
4746  for(unsigned i = 0; i < Color_table.size(); i++)
4747  {
4748  if((LAB[0] == Color_table[i][0]) && (LAB[1] == Color_table[i][1]) &&
4749  (LAB[2] == Color_table[i][2]))
4750  {
4751  Is_existed_color = true;
4752  Inter_color_quantization.push_front(Q_index);
4753  Inter_index_per_color.push_front(i);
4754  break;
4755  }
4756  }
4757 
4758  // Sinon, agrandir le tabeau.
4759  if(Is_existed_color == false)
4760  {
4761  Inter_color_quantization.push_front(Q_index);
4762  Inter_index_per_color.push_front(Color_table.size());
4763 
4764  Color_table.push_back(LAB);
4765  }
4766  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h;
4767 
4768  // First_vertex -> To find the seed edge
4769  if(Vertex_index == 0)
4770  {
4771  h = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(v, _pMesh);
4772  do
4773  {
4774  h++;
4775  } while((*h) != (*hi));
4776  }
4777 
4778  // To find an deterministic order = a given vertex and a vertex
4779  // with the highest value of vertex number
4780  else
4781  {
4782  int Comp_number = -2;
4783 
4784  h = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(v, _pMesh);
4785 
4786  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h2 = h;
4787  CGAL_For_all(h, h2)
4788  {
4789  if(get(this->Vertex_Number, target(opposite(*h, _pMesh), _pMesh)) >
4790  Comp_number)
4791  Comp_number =
4792  get(this->Vertex_Number, target(opposite(*h, _pMesh), _pMesh));
4793  }
4794 
4795  h = h2;
4796  CGAL_For_all(h, h2)
4797  {
4798  if(get(this->Vertex_Number, target(opposite(*h, _pMesh), _pMesh)) ==
4799  Comp_number)
4800  break;
4801  }
4802  }
4803 
4804  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h2 = h;
4805  CGAL_For_all(h, h2)
4806  {
4807  if(get(this->Vertex_Flag, target(opposite(*h, _pMesh), _pMesh)) == FREE)
4808  vertices.push(target(opposite(*h, _pMesh), _pMesh));
4809  }
4810 
4811  Vertex_index++;
4812  }
4813  }
4814 
4815 
4816  int ssss = Inter_color_quantization.size();
4817  this->NumberProcessedVertices[_Component_ID].push_front(ssss);
4818 
4819  while(!Inter_color_quantization.empty())
4820  {
4821  int index = Inter_color_quantization.front();
4822  Inter_color_quantization.pop_front();
4823 
4824  this->ColorChildcellIndex[_Component_ID].push_front(index);
4825  }
4826  while(!Inter_index_per_color.empty())
4827  {
4828  int Color = Inter_index_per_color.front();
4829  Inter_index_per_color.pop_front();
4830 
4831  this->ColorEncoderIndex[_Component_ID].push_front(Color);
4832  }
4833 }
4834 
4835 
4836 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
4837 void
4839  Recalculate_Component_Area(HalfedgeGraph &_pMesh,
4840  const PointMap *_pm,
4841  const int &_Component_ID,
4842  int &Number_facets)
4843 {
4844  typedef boost::graph_traits< HalfedgeGraph > GraphTraits;
4845  typedef typename GraphTraits::face_iterator face_iterator;
4846 
4847  double Area = 0.0;
4848  Number_facets = 0;
4849  auto face_iterator_pair = faces(_pMesh);
4850  face_iterator pFacet_beg = face_iterator_pair.first;
4851  face_iterator pFacet_end = face_iterator_pair.second;
4852  for(face_iterator pFacet = pFacet_beg; pFacet != pFacet_end; ++pFacet)
4853  {
4854  if(get(this->facet_Component_Number, *pFacet) == _Component_ID)
4855  {
4856  Number_facets += 1;
4857  Area += Area_Facet_Triangle(halfedge(*pFacet, _pMesh), _pMesh, _pm);
4858  }
4859  }
4860  Area *= std::pow(
4861  ((double)10.0 / (double)this->HighestLengthBB[_Component_ID]), 2.0);
4862  this->ComponentArea[_Component_ID] = Area;
4863 }
4864 
4865 
4866 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
4867 void
4869  Augment_Geometry_Quantization_Precision(HalfedgeGraph &_pMesh,
4870  Arithmetic_Codec &Decoder,
4871  const int &Component_ID,
4872  PointMap *_pm)
4873 {
4875 
4876  Adaptive_Data_Model Under_quantization_model(8);
4877 
4878  // Premier_Pas == distance d'un Quantization_Step de grill de quantification
4879  // (Q)
4880  double Small_step = 0.0;
4881 
4882  if(this->NumberChangeQuantization[Component_ID] == 0)
4883  Small_step = this->Quantization_Step[Component_ID];
4884 
4885  else
4886  Small_step =
4887  this->Quantization_Step[Component_ID] *
4888  std::pow(2.0, this->NumberChangeQuantization[Component_ID] - 1);
4889 
4890  // double Large_step = Small_step * 2;
4891 
4892  // To find first points to start the conquest.
4893  halfedge_iterator hi = halfedges(_pMesh).first;
4894  while(
4895  (get(this->vertex_Seed_Edge, target(*hi, _pMesh)) != 2 * Component_ID) ||
4896  (get(this->vertex_Seed_Edge, target(opposite(*hi, _pMesh), _pMesh)) !=
4897  2 * Component_ID + 1))
4898  hi++;
4899 
4900  // Vertex_Flag est donnee free a tous les sommets
4901  for(vertex_iterator pVert = vertices(_pMesh).first;
4902  pVert != vertices(_pMesh).second;
4903  pVert++)
4904  {
4905  put(this->Vertex_Flag, *pVert, FREE);
4906  put(this->Vertex_Number, *pVert, -1);
4907  put(this->vertex_Component_Number, *pVert, -1);
4908  }
4909  //_pMesh.compute_normals();
4910 
4911  std::queue< vertex_descriptor > verticesq;
4912  std::list< int > Layer_symbols;
4913 
4914  // push first vertex to begin loop
4915  // to treat all vertices.
4916  verticesq.push(target(*hi, _pMesh));
4917  verticesq.push(target(opposite(*hi, _pMesh), _pMesh));
4918 
4919  int Vertex_index = 0;
4920 
4921  while(!verticesq.empty())
4922  {
4923  vertex_descriptor v = verticesq.front();
4924  verticesq.pop();
4925 
4926  if(get(this->Vertex_Flag, v) == CONQUERED)
4927  continue;
4928 
4929  else
4930  {
4931  put(this->Vertex_Flag, v, CONQUERED);
4932  put(this->Vertex_Number, v, Vertex_index);
4933  put(this->vertex_Component_Number, v, Component_ID);
4934 
4935  unsigned valence = out_degree(v, _pMesh);
4936 
4937  Point3d *Neighbors = new Point3d[valence];
4938  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > hvc(v, _pMesh);
4939  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > hvc2 = hvc;
4940  unsigned count_neighbor = 0;
4941  CGAL_For_all(hvc, hvc2)
4942  {
4943  Neighbors[count_neighbor] =
4944  get(*_pm, target(opposite(*hvc, _pMesh), _pMesh));
4945  count_neighbor++;
4946  }
4947 
4948  Point3d Center = get(*_pm, v);
4949  std::vector< int > D(6, 0);
4950 
4951  for(unsigned i = 0; i < valence; i++)
4952  {
4953  Vector Vect =
4954  FEVV::Math::Vector::sub< FEVV::Geometry_traits< HalfedgeGraph > >(
4955  Neighbors[i], Center, gt);
4956 
4957  if(Vect[0] <= 0)
4958  {
4959  int I_dist = Vect[0] / Small_step / 2;
4960  D[0] += std::abs(I_dist);
4961  }
4962  else
4963  {
4964  int I_dist = Vect[0] / Small_step / 2;
4965  D[1] += std::abs(I_dist);
4966  }
4967 
4968  if(Vect[1] <= 0)
4969  {
4970  int I_dist = Vect[1] / Small_step / 2;
4971  D[2] += std::abs(I_dist);
4972  }
4973  else
4974  {
4975  int I_dist = Vect[1] / Small_step / 2;
4976  D[3] += std::abs(I_dist);
4977  }
4978 
4979  if(Vect[2] <= 0)
4980  {
4981  int I_dist = Vect[2] / Small_step / 2;
4982  D[4] += std::abs(I_dist);
4983  }
4984  else
4985  {
4986  int I_dist = Vect[2] / Small_step / 2;
4987  D[5] += std::abs(I_dist);
4988  }
4989  }
4990 
4991  std::vector< double > U(3, 0);
4992  U[0] = std::abs((double)D[0] / (double)(D[0] + D[1]) - 0.5);
4993  U[1] = std::abs((double)D[2] / (double)(D[2] + D[3]) - 0.5);
4994  U[2] = std::abs((double)D[4] / (double)(D[4] + D[5]) - 0.5);
4995 
4996  std::multimap< double, int > U_order;
4997  U_order.insert(std::pair< double, int >(U[0], 0));
4998  U_order.insert(std::pair< double, int >(U[1], 1));
4999  U_order.insert(std::pair< double, int >(U[2], 2));
5000 
5001  std::multimap< double, int >::iterator it;
5002 
5003  std::vector< int > Weight_axe(3, 0);
5004  int Temp_weight = 1;
5005  for(it = U_order.begin(); it != U_order.end(); it++)
5006  {
5007  Weight_axe[it->second] = Temp_weight;
5008  Temp_weight++;
5009  }
5010 
5011  std::vector< int > Priority(8, 0);
5012  Priority[0] =
5013  Weight_axe[0] * D[0] + Weight_axe[1] * D[2] + Weight_axe[2] * D[4];
5014  Priority[1] =
5015  Weight_axe[0] * D[1] + Weight_axe[1] * D[2] + Weight_axe[2] * D[4];
5016  Priority[2] =
5017  Weight_axe[0] * D[0] + Weight_axe[1] * D[3] + Weight_axe[2] * D[4];
5018  Priority[3] =
5019  Weight_axe[0] * D[1] + Weight_axe[1] * D[3] + Weight_axe[2] * D[4];
5020  Priority[4] =
5021  Weight_axe[0] * D[0] + Weight_axe[1] * D[2] + Weight_axe[2] * D[5];
5022  Priority[5] =
5023  Weight_axe[0] * D[1] + Weight_axe[1] * D[2] + Weight_axe[2] * D[5];
5024  Priority[6] =
5025  Weight_axe[0] * D[0] + Weight_axe[1] * D[3] + Weight_axe[2] * D[5];
5026  Priority[7] =
5027  Weight_axe[0] * D[1] + Weight_axe[1] * D[3] + Weight_axe[2] * D[5];
5028 
5029  std::multimap< int, int > Priority_map;
5030  std::multimap< int, int >::iterator it_reorder;
5031  for(int i = 0; i < 8; i++)
5032  Priority_map.insert(std::pair< int, int >(Priority[i], i));
5033 
5034  std::vector< int > Priority_reorder(8, 0);
5035 
5036  int Temp_priority = 0;
5038  bool Is_same_priority_value = false;
5039 
5040  it_reorder = Priority_map.begin();
5041  for(int i = 0; i < 7; i++)
5042  {
5043  int P0 = it_reorder->first;
5044  it_reorder++;
5045  int P1 = it_reorder->first;
5046 
5047  if(P0 == P1)
5048  Is_same_priority_value = true;
5049  }
5050 
5051  if(!Is_same_priority_value)
5052  {
5053  for(it_reorder = Priority_map.begin(); it_reorder != Priority_map.end();
5054  it_reorder++)
5055  {
5056  Priority_reorder[it_reorder->second] = 7 - Temp_priority;
5057  Temp_priority++;
5058  }
5059  }
5060  else
5061  {
5062  for(int i = 0; i < 8; i++)
5063  {
5064  Priority_reorder[i] = i;
5065  }
5066  }
5067 
5068  int Reordered_number = Decoder.decode(Under_quantization_model);
5069 
5070  for(int i = 0; i < 8; i++)
5071  {
5072  if(Priority_reorder[i] == Reordered_number)
5073  {
5074  put(this->vertex_Q_Index, v, i);
5075  break;
5076  }
5077  }
5078 
5079  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h;
5080  if(Vertex_index == 0)
5081  {
5082  h = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(v, _pMesh);
5083  do
5084  {
5085  h++;
5086  } while((*h) != (*hi));
5087  }
5088  else
5089  {
5090  int Comp_number = -2;
5091  h = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(v, _pMesh);
5092  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h2 = h;
5093  CGAL_For_all(h, h2)
5094  {
5095  if(get(this->Vertex_Number, target(opposite(*h, _pMesh), _pMesh)) >
5096  Comp_number)
5097  {
5098  Comp_number =
5099  get(this->Vertex_Number, target(opposite(*h, _pMesh), _pMesh));
5100  }
5101  }
5102 
5103  h = h2;
5104  CGAL_For_all(h, h2)
5105  {
5106  if(get(this->Vertex_Number, target(opposite(*h, _pMesh), _pMesh)) ==
5107  Comp_number)
5108  break;
5109  }
5110  }
5111 
5112  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h2 = h;
5113  CGAL_For_all(h, h2)
5114  {
5115  if(get(this->Vertex_Flag, target(opposite(*h, _pMesh), _pMesh)) == FREE)
5116  {
5117  verticesq.push(target(opposite(*h, _pMesh), _pMesh));
5118  }
5119  }
5120  Vertex_index++;
5121 
5122  delete[] Neighbors;
5123  }
5124  }
5125  vertex_iterator pVertex;
5126  for(pVertex = vertices(_pMesh).first; pVertex != vertices(_pMesh).second;
5127  pVertex++)
5128  {
5129  if(get(this->vertex_Component_Number, *pVertex) == Component_ID)
5130  {
5131  int Coeff[3] = { 0 };
5132  Get_Coefficient_Up_Quantization(get(this->vertex_Q_Index, *pVertex),
5133  Coeff);
5134  Point3d pt = get(*_pm, *pVertex);
5135  Point3d New_position(pt[0] + Coeff[0] * Small_step / 2,
5136  pt[1] + Coeff[1] * Small_step / 2,
5137  pt[2] + Coeff[2] * Small_step / 2);
5138  put(*_pm, *pVertex, New_position);
5139  }
5140  }
5141  this->Qbit[Component_ID]++;
5142  this->NumberChangeQuantization[Component_ID]--;
5143 }
5144 
5145 
5146 /* Description : ADAPTIVE_QUANTIZATION
5147 Decreasing of quantization resolution based on the prediction of PENG.
5148 Opposite function is up_quantization. */
5149 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
5150 void
5152  Diminush_Geometry_Quantization_Precision(HalfedgeGraph &_pMesh,
5153  const int &Component_ID,
5154  PointMap *_pm)
5155 {
5157 
5158  // stock three mins for the reconstruction.
5159  float _xmin = this->xmin[Component_ID];
5160  float _ymin = this->ymin[Component_ID];
5161  float _zmin = this->zmin[Component_ID];
5162 
5163  // Premier_Pas == distance d'un Quantization_Step de grill de quantification
5164  // (Q)
5165  double Small_step = 0.0;
5166 
5167  if(this->NumberChangeQuantization[Component_ID] == 0)
5168  Small_step = this->Quantization_Step[Component_ID];
5169 
5170  else
5171  Small_step = this->Quantization_Step[Component_ID] *
5172  std::pow(2.0, this->NumberChangeQuantization[Component_ID]);
5173 
5174  // Large_step == distance d'un Quantization_Step de grille de quantification(Q
5175  // - 1)
5176  double Large_step = Small_step * 2;
5177 
5178  // To find first points to start the conquest.
5179  auto halfedge_iterator_pair = halfedges(_pMesh);
5180  halfedge_iterator hi = halfedge_iterator_pair.first;
5181 
5182  while(
5183  (get(this->vertex_Seed_Edge, target(*hi, _pMesh)) != 2 * Component_ID) ||
5184  (get(this->vertex_Seed_Edge, target(opposite(*hi, _pMesh), _pMesh)) !=
5185  2 * Component_ID + 1))
5186  hi++;
5187 
5188  // Vertex_Flag est donnee free a tous les sommets
5189  for(vertex_iterator pVert = vertices(_pMesh).first;
5190  pVert != vertices(_pMesh).second;
5191  pVert++)
5192  {
5193  put(this->Vertex_Flag, *pVert, FREE);
5194  put(this->Vertex_Number, *pVert, -1);
5195  }
5196 
5197 
5198  // premiere passe pour sous quantifie et donne l'indice de symbol a chaque
5199  // sommet
5200  for(vertex_iterator pVert = vertices(_pMesh).first;
5201  pVert != vertices(_pMesh).second;
5202  pVert++)
5203  {
5204  if(get(this->vertex_Component_Number, *pVert) == Component_ID)
5205  {
5206  Point3d pt = get(*_pm, *pVert);
5207  double x = pt[0];
5208  double y = pt[1];
5209  double z = pt[2];
5210 
5211  // Qx, Qy, Qz sont des coordonnees avant under-Quantization
5212  int Qx = (int)(ceil((x - _xmin) / Small_step)) - 1;
5213  if(Qx == -1)
5214  Qx = 0;
5215  int Qy = (int)(ceil((y - _ymin) / Small_step)) - 1;
5216  if(Qy == -1)
5217  Qy = 0;
5218  int Qz = (int)(ceil((z - _zmin) / Small_step)) - 1;
5219  if(Qz == -1)
5220  Qz = 0;
5221 
5222  // Les coordonnees apres under-quantization
5223  int Second_Qx = Qx / 2;
5224  int Second_Qy = Qy / 2;
5225  int Second_Qz = Qz / 2;
5226 
5227  int i = Qx % 2;
5228  int j = Qy % 2;
5229  int k = Qz % 2;
5230 
5231  int Q_index = Get_Correct_Vector(i, j, k);
5232  put(this->vertex_Q_Index, *pVert, Q_index);
5233 
5234  // Les sommets sont deplaces vers le centre de cellule mere.
5235  put(*_pm,
5236  *pVert,
5237  Point3d(_xmin + (Second_Qx + 0.5) * Large_step,
5238  _ymin + (Second_Qy + 0.5) * Large_step,
5239  _zmin + (Second_Qz + 0.5) * Large_step));
5240  }
5241  }
5242 
5244  //_pMesh.compute_normals();
5245 
5246  std::queue< vertex_descriptor > vertices;
5247 
5248  std::list< int > Layer_symbols;
5249 
5250  // push a input gate to begin loop
5251  // in order to treat all vertices.
5252 
5253  vertices.push(target(*hi, _pMesh));
5254  vertices.push(target(opposite(*hi, _pMesh), _pMesh));
5255 
5256  int Vertex_index = 0;
5257 
5258 
5259  while(!vertices.empty())
5260  {
5261  vertex_descriptor v = vertices.front();
5262  vertices.pop();
5263 
5264  if(get(this->Vertex_Flag, v) == CONQUERED)
5265  continue;
5266 
5267  else
5268  {
5269  put(this->Vertex_Flag, v, CONQUERED);
5270  put(this->Vertex_Number, v, Vertex_index);
5271 
5272  int Q_index = get(this->vertex_Q_Index, v);
5273  unsigned Count_neighbor = 0;
5274  unsigned valence = out_degree(v, _pMesh);
5275 
5276  Point3d *Neighbors = new Point3d[valence];
5277  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > hvc =
5278  CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(v, _pMesh);
5279  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > phvc = hvc;
5280 
5281  CGAL_For_all(hvc, phvc)
5282  {
5283  Neighbors[Count_neighbor] =
5284  get(*_pm, target(opposite(*hvc, _pMesh), _pMesh));
5285  Count_neighbor++;
5286  }
5287 
5288  Point3d Center = get(*_pm, v);
5289 
5290  std::vector< int > D(6, 0);
5291 
5292  for(unsigned i = 0; i < valence; i++)
5293  {
5294  Vector Vect =
5295  FEVV::Math::Vector::sub< FEVV::Geometry_traits< HalfedgeGraph > >(
5296  Neighbors[i], Center, gt);
5297 
5298  if(Vect[0] <= 0)
5299  {
5300  int I_dist = Vect[0] / Small_step / 2;
5301  D[0] += std::abs(I_dist);
5302  }
5303  else
5304  {
5305  int I_dist = Vect[0] / Small_step / 2;
5306  D[1] += std::abs(I_dist);
5307  }
5308 
5309  if(Vect[1] <= 0)
5310  {
5311  int I_dist = Vect[1] / Small_step / 2;
5312  D[2] += std::abs(I_dist);
5313  }
5314  else
5315  {
5316  int I_dist = Vect[1] / Small_step / 2;
5317  D[3] += std::abs(I_dist);
5318  }
5319 
5320  if(Vect[2] <= 0)
5321  {
5322  int I_dist = Vect[2] / Small_step / 2;
5323  D[4] += std::abs(I_dist);
5324  }
5325  else
5326  {
5327  int I_dist = Vect[2] / Small_step / 2;
5328  D[5] += std::abs(I_dist);
5329  }
5330  }
5331 
5332  std::vector< double > U(3, 0);
5333  U[0] = std::abs((double)D[0] / (double)(D[0] + D[1]) - 0.5);
5334  U[1] = std::abs((double)D[2] / (double)(D[2] + D[3]) - 0.5);
5335  U[2] = std::abs((double)D[4] / (double)(D[4] + D[5]) - 0.5);
5336 
5337  std::multimap< double, int > U_order;
5338  U_order.insert(std::pair< double, int >(U[0], 0));
5339  U_order.insert(std::pair< double, int >(U[1], 1));
5340  U_order.insert(std::pair< double, int >(U[2], 2));
5341 
5342  std::multimap< double, int >::iterator it;
5343 
5344  std::vector< int > Weight_axe(3, 0);
5345  int Temp_weight = 1;
5346  for(it = U_order.begin(); it != U_order.end(); it++)
5347  {
5348  Weight_axe[it->second] = Temp_weight;
5349  Temp_weight++;
5350  }
5351 
5352  std::vector< int > Priority(8, 0);
5353  Priority[0] =
5354  Weight_axe[0] * D[0] + Weight_axe[1] * D[2] + Weight_axe[2] * D[4];
5355  Priority[1] =
5356  Weight_axe[0] * D[1] + Weight_axe[1] * D[2] + Weight_axe[2] * D[4];
5357  Priority[2] =
5358  Weight_axe[0] * D[0] + Weight_axe[1] * D[3] + Weight_axe[2] * D[4];
5359  Priority[3] =
5360  Weight_axe[0] * D[1] + Weight_axe[1] * D[3] + Weight_axe[2] * D[4];
5361  Priority[4] =
5362  Weight_axe[0] * D[0] + Weight_axe[1] * D[2] + Weight_axe[2] * D[5];
5363  Priority[5] =
5364  Weight_axe[0] * D[1] + Weight_axe[1] * D[2] + Weight_axe[2] * D[5];
5365  Priority[6] =
5366  Weight_axe[0] * D[0] + Weight_axe[1] * D[3] + Weight_axe[2] * D[5];
5367  Priority[7] =
5368  Weight_axe[0] * D[1] + Weight_axe[1] * D[3] + Weight_axe[2] * D[5];
5369 
5370  std::multimap< int, int > Priority_map;
5371  std::multimap< int, int >::iterator it_reorder;
5372  for(int i = 0; i < 8; i++)
5373  Priority_map.insert(std::pair< int, int >(Priority[i], i));
5374 
5375  std::vector< int > Priority_reorder(8, 0);
5376 
5377  int Temp_priority = 0;
5378  bool Is_same_priority_value = false;
5379 
5380  it_reorder = Priority_map.begin();
5381  for(int i = 0; i < 7; i++)
5382  {
5383  int P0 = it_reorder->first;
5384  it_reorder++;
5385  int P1 = it_reorder->first;
5386 
5387  if(P0 == P1)
5388  Is_same_priority_value = true;
5389  }
5390 
5391  if(!Is_same_priority_value)
5392  {
5393  for(it_reorder = Priority_map.begin(); it_reorder != Priority_map.end();
5394  it_reorder++)
5395  {
5396  Priority_reorder[it_reorder->second] = 7 - Temp_priority;
5397  Temp_priority++;
5398  }
5399  }
5400  else
5401  {
5402  for(int i = 0; i < 8; i++)
5403  {
5404  Priority_reorder[i] = i;
5405  }
5406  }
5407 
5408  int Reordered_number = Priority_reorder[Q_index];
5409 
5410  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h;
5411 
5412  // First_vertex -> To find the seed edge
5413  if(Vertex_index == 0)
5414  {
5415  h = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(v, _pMesh);
5416  do
5417  {
5418  h++;
5419  } while((*h) != (*hi));
5420  }
5421 
5422  else
5423  {
5424  int Comp_number = -2;
5425  h = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(v, _pMesh);
5426  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h2 = h;
5427  CGAL_For_all(h, h2)
5428  {
5429  if(get(this->Vertex_Number, target(opposite(*h, _pMesh), _pMesh)) >
5430  Comp_number)
5431  Comp_number =
5432  get(this->Vertex_Number, target(opposite(*h, _pMesh), _pMesh));
5433  }
5434 
5435  h = h2;
5436  CGAL_For_all(h, h2)
5437  {
5438  if(get(this->Vertex_Number, target(opposite(*h, _pMesh), _pMesh)) ==
5439  Comp_number)
5440  break;
5441  }
5442  }
5443 
5444  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h2 = h;
5445  CGAL_For_all(h, h2)
5446  {
5447  if(get(this->Vertex_Flag, target(opposite(*h, _pMesh), _pMesh)) == FREE)
5448  vertices.push(target(opposite(*h, _pMesh), _pMesh));
5449  }
5450  Vertex_index++;
5451 
5452  delete[] Neighbors;
5453  Layer_symbols.push_front(Reordered_number);
5454  }
5455  }
5456 
5457  this->NumberQuantizationLayer[Component_ID].push_front(Layer_symbols.size());
5458  while(!Layer_symbols.empty())
5459  {
5460  int index = Layer_symbols.front();
5461  Layer_symbols.pop_front();
5462 
5463  this->QuantizationCorrectVector[Component_ID].push_front(index);
5464  }
5465 }
5466 
5467 
5468 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
5469 void
5471  Decompress_Init(HalfedgeGraph &_pMesh,
5472  PointMap *_pm,
5473  VertexColorMap *_v_cm,
5474  bool &has_color,
5475  const std::string &Input_File_Name)
5476 {
5477  this->File_name = Input_File_Name;
5478 
5479  if(FILE *file2 = fopen(this->File_name.c_str(), "r"))
5480  {
5481  fseek(file2, 0, SEEK_END);
5482  this->Compressed_file_size = ftell(file2);
5483  fclose(file2);
5484  }
5485  else
5486  {
5487  throw std::runtime_error("Error: failed to open file '" + this->File_name +
5488  "'.");
5489  }
5490 
5491  CGAL::clear(_pMesh);
5492 
5493  this->IsClosed.clear();
5494  this->Qbit.clear();
5495  this->xmin.clear();
5496  this->ymin.clear();
5497  this->zmin.clear();
5498  this->Quantization_Step.clear();
5499  this->NumberColorQuantization.clear();
5500  this->NumberChangeQuantization.clear();
5501  this->ComponentOperations.clear();
5502 
5503  this->Decompress_count = 0;
5504 
5505  // ELO note:
5506  // the .p3d input file is opened here
5507  // and remains open at the end of the function
5508  // for further reading
5509  FILE *fp = fopen(this->File_name.c_str(), "rb");
5510 
5511  this->DM_JCW_MOVE_ERROR.set_alphabet(3);
5512 
5513  int res;
5514 
5515  res = fread(&this->Smallest_Alpha, sizeof(int), 1, fp);
5516  res = fread(&this->Smallest_Gamma, sizeof(int), 1, fp);
5517  res = fread(&this->Initial_file_size, sizeof(unsigned), 1, fp);
5518  res = fread(&this->NumberComponents, sizeof(int), 1, fp);
5519 
5520  float Qpas;
5521  float t_xmin, t_ymin, t_zmin;
5522 
5523  // Read geometry information for each component;
5524  for(int i = 0; i < this->NumberComponents; i++)
5525  {
5526  res = fread(&Qpas, sizeof(float), 1, fp); // quantization step
5527  res = fread(&t_xmin, sizeof(float), 1, fp); // x_min
5528  res = fread(&t_ymin, sizeof(float), 1, fp); // y_min
5529  res = fread(&t_zmin, sizeof(float), 1, fp); // z_min
5530 
5531  this->Quantization_Step.push_back(Qpas);
5532  this->xmin.push_back(t_xmin);
5533  this->ymin.push_back(t_ymin);
5534  this->zmin.push_back(t_zmin);
5535  }
5536 
5537  char Colored, One_color;
5538  res = fread(&Colored, sizeof(char), 1, fp);
5539 
5540  this->IsOneColor = false;
5541  if(Colored == 1)
5542  {
5543  this->IsColored = true;
5544  res = fread(&One_color, sizeof(char), 1, fp);
5545  if(One_color == 1)
5546  this->IsOneColor = true;
5547  }
5548  else
5549  this->IsColored = false;
5550 
5551  // set color flag for calling function
5552  has_color = this->IsColored;
5553 
5554  // read color information for each component
5555  if((this->IsColored) && (!this->IsOneColor))
5556  {
5557  res = fread(&this->Color_Quantization_Step, sizeof(float), 1, fp);
5558 
5559  res = fread(&this->C0_Min,
5560  sizeof(float),
5561  1,
5562  fp); // smallest absolute position of c0
5563  res = fread(&this->C1_Min,
5564  sizeof(float),
5565  1,
5566  fp); // smallest absolute position of c1
5567  res = fread(&this->C2_Min,
5568  sizeof(float),
5569  1,
5570  fp); // smallest absolute position of c2
5571 
5572  res = fread(
5573  &this->Smallest_C0, sizeof(int), 1, fp); // smallest quantized positions
5574  res = fread(&this->Smallest_C1, sizeof(int), 1, fp);
5575  res = fread(&this->Smallest_C2, sizeof(int), 1, fp);
5576  }
5577 
5578  if((this->IsColored) && (this->IsOneColor))
5579  {
5580  res = fread(&this->OnlyColor[0],
5581  sizeof(float),
5582  1,
5583  fp); // smallest absolute position of c0
5584  res = fread(
5585  &this->OnlyColor[1], sizeof(float), 1, fp); // smallest value of c1
5586  res = fread(
5587  &this->OnlyColor[2], sizeof(float), 1, fp); // smallest value of c2
5588  }
5589  this->Decoder.set_buffer(AC_BUFFER);
5590  this->Decoder.read_from_file(fp);
5591 
5592  res += 0; // just to avoid gcc 4.6 warning
5593 
5594  // To know if each component is colored or not, and closed of not.
5595  for(int i = 0; i < this->NumberComponents; i++)
5596  {
5597  if(Decoder.get_bits(1) == 0)
5598  this->IsClosed.push_back(true);
5599  else
5600  this->IsClosed.push_back(false);
5601  }
5602 
5603  if(Decoder.get_bits(1) == 1)
5604  this->Is_Bijection_Enabled = true;
5605  else
5606  this->Is_Bijection_Enabled = false;
5607 
5608  this->GlobalCountOperation = -1;
5609 
5610  unsigned Max_Qbit = 0;
5611  for(int i = 0; i < this->NumberComponents; i++)
5612  {
5613  int Number_operation = Decoder.get_bits(8); // Number of total operations.
5614  this->ComponentOperations.push_back(Number_operation);
5615 
5616  if(Number_operation > this->GlobalCountOperation)
5617  this->GlobalCountOperation = Number_operation;
5618 
5619  int Qbit = Decoder.get_bits(4); // Initial quantization bit of geometry
5620  Qbit += 4;
5621  this->Qbit.push_back(Qbit);
5622 
5623  int NCQ = Decoder.get_bits(4); // Number of change of geometry quantization
5624  this->NumberChangeQuantization.push_back(NCQ);
5625 
5626  int Number_color_quantization_change =
5627  Decoder.get_bits(3); // Number of change of color quantization
5628  this->NumberColorQuantization.push_back(Number_color_quantization_change);
5629 
5630  if(this->Qbit[i] > Max_Qbit)
5631  Max_Qbit = this->Qbit[i];
5632  }
5633 
5634  int Number_basemesh_vertex =
5635  Decoder.get_bits(15); // Number of vertices of base mesh
5636  int Number_basemesh_facet =
5637  Decoder.get_bits(16); // Number of facets of base mesh
5638 
5639  // Vectors for generation of base mesh
5640  std::vector< Point3d > vlist;
5641  std::vector< int > flist;
5642  std::vector< float > clist;
5643  std::vector< int > Color_index_list;
5644 
5645  for(int i = 0; i < Number_basemesh_vertex; i++)
5646  {
5647  Point_Int Pt_int;
5648  Pt_int.x = Decoder.get_bits(Max_Qbit + 1); // Read geometry info
5649  Pt_int.y = Decoder.get_bits(Max_Qbit + 1);
5650  Pt_int.z = Decoder.get_bits(Max_Qbit + 1);
5651 
5652  // All vertices have quantization precision of component 0
5653  // That'll be corrected below.
5654  Point3d Pt_real = Change_Int_Real(Pt_int, 0);
5655  vlist.push_back(Pt_real);
5656 
5657  if((this->IsColored) && (!this->IsOneColor))
5658  {
5659  //#ifdef PREDICTION_METHOD
5660 
5661  Color_Unit TC;
5662  TC.c0 = Decoder.get_bits(C0_QUANTIZATION); // Read color info.
5663  TC.c1 = Decoder.get_bits(C1_QUANTIZATION);
5664  TC.c2 = Decoder.get_bits(C2_QUANTIZATION);
5665 
5666  float L = this->C0_Min + TC.c0 * this->Color_Quantization_Step;
5667  float a = this->C1_Min + TC.c1 * this->Color_Quantization_Step;
5668  float b = this->C2_Min + TC.c2 * this->Color_Quantization_Step;
5669 
5670  clist.push_back(L);
5671  clist.push_back(a);
5672  clist.push_back(b);
5673  // #endif
5674  }
5675  }
5676 
5677  // Read connectivity information
5678  int Facet_index_bit =
5679  (int)ceil(log((double)(Number_basemesh_vertex + 1)) / log((double)2));
5680 
5681  for(int i = 0; i < (Number_basemesh_facet * 3); i++)
5682  {
5683  int v = Decoder.get_bits(Facet_index_bit);
5684  flist.push_back(v);
5685  }
5686 
5687  // Generation of base mesh
5688  build_mesh(_pMesh, _pm, _v_cm, vlist, flist, clist, Color_index_list);
5689 
5690  compute_normals(_pMesh, _pm);
5691 
5692  // Seed Edges;
5693  std::map< int, int > Seed_Edges;
5694 
5695  for(int i = 0; i < 2 * this->NumberComponents; i++)
5696  {
5697  int Vertex_number = Decoder.get_bits(Facet_index_bit);
5698  Seed_Edges.insert(std::pair< int, int >(Vertex_number, i));
5699  }
5700 
5701  int Basemesh_vertex_number = 0;
5702 
5703  vertex_iterator pVertex;
5704 
5705  std::map< int, int >::iterator Seed_edge_iterator = Seed_Edges.begin();
5706 
5707  int Count_detected_vertices = 0;
5708  for(pVertex = vertices(_pMesh).first; pVertex != vertices(_pMesh).second;
5709  Basemesh_vertex_number++, pVertex++)
5710  {
5711  if(Count_detected_vertices < this->NumberComponents * 2)
5712  {
5713  if(Basemesh_vertex_number == Seed_edge_iterator->first)
5714  {
5715  put(this->vertex_Seed_Edge, *pVertex, Seed_edge_iterator->second);
5716  Seed_edge_iterator++;
5717  Count_detected_vertices++;
5718  }
5719  }
5720  else
5721  put(this->vertex_Seed_Edge, *pVertex, OTHER_COORDINATE);
5722 
5723  put(this->vertex_Component_Number, *pVertex, -1);
5724  }
5725 
5726  /*float C0_min = this->C0_Min;
5727  float C1_min = this->C1_Min;
5728  float C2_min = this->C2_Min;*/
5729 
5730  float Color_small_step = 0.0;
5731 
5732  if((this->IsColored) && (!this->IsOneColor))
5733  {
5734  // ELO useless ?
5735  for(pVertex = vertices(_pMesh).first; pVertex != vertices(_pMesh).second;
5736  pVertex++)
5737  {
5738  /*float LAB[3];
5739  LAB[0] = pVertex->color(0);
5740  LAB[1] = pVertex->color(1);
5741  LAB[2] = pVertex->color(2);
5742 
5743  float RGB[3];
5744  LAB_To_RGB(LAB[0], LAB[1], LAB[2], RGB);
5745  pVertex->color(RGB[0], RGB[1], RGB[2]); */
5746  }
5747 
5748  this->C0_Range = Decoder.get_bits(C0_QUANTIZATION + 1);
5749  this->Color_0_Model.set_alphabet(this->C0_Range);
5750  this->C1_Range = Decoder.get_bits(C1_QUANTIZATION + 1);
5751  this->Color_1_Model.set_alphabet(this->C1_Range);
5752  this->C2_Range = Decoder.get_bits(C2_QUANTIZATION + 1);
5753  this->Color_2_Model.set_alphabet(this->C2_Range);
5754  }
5755  if((this->IsColored) && (this->IsOneColor))
5756  {
5757  for(pVertex = vertices(_pMesh).first; pVertex != vertices(_pMesh).second;
5758  pVertex++)
5759  {
5760  typedef
5761  typename boost::property_traits< VertexColorMap >::value_type Color;
5762  put(*_v_cm,
5763  *pVertex,
5764  Color(this->OnlyColor[0], this->OnlyColor[1], this->OnlyColor[2]));
5765  }
5766  }
5767 
5768  // To get number of vertices of each component and restore the real position
5769  // of vertices
5770  // if (this->NumberComponents != 1)
5771  {
5772  for(face_iterator pFacet = faces(_pMesh).first;
5773  pFacet != faces(_pMesh).second;
5774  ++pFacet)
5775  {
5776  put(this->facet_tag, *pFacet, -1);
5777  }
5778  int Component_index = 0;
5779 
5780  for(int Component_number = 0; Component_number < this->NumberComponents;
5781  Component_number++)
5782  {
5783  halfedge_iterator hi = halfedges(_pMesh).first;
5784 
5785  while(
5786  (get(this->vertex_Seed_Edge, target(*hi, _pMesh)) !=
5787  2 * Component_number) ||
5788  (get(this->vertex_Seed_Edge, target(opposite(*hi, _pMesh), _pMesh)) !=
5789  2 * Component_number + 1))
5790  hi++;
5791 
5792  face_descriptor fh = face(*hi, _pMesh);
5793  put(this->facet_tag, fh, Component_index);
5794 
5795  std::list< face_descriptor > facets;
5796  facets.push_front(fh);
5797 
5798  while(!facets.empty())
5799  {
5800  face_descriptor F = facets.front();
5801  facets.pop_front();
5802 
5803  put(this->facet_tag, F, Component_index);
5804 
5805  CGAL::Halfedge_around_face_circulator< HalfedgeGraph > pHalfedge =
5806  CGAL::Halfedge_around_face_circulator< HalfedgeGraph >(
5807  halfedge(F, _pMesh), _pMesh);
5808  CGAL::Halfedge_around_face_circulator< HalfedgeGraph > end = pHalfedge;
5809 
5810  CGAL_For_all(pHalfedge, end)
5811  {
5812  // tag the vertex to its corresponding component number
5813  if(get(this->vertex_Component_Number, target(*pHalfedge, _pMesh)) ==
5814  -1)
5815  {
5816  put(this->vertex_Component_Number,
5817  target(*pHalfedge, _pMesh),
5818  Component_index);
5819  Point3d Wrong_position = get(*_pm, target(*pHalfedge, _pMesh));
5820 
5821  // The correct position of vertex is restored.
5822  Point_Int Temp_pos = Change_Real_Int(Wrong_position, 0);
5823  Point3d Real_position = Change_Int_Real(Temp_pos, Component_number);
5824 
5825  put(*_pm, target(*pHalfedge, _pMesh), Real_position);
5826 
5827  float Wrong_LAB[3];
5828  Wrong_LAB[0] = get(*_v_cm, target(*pHalfedge, _pMesh))[0];
5829  Wrong_LAB[1] = get(*_v_cm, target(*pHalfedge, _pMesh))[1];
5830  Wrong_LAB[2] = get(*_v_cm, target(*pHalfedge, _pMesh))[2];
5831 
5832  int Original_LAB[3];
5833  Original_LAB[0] = (int)floor((Wrong_LAB[0] - this->C0_Min) /
5834  this->Color_Quantization_Step +
5835  0.5);
5836  Original_LAB[1] = (int)floor((Wrong_LAB[1] - this->C1_Min) /
5837  this->Color_Quantization_Step +
5838  0.5);
5839  Original_LAB[2] = (int)floor((Wrong_LAB[2] - this->C2_Min) /
5840  this->Color_Quantization_Step +
5841  0.5);
5842 
5843  put(this->vertex_color_int,
5844  target(*pHalfedge, _pMesh),
5845  Color_Unit(Original_LAB[0], Original_LAB[1], Original_LAB[2]));
5846 
5847  if(this->NumberColorQuantization[Component_number] == 0)
5848  Color_small_step = this->Color_Quantization_Step;
5849  else
5850  Color_small_step =
5851  this->Color_Quantization_Step *
5852  std::pow(2.0,
5853  this->NumberColorQuantization[Component_number]);
5854 
5855  float RGB[3];
5856  float LAB[3];
5857  LAB[0] = this->C0_Min + Original_LAB[0] * Color_small_step;
5858  LAB[1] = this->C1_Min + Original_LAB[1] * Color_small_step;
5859  LAB[2] = this->C2_Min + Original_LAB[2] * Color_small_step;
5860 
5861  LAB_To_RGB(LAB[0], LAB[1], LAB[2], RGB);
5862  typedef
5863  typename boost::property_traits< VertexColorMap >::value_type
5864  Color;
5865  put(*_v_cm,
5866  target(*pHalfedge, _pMesh),
5867  Color(RGB[0], RGB[1], RGB[2]));
5868  }
5869 
5870  face_descriptor pNFacet = face(opposite(*pHalfedge, _pMesh), _pMesh);
5871  if(pNFacet != boost::graph_traits< HalfedgeGraph >::null_face() &&
5872  get(this->facet_tag, pNFacet) == -1)
5873  {
5874  facets.push_front(pNFacet);
5875  put(this->facet_tag, pNFacet, Component_index);
5876  }
5877  }
5878  }
5879  // this->ComponentNumberVertices.push_back(Number_vertices);
5880  Component_index++;
5881  }
5882  }
5883 
5884  this->IsDecompress = true;
5885  this->Current_level = 0;
5886  // this->Initial_file_size = _Initial_file_size;
5887  this->Total_layer = this->GlobalCountOperation;
5888 
5889 
5890  float prog = (float)this->Calculate_Current_File_Size() /
5891  this->Compressed_file_size * 100;
5892  float ratio = 0;
5893  if(this->Initial_file_size != 0)
5894  ratio = 1 / ((float)this->Calculate_Current_File_Size() /
5895  this->Initial_file_size);
5896 
5897  std::ostringstream infos_tmp;
5898  infos_tmp << "Number of all levels : ";
5899  infos_tmp << int(this->Total_layer);
5900  infos_tmp << " | ";
5901  infos_tmp << std::setw(3) << prog;
5902  infos_tmp << " | ";
5903  infos_tmp << std::setw(3) << ratio;
5904  std::string infos(infos_tmp.str());
5905 
5906  this->Prog.clear();
5907  this->Prog.push_back(prog);
5908  this->Ratio.clear();
5909  this->Ratio.push_back(ratio);
5910 
5911  std::cout << infos << std::endl;
5912 }
5913 
5914 
5915 //#define DBG_Decompress_Each_Step
5916 
5917 // Description : To decode step by step - show intermediate meshes
5918 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
5919 int
5921  Decompress_Each_Step(HalfedgeGraph &_pMesh,
5922  PointMap *_pm,
5923  VertexColorMap *_v_cm)
5924 {
5925  if(this->Decompress_count < this->GlobalCountOperation)
5926  {
5927  for(int Component_ID = 0; Component_ID < this->NumberComponents;
5928  Component_ID++)
5929  {
5930  if(this->Decompress_count < this->ComponentOperations[Component_ID])
5931  {
5932  int Operation = Decoder.get_bits(2);
5933  if(Operation == 0)
5934  {
5935 #ifdef DBG_Decompress_Each_Step
5936  std::cout << "DBG in " << __func__
5937  << " Decompress_count=" << this->Decompress_count
5938  << " Component_ID=" << Component_ID
5939  << " Operation=" << Operation << std::endl;
5940  DBG_print_mesh_geometry(_pMesh, _pm, "before Un_Regulation");
5941  DBG_print_mesh_vertexcolor(_pMesh, _v_cm, "before Un_Regulation");
5942 #endif
5943 
5944  this->Un_Regulation(_pMesh, Decoder, Component_ID, _pm, _v_cm);
5945 
5946 #ifdef DBG_Decompress_Each_Step
5947  DBG_print_mesh_geometry(_pMesh, _pm, "after Un_Regulation");
5948  DBG_print_mesh_vertexcolor(_pMesh, _v_cm, "after Un_Regulation");
5949 #endif
5950 
5951  this->Un_Decimation_Conquest(
5952  _pMesh, Decoder, Component_ID, _pm, _v_cm);
5953 
5954 #ifdef DBG_Decompress_Each_Step
5955  DBG_print_mesh_geometry(_pMesh, _pm, "after Un_Decimation_Conquest");
5956  DBG_print_mesh_vertexcolor(
5957  _pMesh, _v_cm, "after Un_Decimation_Conquest");
5958 #endif
5959  }
5960  else if(Operation == 1)
5961  {
5962  this->Augment_Geometry_Quantization_Precision(
5963  _pMesh, Decoder, Component_ID, _pm);
5964 
5965 #ifdef DBG_Decompress_Each_Step
5966  std::cout << "DBG in " << __func__
5967  << " Decompress_count=" << this->Decompress_count
5968  << " Component_ID=" << Component_ID
5969  << " Operation=" << Operation << std::endl;
5970  DBG_print_mesh_geometry(
5971  _pMesh, _pm, "after Augment_Geometry_Quantization_Precision");
5972  DBG_print_mesh_vertexcolor(
5973  _pMesh, _v_cm, "after Augment_Geometry_Quantization_Precision");
5974 #endif
5975  }
5976  else if(Operation == 2)
5977  {
5978  this->Augment_Color_Quantization_Precision(
5979  _pMesh, Decoder, Component_ID, _v_cm);
5980 
5981 #ifdef DBG_Decompress_Each_Step
5982  std::cout << "DBG in " << __func__
5983  << " Decompress_count=" << this->Decompress_count
5984  << " Component_ID=" << Component_ID
5985  << " Operation=" << Operation << std::endl;
5986  DBG_print_mesh_geometry(
5987  _pMesh, _pm, "after Augment_Color_Quantization_Precision");
5988  DBG_print_mesh_vertexcolor(
5989  _pMesh, _v_cm, "after Augment_Color_Quantization_Precision");
5990 #endif
5991  }
5992  }
5993  }
5994  }
5995 
5996  this->Decompress_count++;
5997  compute_normals(_pMesh, _pm);
5998 
5999  return this->Decompress_count;
6000  //
6002  // //
6003  // WIP WIP WIP WIPWIP //
6004  // WIP WIP WIP WIP //
6005  // WIP WIP WIP WIPWIP //
6006  // WIP WIP WIP WIP WIP //
6007  // WIP WIP WIP WIP //
6008  // //
6010  //
6011  //
6012  //
6013  // std::cout << "fixme here: " << __FILE__ << ":" << __LINE__ << " in " <<
6014  // __func__ << std::endl;
6015 }
6016 
6017 
6018 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
6019 void
6021  Augment_Color_Quantization_Precision(HalfedgeGraph &_pMesh,
6022  Arithmetic_Codec &Decoder,
6023  const int &_Component_ID,
6024  VertexColorMap *_v_cm)
6025 {
6026  Adaptive_Data_Model *Color_quantization_model =
6028  for(int i = 0; i < COLOR_NUMBER; i++)
6029  Color_quantization_model[i].set_alphabet(8);
6030 
6031  /*float C0_min = this->C0_Min;
6032  float C1_min = this->C1_Min;
6033  float C2_min = this->C2_Min;*/
6034 
6035  float Color_small_step = 0.0;
6036  float Color_large_step = 0.0;
6037 
6038  // define quantization step for (QC = large step) and (QC+1 = small_step)
6039  if(this->NumberColorQuantization[_Component_ID] == 0)
6040  Color_large_step = this->Color_Quantization_Step;
6041  else
6042  Color_large_step =
6043  this->Color_Quantization_Step *
6044  std::pow(2.0, this->NumberColorQuantization[_Component_ID]);
6045 
6046  Color_small_step = Color_large_step / (float)2.0;
6047 
6048  // To find first points to start the conquest.
6049  halfedge_iterator hi = halfedges(_pMesh).first;
6050 
6051  while(
6052  (get(this->vertex_Seed_Edge, target(*hi, _pMesh)) != 2 * _Component_ID) ||
6053  (get(this->vertex_Seed_Edge, target(opposite(*hi, _pMesh), _pMesh)) !=
6054  2 * _Component_ID + 1))
6055  hi++;
6056 
6057  // Vertex_Flag est donnee free a tous les sommets
6058  for(vertex_iterator pVert = vertices(_pMesh).first;
6059  pVert != vertices(_pMesh).second;
6060  pVert++)
6061  {
6062  put(this->Vertex_Flag, *pVert, FREE);
6063  put(this->Vertex_Number, *pVert, -1);
6064  put(this->vertex_Component_Number, *pVert, -1);
6065  }
6066 
6067  // Generation of color table
6068  std::vector< std::vector< int > > Color_table;
6069 
6070  std::queue< vertex_descriptor > verticesq;
6071  // push a input gate to begin loop
6072  // in order to treat all vertices.
6073  verticesq.push(target(*hi, _pMesh));
6074  verticesq.push(target(opposite(*hi, _pMesh), _pMesh));
6075 
6076  int Vertex_index = 0;
6077 
6078  while(!verticesq.empty())
6079  {
6080  vertex_descriptor v = verticesq.front();
6081  verticesq.pop();
6082 
6083  if(get(this->Vertex_Flag, v) == CONQUERED)
6084  continue;
6085 
6086  else
6087  {
6088  put(this->Vertex_Flag, v, CONQUERED);
6089  put(this->Vertex_Number, v, Vertex_index);
6090  put(this->vertex_Component_Number, v, _Component_ID);
6091 
6092  std::vector< int > LAB;
6093 
6094  Color_Unit color = get(this->vertex_color_int, v);
6095  LAB.push_back(color.c0);
6096  LAB.push_back(color.c1);
6097  LAB.push_back(color.c2);
6098 
6099  bool Is_existed_color = false;
6100 
6101  int Color_index = -1;
6102 
6103  // Color table creation
6104  for(int i = 0; i < (int)Color_table.size(); i++)
6105  {
6106  if((LAB[0] == Color_table[i][0]) && (LAB[1] == Color_table[i][1]) &&
6107  (LAB[2] == Color_table[i][2]))
6108  {
6109  Is_existed_color = true;
6110  Color_index = Decoder.decode(Color_quantization_model[i]);
6111 
6112  break;
6113  }
6114  }
6115 
6116  if(Is_existed_color == false)
6117  {
6118  Color_index =
6119  Decoder.decode(Color_quantization_model[Color_table.size()]);
6120  Color_table.push_back(LAB);
6121  }
6122 
6123  put(this->vertex_Q_Index, v, Color_index);
6124 
6125  // unsigned Count_neighbor = 0;
6126  // unsigned valence = v->vertex_degree();
6127 
6128  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h;
6129 
6130  // First_vertex -> To find the seed edge
6131  if(Vertex_index == 0)
6132  {
6133  h = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(v, _pMesh);
6134  do
6135  {
6136  h++;
6137  } while((*h) != (*hi));
6138  }
6139 
6140  // Synchronization proble = find an deterministic order using the vertex
6141  // with the highest vertex number
6142  else
6143  {
6144  int Comp_number = -2;
6145  h = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(v, _pMesh);
6146  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h2 = h;
6147  CGAL_For_all(h, h2)
6148  {
6149  if(get(this->Vertex_Number, target(opposite(*h, _pMesh), _pMesh)) >
6150  Comp_number)
6151  Comp_number =
6152  get(this->Vertex_Number, target(opposite(*h, _pMesh), _pMesh));
6153  }
6154 
6155  h = h2;
6156  CGAL_For_all(h, h2)
6157  {
6158  if(get(this->Vertex_Number, target(opposite(*h, _pMesh), _pMesh)) ==
6159  Comp_number)
6160  break;
6161  }
6162  }
6163 
6164  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > h2 = h;
6165  CGAL_For_all(h, h2)
6166  {
6167  if(get(this->Vertex_Flag, target(opposite(*h, _pMesh), _pMesh)) == FREE)
6168  verticesq.push(target(opposite(*h, _pMesh), _pMesh));
6169  }
6170  Vertex_index++;
6171  }
6172  }
6173 
6174  // Here, we increase a bit of quantization precision of corresponding
6175  // component
6176  for(vertex_iterator pVert = vertices(_pMesh).first;
6177  pVert != vertices(_pMesh).second;
6178  pVert++)
6179  {
6180  if(get(this->vertex_Component_Number, *pVert) == _Component_ID)
6181  {
6182  int Coeff[3] = { 0 };
6183  Get_Coefficient_Up_Quantization(get(this->vertex_Q_Index, *pVert), Coeff);
6184 
6185  Color_Unit color = get(this->vertex_color_int, *pVert);
6186  int LAB_init_C0 = color.c0;
6187  int LAB_init_C1 = color.c1;
6188  int LAB_init_C2 = color.c2;
6189 
6190  // Each coordinate is multiplied by 2
6191  int LAB_final_C0 = LAB_init_C0 * 2;
6192  int LAB_final_C1 = LAB_init_C1 * 2;
6193  int LAB_final_C2 = LAB_init_C2 * 2;
6194 
6195  // We sum the childcell index to restore true color
6196  if(Coeff[0] == 1)
6197  LAB_final_C0 += 1;
6198  if(Coeff[1] == 1)
6199  LAB_final_C1 += 1;
6200  if(Coeff[2] == 1)
6201  LAB_final_C2 += 1;
6202 
6203  put(this->vertex_color_int,
6204  *pVert,
6205  Color_Unit(LAB_final_C0, LAB_final_C1, LAB_final_C2));
6206 
6207  float Inter_color[3];
6208  float RGB[3];
6209 
6210  Inter_color[0] = this->C0_Min + LAB_final_C0 * Color_small_step;
6211  Inter_color[1] = this->C1_Min + LAB_final_C1 * Color_small_step;
6212  Inter_color[2] = this->C2_Min + LAB_final_C2 * Color_small_step;
6213 
6214  LAB_To_RGB(Inter_color[0], Inter_color[1], Inter_color[2], RGB);
6215 
6216  typedef
6217  typename boost::property_traits< VertexColorMap >::value_type Color;
6218  put(*_v_cm, *pVert, Color(RGB[0], RGB[1], RGB[2]));
6219  }
6220  }
6221 
6222  // this->Q_color++;
6223  this->NumberColorQuantization[_Component_ID]--;
6224 
6225  delete[] Color_quantization_model;
6226 }
6227 
6228 
6229 // Description : Change a point coordinates in real to integer coordinates
6230 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
6231 Point_Int
6233  Change_Real_Int(const Point3d &pt, const int &Component_ID)
6234 {
6235  Point_Int Point;
6236 
6237  double Quantization_step = 0.0;
6238 
6239  // If the quantization resolution is decreased,
6240  // we increase the step of quantization by a power of two.
6241  if(this->NumberChangeQuantization[Component_ID] == 0)
6242  Quantization_step = this->Quantization_Step[Component_ID];
6243  else
6244  Quantization_step =
6245  this->Quantization_Step[Component_ID] *
6246  std::pow(2.0, (int)this->NumberChangeQuantization[Component_ID]);
6247 
6248  float xmin = this->xmin[Component_ID];
6249  float ymin = this->ymin[Component_ID];
6250  float zmin = this->zmin[Component_ID];
6251 
6252  double x = pt[0];
6253  double y = pt[1];
6254  double z = pt[2];
6255 
6256  Point.x = (int)(ceil((x - xmin) / Quantization_step)) - 1;
6257  if(Point.x == -1)
6258  Point.x = 0;
6259 
6260  Point.y = (int)(ceil((y - ymin) / Quantization_step)) - 1;
6261  if(Point.y == -1)
6262  Point.y = 0;
6263 
6264  Point.z = (int)(ceil((z - zmin) / Quantization_step)) - 1;
6265  if(Point.z == -1)
6266  Point.z = 0;
6267 
6268  return Point;
6269 }
6270 
6271 
6272 // Description : Change a point coordinates in integer to real coordinates
6273 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
6274 typename Compression_Valence_Component< HalfedgeGraph,
6275  PointMap,
6276  VertexColorMap >::Point3d
6278  Change_Int_Real(const Point_Int &Point, const int &Component_ID)
6279 {
6280  float Quantization_step = 0;
6281 
6282  // If the quantization resolution is decreased,
6283  // we increase the step of quantization by a power of two.
6284  if(this->NumberChangeQuantization[Component_ID] == 0)
6285  Quantization_step = this->Quantization_Step[Component_ID];
6286  else
6287  Quantization_step =
6288  this->Quantization_Step[Component_ID] *
6289  std::pow(2.0, (int)this->NumberChangeQuantization[Component_ID]);
6290 
6291  float xmin = this->xmin[Component_ID];
6292  float ymin = this->ymin[Component_ID];
6293  float zmin = this->zmin[Component_ID];
6294 
6295  double x = xmin + (Point.x + 0.5) * Quantization_step;
6296  double y = ymin + (Point.y + 0.5) * Quantization_step;
6297  double z = zmin + (Point.z + 0.5) * Quantization_step;
6298 
6299  Point3d pt(x, y, z);
6300 
6301  return pt;
6302 }
6303 
6304 
6305 //#define DBG_Error_Projected_Surface
6306 
6307 // Error metric which measures importance of color and geometry for each vertex.
6308 // Used to prevent removal of the visually important vertex.
6309 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
6310 bool
6312  Error_Projected_Surface(const HalfedgeGraph &_pMesh,
6313  const PointMap *_pm,
6314  const halfedge_descriptor &_h,
6315  const int &_Component_ID,
6316  const double &Mean_color,
6317  const double &Mean_area)
6318 {
6319  halfedge_descriptor g = _h;
6320  int Valence = (int)out_degree(target(next(g, _pMesh), _pMesh), _pMesh);
6321  int Type = Find_Type(_pMesh, g, Valence);
6322 
6323  float C0_min = this->C0_Min;
6324  float C1_min = this->C1_Min;
6325  float C2_min = this->C2_Min;
6326 
6327  float Color_step = 0.0;
6328 
6329  if(this->NumberColorQuantization[_Component_ID] == 0)
6330  Color_step = this->Color_Quantization_Step;
6331  else
6332  Color_step =
6333  this->Color_Quantization_Step *
6334  std::pow(2.0, (double)this->NumberColorQuantization[_Component_ID]);
6335 
6336  std::vector< float > Center_color;
6337  Center_color.push_back(
6338  C0_min +
6339  (get(this->vertex_color_int, target(next(g, _pMesh), _pMesh))).c0 *
6340  Color_step);
6341  Center_color.push_back(
6342  C1_min +
6343  (get(this->vertex_color_int, target(next(g, _pMesh), _pMesh))).c1 *
6344  Color_step);
6345  Center_color.push_back(
6346  C2_min +
6347  (get(this->vertex_color_int, target(next(g, _pMesh), _pMesh))).c2 *
6348  Color_step);
6349 
6350  std::vector< Color_Unit > Neighbors_color;
6351 
6352  std::vector< float > Projected_color;
6353 
6354  double Patch_area = 0.0;
6355 
6356  // Calculate area of patch
6357  g = next(g, _pMesh);
6358  for(int i = 0; i < Valence; i++)
6359  {
6360  g = opposite(g, _pMesh);
6361  Color_Unit c;
6362 
6363  c = get(this->vertex_color_int, target(g, _pMesh));
6364  Neighbors_color.push_back(c);
6365 
6366  Patch_area += Area_Facet_Triangle(g, _pMesh, _pm);
6367 
6368  g = prev(g, _pMesh);
6369  }
6370 
6371  Color_Unit Average_color;
6372 
6373  if(Valence == 3)
6374  {
6375  for(int i = 0; i < 3; i++)
6376  Average_color = Average_color + Neighbors_color[i];
6377  }
6378 
6379  if(Valence == 4)
6380  {
6381  if((Type == 5) || (Type == 8))
6382  {
6383  Average_color = Average_color + Neighbors_color[1];
6384  Average_color = Average_color + Neighbors_color[3];
6385  }
6386 
6387  if((Type == 6) || (Type == 7))
6388  {
6389  Average_color = Average_color + Neighbors_color[0];
6390  Average_color = Average_color + Neighbors_color[2];
6391  }
6392  }
6393 
6394  if(Valence == 5)
6395  {
6396  if((Type == 9) || (Type == 12))
6397  {
6398  Average_color = Average_color + Neighbors_color[1];
6399  Average_color = Average_color + Neighbors_color[3];
6400  Average_color = Average_color + Neighbors_color[4];
6401  }
6402 
6403  if(Type == 10)
6404  {
6405  Average_color = Average_color + Neighbors_color[0];
6406  Average_color = Average_color + Neighbors_color[1];
6407  Average_color = Average_color + Neighbors_color[3];
6408  }
6409 
6410  if(Type == 11)
6411  {
6412  Average_color = Average_color + Neighbors_color[0];
6413  Average_color = Average_color + Neighbors_color[2];
6414  Average_color = Average_color + Neighbors_color[4];
6415  }
6416  }
6417 
6418 
6419  if(Valence == 6)
6420  {
6421  if((Type == 13) || (Type == 16))
6422  {
6423  Average_color = Average_color + Neighbors_color[1];
6424  Average_color = Average_color + Neighbors_color[3];
6425  Average_color = Average_color + Neighbors_color[5];
6426  }
6427  else
6428  {
6429  Average_color = Average_color + Neighbors_color[0];
6430  Average_color = Average_color + Neighbors_color[2];
6431  Average_color = Average_color + Neighbors_color[4];
6432  }
6433  }
6434 
6435  float Divised_c0, Divised_c1, Divised_c2;
6436  if(Valence != 4)
6437  {
6438  Divised_c0 = (float)Average_color.c0 / 3.0;
6439  Divised_c1 = (float)Average_color.c1 / 3.0;
6440  Divised_c2 = (float)Average_color.c2 / 3.0;
6441  }
6442  else
6443  {
6444  Divised_c0 = (float)Average_color.c0 / 2.0;
6445  Divised_c1 = (float)Average_color.c1 / 2.0;
6446  Divised_c2 = (float)Average_color.c2 / 2.0;
6447  }
6448 
6449  Projected_color.push_back(C0_min + Divised_c0 * Color_step);
6450  Projected_color.push_back(C1_min + Divised_c1 * Color_step);
6451  Projected_color.push_back(C2_min + Divised_c2 * Color_step);
6452 
6453 
6454  // Color distance between the original color and estimated color
6455  double Color_distance = (Projected_color[0] - Center_color[0]) *
6456  (Projected_color[0] - Center_color[0]) +
6457  (Projected_color[1] - Center_color[1]) *
6458  (Projected_color[1] - Center_color[1]) +
6459  (Projected_color[2] - Center_color[2]) *
6460  (Projected_color[2] - Center_color[2]);
6461 
6462  Color_distance = std::sqrt(Color_distance);
6463 
6464  // Mean color is obtained using number of vertices.
6465  // X 3.0 cause we should use the number of edges.
6466  double Relative_color_distance = Color_distance / Mean_color * 3.0;
6467 #ifdef DBG_Error_Projected_Surface
6468  std::cout << "Color_distance = " << Color_distance << std::endl;
6469  std::cout << "Mean_color = " << Mean_color << std::endl;
6470  std::cout << "Relative_color_distance = " << Relative_color_distance
6471  << std::endl;
6472 #endif
6473 
6474  // Averaged area of triangles of patch
6475  double Area_per_triangle = Patch_area / double(Valence);
6476  Area_per_triangle *= std::pow(
6477  ((double)10.0 / (double)this->HighestLengthBB[_Component_ID]), 2.0);
6478 
6479  double Relative_geo_distance = Area_per_triangle / Mean_area;
6480 #ifdef DBG_Error_Projected_Surface
6481  std::cout << "Area_per_triangle = " << Area_per_triangle << std::endl;
6482  std::cout << "Mean_area = " << Mean_area << std::endl;
6483  std::cout << "Relative_geo_distance = " << Relative_geo_distance << std::endl;
6484 #endif
6485 
6486  double Global_distance = (Relative_color_distance) * (Relative_geo_distance);
6487 #ifdef DBG_Error_Projected_Surface
6488  std::cout << "Global_distance = " << Global_distance << std::endl;
6489 #endif
6490 
6491  if(Global_distance > 0.5)
6492  return true;
6493  else
6494  return false;
6495 }
6496 
6497 
6498 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
6499 void
6501  write_intermediate_mesh(/*const*/ HalfedgeGraph &_pMesh,
6502  const VertexColorMap *_v_cm)
6503 {
6504  // build output file name
6505  std::string outputFilePath = this->File_name;
6506  outputFilePath += ".level" + std::to_string(this->Current_level) + ".off";
6507 
6508  // create a temporary property map bag in order
6509  // to be able to call the generic writer
6510  FEVV::PMapsContainer pmaps_bag;
6511  put_property_map(FEVV::vertex_color, _pMesh, pmaps_bag, *_v_cm);
6512 
6513  // write the mesh to file
6514  FEVV::Filters::write_mesh(outputFilePath, _pMesh, pmaps_bag);
6515 }
6516 
6517 
6518 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
6519 void
6521  copy_mesh(const HalfedgeGraph &_pMesh,
6522  const VertexColorMap *_v_cm,
6523  HalfedgeGraph &mesh_copy,
6524  VertexColorMap *v_cm_copy /* nullptr allowed */)
6525 {
6526  // storage for vertices correspondance
6527  boost::unordered_map< vertex_descriptor, vertex_descriptor > v2v;
6528 
6529  // copy topology and geometry
6530  CGAL::clear(mesh_copy);
6531  CGAL::copy_face_graph(_pMesh, mesh_copy, std::inserter(v2v, v2v.end()));
6532 
6533  // copy the vertex-color property map
6534  if(v_cm_copy)
6535  {
6536  typename boost::unordered_map< vertex_descriptor,
6537  vertex_descriptor >::iterator
6538  it = v2v.begin(),
6539  end = v2v.end();
6540  for(; it != end; ++it)
6541  {
6542  auto color = get(*_v_cm, it->first);
6543  put(*v_cm_copy, it->second, color);
6544  }
6545  }
6546 }
6547 
6548 
6549 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
6550 void
6553  const HalfedgeGraph &_pMesh,
6554  const VertexColorMap *_v_cm,
6555  std::vector< HalfedgeGraph * > *intermediate_meshes,
6556  std::vector< VertexColorMap * > *intermediate_vertexColorMaps)
6557 {
6558  if(!intermediate_meshes)
6559  return;
6560 
6561  // create empty new mesh
6562  HalfedgeGraph *m_copy = new HalfedgeGraph;
6563 
6564  // create empty new vertex-color property map
6565  VertexColorMap *v_cm_copy = nullptr;
6566  if(intermediate_vertexColorMaps)
6567  v_cm_copy = new VertexColorMap;
6568 
6569  // copy mesh + geometry + vertex-color
6570  copy_mesh(_pMesh, _v_cm, *m_copy, v_cm_copy);
6571 
6572  // store copied mesh and vertex-color
6573  intermediate_meshes->push_back(m_copy);
6574  if(intermediate_vertexColorMaps)
6575  intermediate_vertexColorMaps->push_back(v_cm_copy);
6576 }
6577 
6578 
6579 //#define DBG_Decompression_All_From_File
6580 
6581 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
6582 std::string
6585  HalfedgeGraph &_pMesh,
6586  PointMap *_pm,
6587  VertexColorMap *_v_cm,
6588  bool do_write_info,
6589  std::vector< HalfedgeGraph * >
6590  *intermediate_meshes /* nullptr allowed */,
6591  std::vector< VertexColorMap * >
6592  *intermediate_vertexColorMaps /* nullptr allowed */,
6593  int stop_level /* decompression level to stop at */,
6594  bool do_write_intermediate_meshes)
6595 {
6596  // start time measurement
6597  auto time_start = std::chrono::steady_clock::now();
6598 
6599  if(do_write_info)
6600  {
6601  if(this->Process_level == 0)
6602  Write_Info(_pMesh);
6603  }
6604 
6605  //ELO+ fix color > 1 issue on level 0 mesh
6606  truncate_colors(_pMesh, _v_cm);
6607 
6608  // save the level 0 mesh (the simplest one) to file
6609  if(do_write_intermediate_meshes)
6610  write_intermediate_mesh(_pMesh, _v_cm);
6611 
6612  // keep the level 0 mesh (the simplest one)
6613  if(intermediate_meshes)
6614  keep_intermediate_mesh(
6615  _pMesh, _v_cm, intermediate_meshes, intermediate_vertexColorMaps);
6616 
6617  // check at which level to stop decompression
6618  if(stop_level == -1 || stop_level > this->Total_layer)
6619  stop_level = this->Total_layer;
6620 
6621  // loop over decompression levels
6622  while(this->Current_level != stop_level)
6623  {
6624 #ifdef DBG_Decompression_All_From_File
6625  std::cout << "DBG in " << __func__
6626  << " Current_level=" << this->Current_level << std::endl;
6627  DBG_print_mesh_geometry(_pMesh, _pm, "loop begin");
6628  DBG_print_mesh_vertexcolor(_pMesh, _v_cm, "loop begin");
6629 #endif
6630 
6631  this->Current_level = this->Decompress_Each_Step(_pMesh, _pm, _v_cm);
6632  this->Process_level++;
6633 
6634  if(do_write_info)
6635  {
6636  Write_Info(_pMesh);
6637  }
6638 
6639  //ELO+ fix color > 1 issue on current level mesh
6640  truncate_colors(_pMesh, _v_cm);
6641 
6642  // save intermediate meshes into files
6643  if(do_write_intermediate_meshes)
6644  write_intermediate_mesh(_pMesh, _v_cm);
6645 
6646  // keep intermediate meshes
6647  if(intermediate_meshes && this->Current_level < stop_level)
6648  keep_intermediate_mesh(
6649  _pMesh, _v_cm, intermediate_meshes, intermediate_vertexColorMaps);
6650 
6651 
6652 #ifdef DBG_Decompression_All_From_File
6653  DBG_print_mesh_geometry(_pMesh, _pm, "loop end");
6654  DBG_print_mesh_vertexcolor(_pMesh, _v_cm, "loop end");
6655 #endif
6656  }
6657 
6658  // stop time measurement
6659  auto time_end = std::chrono::steady_clock::now();
6660  std::chrono::duration< double > time_diff = time_end - time_start;
6661  std::stringstream msgbuffer;
6662  msgbuffer << "Number of layers : " << this->Total_layer << std::endl;
6663  msgbuffer << "Calculation time for decompressing layers 1 to "
6664  << stop_level << " : " << (float)time_diff.count()
6665  << " seconds" << std::endl;
6666  msgbuffer << "Time for loading .p3d and decompressing layer 0 was not taken "
6667  "into account."
6668  << std::endl;
6669  std::cout << msgbuffer.str() << std::endl;
6670 
6671  return msgbuffer.str();
6672 }
6673 
6674 
6675 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
6676 void
6678  Write_Info(HalfedgeGraph &_pMesh)
6679 {
6680  if(this->Process_level == 0)
6681  {
6682  this->Dec_File_Info = this->File_name;
6683  (this->Dec_File_Info).append(".infos.txt");
6684 
6685  this->Dec_Info = fopen(this->Dec_File_Info.c_str(), "w");
6686  }
6687  else
6688  this->Dec_Info = fopen(this->Dec_File_Info.c_str(), "a");
6689 
6690  int CLevel = 0, Number_vertices = 0;
6691 
6692  if(this->Sequence)
6693  {
6694  CLevel = this->Visu_level;
6695  Number_vertices = (int)FEVV::size_of_vertices(_pMesh);
6696  }
6697  else
6698  {
6699  CLevel = this->Current_level;
6700  Number_vertices = (int)FEVV::size_of_vertices(_pMesh);
6701  }
6702 
6703  unsigned Current_file_size = this->Calculate_Current_File_Size();
6704 
6705  float prog = (float)Current_file_size / this->Compressed_file_size * 100;
6706 
6707  if(this->Process_level == this->Total_layer)
6708  prog = 100.0;
6709 
6710  float ratio = 1 / ((float)Current_file_size / this->Initial_file_size);
6711 
6712  fprintf(this->Dec_Info,
6713  "Level %2d #v : %8d %6u bytes Prog : %7.3f %% Ratio : "
6714  "%9.3f\n",
6715  CLevel,
6716  Number_vertices,
6717  Current_file_size,
6718  prog,
6719  ratio);
6720  fclose(this->Dec_Info);
6721 }
6722 
6723 
6724 //-----------------------------------------------------------
6725 // Functions moved from Compression_Valence_Common.h
6726 //-----------------------------------------------------------
6727 
6728 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
6729 bool
6731  Is_Border_Vertex(const halfedge_descriptor &h, const HalfedgeGraph &mesh)
6732 {
6733  bool check = false;
6734 
6735  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > hvc(target(h, mesh),
6736  mesh);
6737  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > hvc_end(hvc);
6738 
6739  do
6740  {
6741  if(CGAL::is_border_edge(*hvc, mesh))
6742  {
6743  check = true;
6744  break;
6745  }
6746  } while(++hvc != hvc_end);
6747 
6748  return check;
6749 }
6750 
6751 
6752 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
6753 int
6755  Find_Type(const HalfedgeGraph &_pMesh,
6756  const halfedge_descriptor &h,
6757  const int &valence)
6758 {
6759  int type = 0;
6760 
6761  if(valence == 3)
6762  {
6763  if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
6764  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) == PLUS))
6765  type = 1;
6766  else if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
6767  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
6768  MINUS))
6769  type = 2;
6770  else if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
6771  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
6772  PLUS))
6773  type = 3;
6774  else if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
6775  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
6776  MINUS))
6777  type = 4;
6778  }
6779 
6780  else if(valence == 4)
6781  {
6782  if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
6783  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) == PLUS))
6784  type = 5;
6785  else if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
6786  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
6787  MINUS))
6788  type = 6;
6789  else if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
6790  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
6791  PLUS))
6792  type = 7;
6793  else if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
6794  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
6795  MINUS))
6796  type = 8;
6797  }
6798 
6799  else if(valence == 5)
6800  {
6801  if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
6802  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) == PLUS))
6803  type = 9;
6804  else if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
6805  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
6806  MINUS))
6807  type = 10;
6808  else if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
6809  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
6810  PLUS))
6811  type = 11;
6812  else if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
6813  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
6814  MINUS))
6815  type = 12;
6816  }
6817 
6818  else if(valence == 6)
6819  {
6820  if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
6821  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) == PLUS))
6822  type = 13;
6823  else if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
6824  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
6825  MINUS))
6826  type = 14;
6827  else if((get(this->Vertex_Sign, target(h, _pMesh)) == PLUS) &&
6828  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
6829  PLUS))
6830  type = 15;
6831  else if((get(this->Vertex_Sign, target(h, _pMesh)) == MINUS) &&
6832  (get(this->Vertex_Sign, target(opposite(h, _pMesh), _pMesh)) ==
6833  MINUS))
6834  type = 16;
6835  }
6836  return type;
6837 }
6838 
6839 
6840 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
6841 bool
6843  Is_Manifold_Property_Violated(const HalfedgeGraph &_pMesh,
6844  const halfedge_descriptor &h,
6845  const int &type,
6846  const int &valence)
6847 {
6848  bool check = false;
6849  halfedge_descriptor g = h;
6850  int *Points_index = new int[valence];
6851 
6852  // if valence is 3, no new edge is inserted, so always safe to remove.
6853  if(valence == 3)
6854  return false;
6855 
6856  else
6857  {
6858  // Points_index[ ] contains all boundary vertices' indices (ordered in
6859  // counterclockwise)
6860  Points_index[0] = get(this->Vertex_Number, target(g, _pMesh));
6861  g = next(g, _pMesh); // g points center vertex;
6862 
6863  for(int i = 1; i < valence; i++)
6864  {
6865  g = prev(opposite(g, _pMesh),
6866  _pMesh); // around the vertex in the counterclockwise way.
6867  Points_index[i] =
6868  get(this->Vertex_Number, target(opposite(g, _pMesh), _pMesh));
6869  }
6870 
6871  // quadrangle
6872  if(valence == 4)
6873  {
6874  if((type == 5) || (type == 8))
6875  {
6876  g = opposite(h, _pMesh);
6877  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc(
6878  target(g, _pMesh), _pMesh);
6879  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc_end = Hvc;
6880 
6881  CGAL_For_all(Hvc, Hvc_end)
6882  {
6883  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
6884  Points_index[1])
6885  check = true;
6886  }
6887  }
6888 
6889  else if((type == 6) || (type == 7))
6890  {
6891  g = h;
6892  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc(
6893  target(g, _pMesh), _pMesh);
6894  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc_end = Hvc;
6895 
6896  CGAL_For_all(Hvc, Hvc_end)
6897  {
6898  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
6899  Points_index[2])
6900  check = true;
6901  ;
6902  }
6903  }
6904  }
6905 
6906  // pendtagone : 2 edges to verify
6907  if(valence == 5)
6908  {
6909  if((type == 9) || (type == 12))
6910  {
6911  g = opposite(h, _pMesh);
6912  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc(
6913  target(g, _pMesh), _pMesh);
6914  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc_end = Hvc;
6915 
6916  CGAL_For_all(Hvc, Hvc_end)
6917  {
6918  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
6919  Points_index[1])
6920  check = true;
6921  }
6922 
6923  g = next(opposite(next(h, _pMesh), _pMesh), _pMesh);
6924  Hvc = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(
6925  target(g, _pMesh), _pMesh);
6926  Hvc_end = Hvc;
6927 
6928  CGAL_For_all(Hvc, Hvc_end)
6929  {
6930  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
6931  Points_index[3])
6932  check = true;
6933  }
6934  }
6935 
6936  else if(type == 10)
6937  {
6938  g = h;
6939  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc(
6940  target(g, _pMesh), _pMesh);
6941  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc_end = Hvc;
6942 
6943  CGAL_For_all(Hvc, Hvc_end)
6944  {
6945  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
6946  Points_index[3])
6947  check = true;
6948  }
6949 
6950  g = next(opposite(next(h, _pMesh), _pMesh), _pMesh);
6951  Hvc = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(
6952  target(g, _pMesh), _pMesh);
6953  Hvc_end = Hvc;
6954 
6955  CGAL_For_all(Hvc, Hvc_end)
6956  {
6957  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
6958  Points_index[3])
6959  check = true;
6960  }
6961  }
6962 
6963  else if(type == 11)
6964  {
6965  g = h;
6966  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc(
6967  target(g, _pMesh), _pMesh);
6968  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc_end = Hvc;
6969 
6970  CGAL_For_all(Hvc, Hvc_end)
6971  {
6972  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
6973  Points_index[2])
6974  check = true;
6975  }
6976 
6977  g = opposite(h, _pMesh);
6978  Hvc = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(
6979  target(g, _pMesh), _pMesh);
6980  Hvc_end = Hvc;
6981 
6982  CGAL_For_all(Hvc, Hvc_end)
6983  {
6984  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
6985  Points_index[2])
6986  check = true;
6987  }
6988  }
6989  }
6990 
6991  // hexagone
6992 
6993  if(valence == 6)
6994  {
6995  if((type == 13) || (type == 16))
6996  {
6997  g = opposite(h, _pMesh);
6998  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc(
6999  target(g, _pMesh), _pMesh);
7000  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc_end = Hvc;
7001 
7002  CGAL_For_all(Hvc, Hvc_end)
7003  {
7004  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
7005  Points_index[1])
7006  check = true;
7007  }
7008 
7009  g = opposite(h, _pMesh);
7010  Hvc = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(
7011  target(g, _pMesh), _pMesh);
7012  Hvc_end = Hvc;
7013 
7014  CGAL_For_all(Hvc, Hvc_end)
7015  {
7016  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
7017  Points_index[3])
7018  check = true;
7019  }
7020 
7021  g = next(opposite(next(h, _pMesh), _pMesh), _pMesh);
7022  Hvc = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(
7023  target(g, _pMesh), _pMesh);
7024  Hvc_end = Hvc;
7025 
7026  CGAL_For_all(Hvc, Hvc_end)
7027  {
7028  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
7029  Points_index[3])
7030  check = true;
7031  }
7032  }
7033 
7034  else if((type == 14) || (type == 15))
7035  {
7036  g = h;
7037  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc(
7038  target(g, _pMesh), _pMesh);
7039  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > Hvc_end = Hvc;
7040 
7041  CGAL_For_all(Hvc, Hvc_end)
7042  {
7043  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
7044  Points_index[2])
7045  check = true;
7046  }
7047 
7048  g = h;
7049  Hvc = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(
7050  target(g, _pMesh), _pMesh);
7051  Hvc_end = Hvc;
7052 
7053  CGAL_For_all(Hvc, Hvc_end)
7054  {
7055  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
7056  Points_index[4])
7057  check = true;
7058  }
7059 
7060  g = next(opposite(prev(h, _pMesh), _pMesh), _pMesh);
7061  Hvc = CGAL::Halfedge_around_target_circulator< HalfedgeGraph >(
7062  target(g, _pMesh), _pMesh);
7063  Hvc_end = Hvc;
7064 
7065  CGAL_For_all(Hvc, Hvc_end)
7066  {
7067  if(get(this->Vertex_Number, target(opposite(*Hvc, _pMesh), _pMesh)) ==
7068  Points_index[2])
7069  check = true;
7070  }
7071  }
7072  }
7073  }
7074 
7075  delete[] Points_index;
7076  return check;
7077 }
7078 
7079 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
7080 bool
7082  Is_Normal_Flipping_Occured(const HalfedgeGraph &_pMesh,
7083  const PointMap *_pm,
7084  const halfedge_descriptor &h,
7085  const unsigned &valence)
7086 {
7090 
7091  int type = Find_Type(_pMesh, h, valence);
7092  bool check = false;
7094 
7095  halfedge_descriptor g = h;
7096  g = next(g, _pMesh);
7097 
7098  Vector V_normal = get(this->vertex_normal, target(next(h, _pMesh), _pMesh));
7099 
7100  double length =
7101  FEVV::Math::Vector::l2_distance< FEVV::Geometry_traits< HalfedgeGraph > >(
7102  V_normal, gt);
7103  if(length != 0)
7104  V_normal = V_normal / length;
7105 
7106  Point3d *Points = new Point3d[valence];
7107  Vector *Normal = new Vector[valence - 2];
7108 
7109 
7110  for(unsigned int i = 0; i < valence; i++)
7111  {
7112  Points[i] = get(*_pm, target(opposite(g, _pMesh), _pMesh));
7113  g = prev(opposite(g, _pMesh), _pMesh);
7114  }
7115 
7116  for(unsigned int j = 0; j < (valence - 2); j++)
7117  {
7118  Normal[j] = Vector(0.0, 0.0, 0.0);
7119  }
7120 
7121  // if valence = 3 , there is no normal flipping;
7122  if(valence == 3)
7123  {
7124  check = false;
7125  }
7126 
7127  // quadrangle
7128  else if((type == 5) || (type == 8)) // 0 1 3 , 1 2 3
7129  {
7130  Normal[0] = Triangle_Normal(_pMesh, Points[0], Points[1], Points[3]);
7131  Normal[1] = Triangle_Normal(_pMesh, Points[1], Points[2], Points[3]);
7132  }
7133 
7134  else if((type == 6) || (type == 7)) // 0 1 2 , 0 2 3
7135  {
7136  Normal[0] = Triangle_Normal(_pMesh, Points[0], Points[1], Points[2]);
7137  Normal[1] = Triangle_Normal(_pMesh, Points[0], Points[2], Points[3]);
7138  }
7139 
7140  // pentagone
7141  else if((type == 9) || (type == 12)) // 0 1 4 , 1 2 3 , 1 3 4
7142  {
7143  Normal[0] = Triangle_Normal(_pMesh, Points[0], Points[1], Points[4]);
7144  Normal[1] = Triangle_Normal(_pMesh, Points[1], Points[2], Points[3]);
7145  Normal[2] = Triangle_Normal(_pMesh, Points[1], Points[3], Points[4]);
7146  }
7147 
7148 
7149  else if(type == 10) // 0 1 3 , 1 2 3 , 0 3 4
7150  {
7151  Normal[0] = Triangle_Normal(_pMesh, Points[0], Points[1], Points[3]);
7152  Normal[1] = Triangle_Normal(_pMesh, Points[1], Points[2], Points[3]);
7153  Normal[2] = Triangle_Normal(_pMesh, Points[0], Points[3], Points[4]);
7154  }
7155 
7156  else if(type == 11) // 0 1 2 , 0 2 4 , 2 3 4
7157  {
7158  Normal[0] = Triangle_Normal(_pMesh, Points[0], Points[1], Points[2]);
7159  Normal[1] = Triangle_Normal(_pMesh, Points[0], Points[2], Points[4]);
7160  Normal[2] = Triangle_Normal(_pMesh, Points[2], Points[3], Points[4]);
7161  }
7162 
7163  // Hexagone
7164 
7165  else if((type == 13) || (type == 16)) // 0 1 5, 1 2 3 , 3 4 5, 1 3 5
7166  {
7167  Normal[0] = Triangle_Normal(_pMesh, Points[0], Points[1], Points[5]);
7168  Normal[1] = Triangle_Normal(_pMesh, Points[1], Points[2], Points[3]);
7169  Normal[2] = Triangle_Normal(_pMesh, Points[3], Points[4], Points[5]);
7170  Normal[3] = Triangle_Normal(_pMesh, Points[1], Points[3], Points[5]);
7171  }
7172 
7173  else if((type == 14) || (type == 15)) // 0 1 2 , 2 3 4 , 4 5 0, 0 2 4
7174  {
7175  Normal[0] = Triangle_Normal(_pMesh, Points[0], Points[1], Points[2]);
7176  Normal[1] = Triangle_Normal(_pMesh, Points[2], Points[3], Points[4]);
7177  Normal[2] = Triangle_Normal(_pMesh, Points[4], Points[5], Points[0]);
7178  Normal[3] = Triangle_Normal(_pMesh, Points[0], Points[2], Points[4]);
7179  }
7180 
7181  for(unsigned int i = 0; i < (valence - 2); i++)
7182  {
7183  double length_normal = FEVV::Math::Vector::l2_distance<
7184  FEVV::Geometry_traits< HalfedgeGraph > >(Normal[i], gt);
7185  if(length_normal != 0)
7186  Normal[i] = Normal[i] / length_normal;
7187  }
7188 
7189  for(unsigned int i = 0; i < (valence - 2); i++)
7190  {
7191  double cosine = FEVV::Math::Vector::dot_product<
7192  FEVV::Geometry_traits< HalfedgeGraph > >(V_normal, Normal[i], gt);
7193  double cosine_rad = std::acos(cosine);
7194 
7195  if(cosine_rad >= PI / 2)
7196  check = true;
7197  }
7198  delete[] Points;
7199  delete[] Normal;
7200 
7201  return check;
7202 }
7203 
7204 
7205 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
7208  Triangle_Normal(const HalfedgeGraph &_pMesh,
7209  const PointMap *_pm,
7210  const halfedge_descriptor &h)
7211 {
7215 
7216  Point3d P = get(*_pm, target(h, _pMesh));
7217  Point3d Q = get(*_pm, target(next(h, _pMesh), _pMesh));
7218  Point3d R = get(*_pm, target(next(next(h, _pMesh), _pMesh), _pMesh));
7219 
7220  Vector PQ = Q - P;
7221  // Vector PR = R-P; // MT
7222  Vector QR = R - Q;
7223 
7226  double length =
7227  FEVV::Math::Vector::l2_distance< FEVV::Geometry_traits< HalfedgeGraph > >(
7228  normal, gt);
7229  if(length != 0.0)
7230  normal = normal / length;
7231 
7232  return normal;
7233 }
7234 
7235 
7236 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
7240  const HalfedgeGraph &_pMesh,
7244 {
7245  //typedef typename FEVV::Geometry_traits< HalfedgeGraph >::Point Point3d;
7248 
7249  Vector PQ = Q - P;
7250  // Vector PR = R - P; // MT
7251  Vector QR = R - Q;
7252 
7255  double length =
7256  FEVV::Math::Vector::l2_distance< FEVV::Geometry_traits< HalfedgeGraph > >(
7257  normal, gt);
7258  if(length != 0.0)
7259  normal = normal / length;
7260 
7261  return normal;
7262 }
7263 
7264 
7265 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
7266 bool
7268  Is_Geometric_Metric_Violated(const HalfedgeGraph &_pMesh,
7269  const PointMap *_pm,
7270  const halfedge_descriptor &h,
7271  const int &type,
7272  const unsigned int &valence,
7273  const float &Threshold)
7274 {
7276 
7277  bool check = false;
7278  double volume = 0; // volume;;
7279  double perimeter = 0; // perimeter;;;
7280  double area = 0; // area;;
7281  unsigned int i;
7282 
7283  halfedge_descriptor g = h;
7284  Point3d *Points = new Point3d[valence + 1];
7285  g = next(g, _pMesh); // g points front vertex
7286 
7287  // Points[0] = coordinates of the front vertex
7288  // Points[i] = coordinates of the ith vertex in the counterclockwise way.
7289  Points[0] = get(*_pm, target(g, _pMesh));
7290  for(i = 1; i < (valence + 1); i++)
7291  {
7292  Points[i] = get(*_pm, target(opposite(g, _pMesh), _pMesh));
7293  g = prev(opposite(g, _pMesh), _pMesh);
7294  }
7295 
7296  // caculate perimeter
7297  Vector *Vectors = new Vector[valence];
7298  Vectors[0] = Points[1] - Points[valence];
7299  perimeter =
7300  FEVV::Math::Vector::l2_distance< FEVV::Geometry_traits< HalfedgeGraph > >(
7301  Vectors[0], gt);
7302 
7303  for(i = 1; i < valence; i++)
7304  {
7305  Vectors[i] = Points[(i + 1)] - Points[i];
7306  double per = FEVV::Math::Vector::l2_distance<
7307  FEVV::Geometry_traits< HalfedgeGraph > >(Vectors[i], gt);
7308  perimeter = perimeter + per;
7309  }
7310 
7311  // calculate volume and area;;;
7312  if(valence == 3) //[0 1 2 3]
7313  {
7314  volume = Volume(Points[0], Points[1], Points[3], Points[2], _pMesh);
7315  volume = std::abs(volume);
7316 
7317  area = Area_Facet_Triangle(Points[1], Points[2], Points[3], _pMesh);
7318  area = std::abs(area);
7319  }
7320 
7321  else if(valence == 4)
7322  {
7323  if((type == 5) || (type == 8)) // [0 1 2 4], [0 2 3 4]
7324  {
7325  double vol = Volume(Points[0], Points[1], Points[4], Points[2], _pMesh);
7326  vol = std::abs(vol);
7327  volume = volume + vol;
7328 
7329  vol = Volume(Points[0], Points[2], Points[4], Points[3], _pMesh);
7330  vol = std::abs(vol);
7331  volume = volume + vol;
7332 
7333  double area_intermediate =
7334  Area_Facet_Triangle(Points[1], Points[2], Points[4], _pMesh);
7335  area_intermediate = std::abs(area_intermediate);
7336  area = area + area_intermediate;
7337 
7338  area_intermediate =
7339  Area_Facet_Triangle(Points[2], Points[3], Points[4], _pMesh);
7340  area_intermediate = std::abs(area_intermediate);
7341  area = area + area_intermediate;
7342  }
7343 
7344  else if((type == 6) || (type == 7)) // [0 1 2 3], [0 1 3 4]
7345  {
7346  double vol = Volume(Points[0], Points[1], Points[3], Points[2], _pMesh);
7347  vol = std::abs(vol);
7348  volume = volume + vol;
7349 
7350  vol = Volume(Points[0], Points[1], Points[4], Points[3], _pMesh);
7351  vol = std::abs(vol);
7352  volume = volume + vol;
7353 
7354  double area_intermediate =
7355  Area_Facet_Triangle(Points[1], Points[2], Points[3], _pMesh);
7356  area_intermediate = std::abs(area_intermediate);
7357  area = area + area_intermediate;
7358 
7359  area_intermediate =
7360  Area_Facet_Triangle(Points[1], Points[3], Points[4], _pMesh);
7361  area_intermediate = std::abs(area_intermediate);
7362  area = area + area_intermediate;
7363  }
7364  }
7365 
7366  else if(valence == 5)
7367  {
7368  if((type == 9) || (type == 12)) // [0 1 2 5] , [0 2 4 5], [0 2 3 4]
7369  {
7370  double vol = Volume(Points[0], Points[1], Points[5], Points[2], _pMesh);
7371  vol = std::abs(vol);
7372  volume = volume + vol;
7373 
7374  vol = Volume(Points[0], Points[2], Points[5], Points[4], _pMesh);
7375  vol = std::abs(vol);
7376  volume = volume + vol;
7377 
7378  vol = Volume(Points[0], Points[2], Points[4], Points[3], _pMesh);
7379  vol = std::abs(vol);
7380  volume = volume + vol;
7381 
7382  double area_intermediate =
7383  Area_Facet_Triangle(Points[1], Points[2], Points[5], _pMesh);
7384  area_intermediate = std::abs(area_intermediate);
7385  area = area + area_intermediate;
7386 
7387  area_intermediate =
7388  Area_Facet_Triangle(Points[2], Points[4], Points[5], _pMesh);
7389  area_intermediate = std::abs(area_intermediate);
7390  area = area + area_intermediate;
7391 
7392  area_intermediate =
7393  Area_Facet_Triangle(Points[2], Points[3], Points[4], _pMesh);
7394  area_intermediate = std::abs(area_intermediate);
7395  area = area + area_intermediate;
7396  }
7397 
7398  else if(type == 10) // [0 1 4 5], [0 1 2 4], [0 2 3 4]
7399  {
7400  double vol = Volume(Points[0], Points[1], Points[5], Points[4], _pMesh);
7401  vol = std::abs(vol);
7402  volume = volume + vol;
7403 
7404  vol = Volume(Points[0], Points[1], Points[4], Points[2], _pMesh);
7405  vol = std::abs(vol);
7406  volume = volume + vol;
7407 
7408  vol = Volume(Points[0], Points[2], Points[4], Points[3], _pMesh);
7409  vol = std::abs(vol);
7410  volume = volume + vol;
7411 
7412  double area_intermediate =
7413  Area_Facet_Triangle(Points[1], Points[4], Points[5], _pMesh);
7414  area_intermediate = std::abs(area_intermediate);
7415  area = area + area_intermediate;
7416 
7417  area_intermediate =
7418  Area_Facet_Triangle(Points[1], Points[2], Points[4], _pMesh);
7419  area_intermediate = std::abs(area_intermediate);
7420  area = area + area_intermediate;
7421 
7422  area_intermediate =
7423  Area_Facet_Triangle(Points[2], Points[3], Points[4], _pMesh);
7424  area_intermediate = std::abs(area_intermediate);
7425  area = area + area_intermediate;
7426  }
7427 
7428  else if(type == 11) // [0 1 2 3], [0 1 3 5], [0 3 4 5]
7429  {
7430  double vol = Volume(Points[0], Points[1], Points[3], Points[2], _pMesh);
7431  vol = std::abs(vol);
7432  volume = volume + vol;
7433 
7434  vol = Volume(Points[0], Points[1], Points[5], Points[3], _pMesh);
7435  vol = std::abs(vol);
7436  volume = volume + vol;
7437 
7438  vol = Volume(Points[0], Points[3], Points[5], Points[4], _pMesh);
7439  vol = std::abs(vol);
7440  volume = volume + vol;
7441 
7442  double area_intermediate =
7443  Area_Facet_Triangle(Points[1], Points[2], Points[3], _pMesh);
7444  area_intermediate = std::abs(area_intermediate);
7445  area = area + area_intermediate;
7446 
7447  area_intermediate =
7448  Area_Facet_Triangle(Points[1], Points[3], Points[5], _pMesh);
7449  area_intermediate = std::abs(area_intermediate);
7450  area = area + area_intermediate;
7451 
7452  area_intermediate =
7453  Area_Facet_Triangle(Points[3], Points[4], Points[5], _pMesh);
7454  area_intermediate = std::abs(area_intermediate);
7455  area = area + area_intermediate;
7456  }
7457  }
7458 
7459  else if(valence == 6)
7460  {
7461  if((type == 13) ||
7462  (type == 16)) //[0 1 2 6], [0 2 3 4] , [0 4 5 6], [0 2 4 6]
7463  {
7464  double vol = Volume(Points[0], Points[1], Points[6], Points[2], _pMesh);
7465  vol = std::abs(vol);
7466  volume = volume + vol;
7467 
7468  vol = Volume(Points[0], Points[2], Points[4], Points[3], _pMesh);
7469  vol = std::abs(vol);
7470  volume = volume + vol;
7471 
7472  vol = Volume(Points[0], Points[4], Points[6], Points[5], _pMesh);
7473  vol = std::abs(vol);
7474  volume = volume + vol;
7475 
7476  vol = Volume(Points[0], Points[2], Points[6], Points[4], _pMesh);
7477  vol = std::abs(vol);
7478  volume = volume + vol;
7479 
7480  double area_intermediate =
7481  Area_Facet_Triangle(Points[1], Points[2], Points[6], _pMesh);
7482  area_intermediate = std::abs(area_intermediate);
7483  area = area + area_intermediate;
7484 
7485  area_intermediate =
7486  Area_Facet_Triangle(Points[2], Points[3], Points[4], _pMesh);
7487  area_intermediate = std::abs(area_intermediate);
7488  area = area + area_intermediate;
7489 
7490  area_intermediate =
7491  Area_Facet_Triangle(Points[4], Points[5], Points[6], _pMesh);
7492  area_intermediate = std::abs(area_intermediate);
7493  area = area + area_intermediate;
7494 
7495  area_intermediate =
7496  Area_Facet_Triangle(Points[2], Points[6], Points[4], _pMesh);
7497  area_intermediate = std::abs(area_intermediate);
7498  area = area + area_intermediate;
7499  }
7500 
7501  else if((type == 14) ||
7502  (type == 15)) // [ 0 1 2 3] [ 0 3 4 5] [ 0 1 5 6] [ 0 1 3 5]
7503  {
7504  double vol = Volume(Points[0], Points[1], Points[3], Points[2], _pMesh);
7505  vol = std::abs(vol);
7506  volume = volume + vol;
7507 
7508  vol = Volume(Points[0], Points[3], Points[5], Points[4], _pMesh);
7509  vol = std::abs(vol);
7510  volume = volume + vol;
7511 
7512  vol = Volume(Points[0], Points[1], Points[6], Points[5], _pMesh);
7513  vol = std::abs(vol);
7514  volume = volume + vol;
7515 
7516  vol = Volume(Points[0], Points[1], Points[5], Points[3], _pMesh);
7517  vol = std::abs(vol);
7518  volume = volume + vol;
7519 
7520  double area_intermediate =
7521  Area_Facet_Triangle(Points[1], Points[2], Points[3], _pMesh);
7522  area_intermediate = std::abs(area_intermediate);
7523  area = area + area_intermediate;
7524 
7525  area_intermediate =
7526  Area_Facet_Triangle(Points[3], Points[4], Points[5], _pMesh);
7527  area_intermediate = std::abs(area_intermediate);
7528  area = area + area_intermediate;
7529 
7530  area_intermediate =
7531  Area_Facet_Triangle(Points[1], Points[5], Points[6], _pMesh);
7532  area_intermediate = std::abs(area_intermediate);
7533  area = area + area_intermediate;
7534 
7535  area_intermediate =
7536  Area_Facet_Triangle(Points[1], Points[3], Points[5], _pMesh);
7537  area_intermediate = std::abs(area_intermediate);
7538  area = area + area_intermediate;
7539  }
7540  }
7541 
7542  double volume_3_root = 0.0;
7543 
7544  double volume_measured = 0.0;
7545 
7546  if(volume == 0)
7547  volume_3_root = volume;
7548  else
7549  volume_3_root = exp(1.0 / 3.0 * (double)log(volume));
7550 
7551 
7552  // volume_mea
7553  volume_measured = volume_3_root / (perimeter / (double)valence);
7554 
7555  // if Volume calculated is greater than threshold value, we should give up
7556  // removal of this vertex
7557  if(volume_measured > Threshold)
7558  check = true;
7559 
7560  // tp free memory.
7561  delete[] Points;
7562  delete[] Vectors;
7563 
7564  return check;
7565 }
7566 
7567 
7568 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
7569 double
7572  const typename boost::graph_traits< HalfedgeGraph >::halfedge_descriptor
7573  &h,
7574  const HalfedgeGraph &_pMesh,
7575  const PointMap *_pm)
7576 {
7579 
7580  Point3d P = get(*_pm, target(h, _pMesh));
7581  Point3d Q = get(*_pm, target(next(h, _pMesh), _pMesh));
7582  Point3d R = get(*_pm, target(next(next(h, _pMesh), _pMesh), _pMesh));
7583 
7586 }
7587 
7588 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
7589 double
7591  Area_Facet_Triangle(const Point3d &P,
7592  const Point3d &Q,
7593  const Point3d &R,
7594  const HalfedgeGraph &_pMesh)
7595 {
7597 
7598  Vector PQ = FEVV::Math::Vector::sub< FEVV::Geometry_traits< HalfedgeGraph > >(
7599  Q, P, gt);
7600  // Vector PR = R - P; // MT
7601  Vector QR = FEVV::Math::Vector::sub< FEVV::Geometry_traits< HalfedgeGraph > >(
7602  R, Q, gt);
7603 
7606  double area =
7607  0.5 *
7608  FEVV::Math::Vector::l2_distance< FEVV::Geometry_traits< HalfedgeGraph > >(
7609  normal, gt);
7610 
7611  return area;
7612 }
7613 
7614 
7615 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
7616 double
7618  Volume(const Point3d &A,
7619  const Point3d &B,
7620  const Point3d &C,
7621  const Point3d &D,
7622  const HalfedgeGraph &_pMesh)
7623 {
7625 
7626  //
7627  // from https://fr.wikipedia.org/wiki/T%C3%A9tra%C3%A8dre
7628  // V = (1/6) * det(AB, AC, AD)
7629  //
7630  // from https://fr.wikipedia.org/wiki/D%C3%A9terminant_(math%C3%A9matiques)
7631  // det(X,X',X") = x.y'.z" + x'.y".z + x".y.z' - x.y".z' - x".y'.z - x'.y.z"
7632  //
7633 
7634  Vector AB = FEVV::Math::Vector::sub< FEVV::Geometry_traits< HalfedgeGraph > >(
7635  B, A, gt);
7636  Vector AC = FEVV::Math::Vector::sub< FEVV::Geometry_traits< HalfedgeGraph > >(
7637  C, A, gt);
7638  Vector AD = FEVV::Math::Vector::sub< FEVV::Geometry_traits< HalfedgeGraph > >(
7639  D, A, gt);
7640 
7641  double x1 = AB[0];
7642  double y1 = AB[1];
7643  double z1 = AB[2];
7644 
7645  double x2 = AC[0];
7646  double y2 = AC[1];
7647  double z2 = AC[2];
7648 
7649  double x3 = AD[0];
7650  double y3 = AD[1];
7651  double z3 = AD[2];
7652 
7653  double vol = x1 * y2 * z3 + x2 * y3 * z1 + x3 * y1 * z2 - x1 * y3 * z2 -
7654  x3 * y2 * z1 - x2 * y1 * z3;
7655 
7656  return vol;
7657 }
7658 
7659 
7660 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
7661 Color_Unit
7663  Get_Vertex_Color(const halfedge_descriptor &h, const HalfedgeGraph &_pMesh)
7664 {
7665  return get(this->vertex_color_int, target(h, _pMesh));
7666 }
7667 
7668 
7669 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
7670 Color_Unit
7673  const int &valence,
7674  const HalfedgeGraph &_pMesh)
7675 {
7676  halfedge_descriptor g = h;
7677 
7678  std::vector< Color_Unit >
7679  Neighbor_color; // contain differents colors among neighbors
7680  int Average_c0 = 0, Average_c1 = 0, Average_c2 = 0;
7681 
7682  g = next(g, _pMesh);
7683 
7684  for(int i = 0; i < valence; i++)
7685  {
7686  Color_Unit col = Get_Vertex_Color(opposite(g, _pMesh), _pMesh);
7687 
7688  bool check = false;
7689  for(unsigned j = 0; j < Neighbor_color.size(); j++)
7690  {
7691  if(Neighbor_color[j] == col)
7692  {
7693  check = true;
7694  break;
7695  }
7696  }
7697 
7698  if(!check)
7699  Neighbor_color.push_back(col);
7700 
7701  Average_c0 += col.c0;
7702  Average_c1 += col.c1;
7703  Average_c2 += col.c2;
7704 
7705  g = prev(opposite(g, _pMesh), _pMesh);
7706  }
7707 
7708  Color_Unit Average_color;
7709 
7710  Average_color.c0 = (int)floor((float)(Average_c0 / valence) + 0.5);
7711  Average_color.c1 = (int)floor((float)(Average_c1 / valence) + 0.5);
7712  Average_color.c2 = (int)floor((float)(Average_c2 / valence) + 0.5);
7713 
7714  double Critere_c0 = 50000.0, Critere_c1 = 50000.0, Critere_c2 = 50000.0;
7715  int Index_c0 = -1, Index_c1 = -1, Index_c2 = -1;
7716 
7717  // Find for each component among neighbors' color, the component which is the
7718  // nearst to the average value.
7719  for(unsigned i = 0; i < Neighbor_color.size(); i++)
7720  {
7721  int Color_component_0 = Neighbor_color[i].c0;
7722  int Color_component_1 = Neighbor_color[i].c1;
7723  int Color_component_2 = Neighbor_color[i].c2;
7724 
7725  if(std::abs(Color_component_0 - Average_color.c0) < Critere_c0)
7726  {
7727  Critere_c0 = std::abs(Color_component_0 - Average_color.c0);
7728  Index_c0 = i;
7729  }
7730  if(std::abs(Color_component_1 - Average_color.c1) < Critere_c1)
7731  {
7732  Critere_c1 = std::abs(Color_component_1 - Average_color.c1);
7733  Index_c1 = i;
7734  }
7735  if(std::abs(Color_component_2 - Average_color.c2) < Critere_c2)
7736  {
7737  Critere_c2 = std::abs(Color_component_2 - Average_color.c2);
7738  Index_c2 = i;
7739  }
7740  }
7741 
7742  Color_Unit Resulting_color;
7743  Resulting_color.c0 = Neighbor_color[Index_c0].c0;
7744  Resulting_color.c1 = Neighbor_color[Index_c1].c1;
7745  Resulting_color.c2 = Neighbor_color[Index_c2].c2;
7746 
7747  return Resulting_color;
7748 }
7749 
7750 
7751 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
7752 typename Compression_Valence_Component< HalfedgeGraph,
7753  PointMap,
7754  VertexColorMap >::Point3d
7757  const HalfedgeGraph &_pMesh,
7758  const PointMap *_pm)
7759 {
7760  halfedge_descriptor g = h;
7761  int valence = (int)out_degree(target(next(g, _pMesh), _pMesh), _pMesh);
7762 
7763  double x = 0., y = 0., z = 0.;
7764 
7765  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > vh_it(
7766  target(next(g, _pMesh), _pMesh), _pMesh);
7767  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > vh_it_end = vh_it;
7768 
7769  CGAL_For_all(vh_it, vh_it_end)
7770  {
7771  Point3d pt = get(*_pm, target(opposite(*vh_it, _pMesh), _pMesh));
7772  x += pt[0];
7773  y += pt[1];
7774  z += pt[2];
7775  }
7776 
7777  x = x / (double)valence;
7778  y = y / (double)valence;
7779  z = z / (double)valence;
7780 
7781  return Point3d(x, y, z);
7782 }
7783 
7784 
7785 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
7786 typename Compression_Valence_Component< HalfedgeGraph,
7787  PointMap,
7788  VertexColorMap >::Point3d
7791  const int &valence,
7792  const HalfedgeGraph &_pMesh,
7793  const PointMap *_pm)
7794 {
7795  halfedge_descriptor g = h;
7796  double x = 0, y = 0, z = 0;
7797  for(int i = 0; i < valence; i++)
7798  {
7799  Point3d pt = get(*_pm, target(g, _pMesh));
7800  x += pt[0];
7801  y += pt[1];
7802  z += pt[2];
7803 
7804  g = next(g, _pMesh);
7805  }
7806 
7807  x /= valence;
7808  y /= valence;
7809  z /= valence;
7810 
7811  return Point3d(x, y, z);
7812 }
7813 
7814 
7815 //#define DBG_Retriangulation
7816 
7817 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
7818 void
7820  Retriangulation(HalfedgeGraph &pMesh,
7821  const halfedge_descriptor &ch,
7822  const unsigned &valence,
7823  const unsigned &/*Vertex_number*/,
7824  const int &Component_ID,
7825  const PointMap *_pm)
7826 {
7827  int type = Find_Type(pMesh, ch, valence);
7829  h = ch;
7831  g = next(h, pMesh);
7832 
7833 
7834  // Triangle
7835  if((type == 1) || (type == 2) || (type == 4))
7836  {
7837  put(this->Facet_Flag, face(h, pMesh), TO_BE_REMOVED);
7838  // h->facet()->Patch_Index = Vertex_number;
7839 
7840  put(this->facet_normal, face(h, pMesh), Triangle_Normal(pMesh, _pm, h));
7841 
7842  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
7843 
7844  if(get(this->Vertex_Sign, target(g, pMesh)) == NOSIGN)
7845  put(this->Vertex_Sign, target(g, pMesh), PLUS);
7846  }
7847  else if(type == 3)
7848  {
7849  put(this->Facet_Flag, face(h, pMesh), TO_BE_REMOVED);
7850  // h->facet()->Patch_Index = Vertex_number;
7851 
7852  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
7853 
7854  put(this->facet_normal, face(h, pMesh), Triangle_Normal(pMesh, _pm, h));
7855 
7856  if(get(this->Vertex_Sign, target(g, pMesh)) == NOSIGN)
7857  put(this->Vertex_Sign, target(g, pMesh), MINUS);
7858  }
7859 
7860  // quadrangle
7861  else if((type == 5) || (type == 8))
7862  {
7863  if(get(this->Vertex_Sign, target(g, pMesh)) == NOSIGN)
7864  put(this->Vertex_Sign, target(g, pMesh), PLUS);
7865  if(get(this->Vertex_Sign, target(next(g, pMesh), pMesh)) == NOSIGN)
7866  put(this->Vertex_Sign, target(next(g, pMesh), pMesh), MINUS);
7867 
7868  h = prev(h, pMesh);
7869 #ifdef DBG_Retriangulation
7870  std::cout << "split face" << std::endl;
7871 #endif
7872  h = CGAL::Euler::split_face(h, g, pMesh);
7873 
7874  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
7875  put(this->facet_Component_Number,
7876  face(opposite(h, pMesh), pMesh),
7877  Component_ID);
7878 
7879  put(this->facet_normal, face(h, pMesh), Triangle_Normal(pMesh, _pm, h));
7880  put(this->facet_normal,
7881  face(opposite(h, pMesh), pMesh),
7882  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
7883 
7884 
7885  put(this->Facet_Flag, face(h, pMesh), TO_BE_REMOVED);
7886  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
7887  }
7888 
7889  else if((type == 6) || (type == 7))
7890  {
7891  if(get(this->Vertex_Sign, target(g, pMesh)) == NOSIGN)
7892  put(this->Vertex_Sign, target(g, pMesh), MINUS);
7893  if(get(this->Vertex_Sign, target(next(g, pMesh), pMesh)) == NOSIGN)
7894  put(this->Vertex_Sign, target(next(g, pMesh), pMesh), PLUS);
7895 
7896  g = next(g, pMesh);
7897 #ifdef DBG_Retriangulation
7898  std::cout << "split face" << std::endl;
7899 #endif
7900  h = CGAL::Euler::split_face(h, g, pMesh);
7901 
7902  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
7903  put(this->facet_Component_Number,
7904  face(opposite(h, pMesh), pMesh),
7905  Component_ID);
7906 
7907  put(this->facet_normal, face(h, pMesh), Triangle_Normal(pMesh, _pm, h));
7908  put(this->facet_normal,
7909  face(opposite(h, pMesh), pMesh),
7910  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
7911 
7912  put(this->Facet_Flag, face(h, pMesh), TO_BE_REMOVED);
7913  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
7914  // h->opposite()->facet()->Patch_Index = Vertex_number;
7915  }
7916  // pentagone
7917  else if((type == 9) || (type == 12))
7918  {
7919  if(get(this->Vertex_Sign, target(g, pMesh)) == NOSIGN)
7920  put(this->Vertex_Sign, target(g, pMesh), PLUS);
7921  if(get(this->Vertex_Sign, target(next(g, pMesh), pMesh)) == NOSIGN)
7922  put(this->Vertex_Sign, target(next(g, pMesh), pMesh), MINUS);
7923  if(get(this->Vertex_Sign, target(next(next(g, pMesh), pMesh), pMesh)) ==
7924  NOSIGN)
7925  put(this->Vertex_Sign, target(next(next(g, pMesh), pMesh), pMesh), PLUS);
7926 
7927  h = prev(h, pMesh);
7928 
7929 #ifdef DBG_Retriangulation
7930  std::cout << "split face" << std::endl;
7931 #endif
7932  h = CGAL::Euler::split_face(h, g, pMesh);
7933 
7934  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
7935  put(this->facet_Component_Number,
7936  face(opposite(h, pMesh), pMesh),
7937  Component_ID);
7938 
7939  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
7940  // h->opposite()->facet()->Patch_Index = Vertex_number;
7941  put(this->facet_normal,
7942  face(opposite(h, pMesh), pMesh),
7943  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
7944 
7945  g = next(next(h, pMesh), pMesh);
7946 #ifdef DBG_Retriangulation
7947  std::cout << "split face" << std::endl;
7948 #endif
7949  h = CGAL::Euler::split_face(h, g, pMesh);
7950 
7951  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
7952  put(this->facet_Component_Number,
7953  face(opposite(h, pMesh), pMesh),
7954  Component_ID);
7955 
7956  put(this->facet_normal, face(h, pMesh), Triangle_Normal(pMesh, _pm, h));
7957  put(this->facet_normal,
7958  face(opposite(h, pMesh), pMesh),
7959  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
7960 
7961  put(this->Facet_Flag, face(h, pMesh), TO_BE_REMOVED);
7962  // h->facet()->Patch_Index = Vertex_number;
7963  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
7964  // h->opposite()->facet()->Patch_Index = Vertex_number;
7965  }
7966 
7967  else if(type == 10)
7968  {
7969  if(get(this->Vertex_Sign, target(g, pMesh)) == NOSIGN)
7970  put(this->Vertex_Sign, target(g, pMesh), PLUS);
7971  if(get(this->Vertex_Sign, target(next(g, pMesh), pMesh)) == NOSIGN)
7972  put(this->Vertex_Sign, target(next(g, pMesh), pMesh), MINUS);
7973  if(get(this->Vertex_Sign, target(next(next(g, pMesh), pMesh), pMesh)) ==
7974  NOSIGN)
7975  put(this->Vertex_Sign, target(next(next(g, pMesh), pMesh), pMesh), PLUS);
7976 
7977  g = h;
7978  h = prev(prev(h, pMesh), pMesh);
7979 
7980 #ifdef DBG_Retriangulation
7981  std::cout << "split face" << std::endl;
7982 #endif
7983  h = CGAL::Euler::split_face(h, g, pMesh);
7984 
7985  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
7986  put(this->facet_Component_Number,
7987  face(opposite(h, pMesh), pMesh),
7988  Component_ID);
7989 
7990  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
7991  // h->opposite()->facet()->Patch_Index = Vertex_number;
7992  put(this->facet_normal,
7993  face(opposite(h, pMesh), pMesh),
7994  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
7995 
7996  g = next(h, pMesh);
7997  h = prev(h, pMesh);
7998 
7999 #ifdef DBG_Retriangulation
8000  std::cout << "split face" << std::endl;
8001 #endif
8002  h = CGAL::Euler::split_face(h, g, pMesh);
8003 
8004  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
8005  put(this->facet_Component_Number,
8006  face(opposite(h, pMesh), pMesh),
8007  Component_ID);
8008 
8009  put(this->facet_normal, face(h, pMesh), Triangle_Normal(pMesh, _pm, h));
8010  put(this->facet_normal,
8011  face(opposite(h, pMesh), pMesh),
8012  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
8013 
8014  put(this->Facet_Flag, face(h, pMesh), TO_BE_REMOVED);
8015  // h->facet()->Patch_Index = Vertex_number;
8016  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
8017  // h->opposite()->facet()->Patch_Index = Vertex_number;
8018  }
8019 
8020  else if(type == 11)
8021  {
8022  if(get(this->Vertex_Sign, target(g, pMesh)) == NOSIGN)
8023  put(this->Vertex_Sign, target(g, pMesh), MINUS);
8024  if(get(this->Vertex_Sign, target(next(g, pMesh), pMesh)) == NOSIGN)
8025  put(this->Vertex_Sign, target(next(g, pMesh), pMesh), PLUS);
8026  if(get(this->Vertex_Sign, target(next(next(g, pMesh), pMesh), pMesh)) ==
8027  NOSIGN)
8028  put(this->Vertex_Sign, target(next(next(g, pMesh), pMesh), pMesh), MINUS);
8029 
8030  g = next(g, pMesh);
8031 #ifdef DBG_Retriangulation
8032  std::cout << "split face" << std::endl;
8033 #endif
8034  h = CGAL::Euler::split_face(h, g, pMesh);
8035 
8036  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
8037  put(this->facet_Component_Number,
8038  face(opposite(h, pMesh), pMesh),
8039  Component_ID);
8040 
8041  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
8042  // h->opposite()->facet()->Patch_Index = Vertex_number;
8043 
8044  put(this->facet_normal,
8045  face(opposite(h, pMesh), pMesh),
8046  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
8047  g = next(next(h, pMesh), pMesh);
8048 
8049 #ifdef DBG_Retriangulation
8050  std::cout << "split face" << std::endl;
8051 #endif
8052  h = CGAL::Euler::split_face(h, g, pMesh);
8053 
8054  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
8055  put(this->facet_Component_Number,
8056  face(opposite(h, pMesh), pMesh),
8057  Component_ID);
8058 
8059  put(this->facet_normal, face(h, pMesh), Triangle_Normal(pMesh, _pm, h));
8060  put(this->facet_normal,
8061  face(opposite(h, pMesh), pMesh),
8062  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
8063 
8064  put(this->Facet_Flag, face(h, pMesh), TO_BE_REMOVED);
8065  // h->facet()->Patch_Index = Vertex_number;
8066  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
8067  // h->opposite()->facet()->Patch_Index = Vertex_number;
8068  }
8069 
8070  // Hexagone
8071  else if((type == 13) || (type == 16))
8072  {
8073  if(get(this->Vertex_Sign, target(g, pMesh)) == NOSIGN)
8074  put(this->Vertex_Sign, target(g, pMesh), PLUS);
8075  if(get(this->Vertex_Sign, target(next(g, pMesh), pMesh)) == NOSIGN)
8076  put(this->Vertex_Sign, target(next(g, pMesh), pMesh), MINUS);
8077  if(get(this->Vertex_Sign, target(next(next(g, pMesh), pMesh), pMesh)) ==
8078  NOSIGN)
8079  put(this->Vertex_Sign, target(next(next(g, pMesh), pMesh), pMesh), PLUS);
8080  if(get(this->Vertex_Sign,
8081  target(next(next(next(g, pMesh), pMesh), pMesh), pMesh)) == NOSIGN)
8082  put(this->Vertex_Sign,
8083  target(next(next(next(g, pMesh), pMesh), pMesh), pMesh),
8084  MINUS);
8085 
8086  h = prev(h, pMesh);
8087 #ifdef DBG_Retriangulation
8088  std::cout << "split face" << std::endl;
8089 #endif
8090  h = CGAL::Euler::split_face(h, g, pMesh);
8091 
8092  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
8093  put(this->facet_Component_Number,
8094  face(opposite(h, pMesh), pMesh),
8095  Component_ID);
8096 
8097  put(this->facet_normal,
8098  face(opposite(h, pMesh), pMesh),
8099  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
8100  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
8101  // h->opposite()->facet()->Patch_Index = Vertex_number;
8102 
8103 
8104  g = next(next(h, pMesh), pMesh);
8105 #ifdef DBG_Retriangulation
8106  std::cout << "split face" << std::endl;
8107 #endif
8108  h = CGAL::Euler::split_face(h, g, pMesh);
8109 
8110  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
8111  put(this->facet_Component_Number,
8112  face(opposite(h, pMesh), pMesh),
8113  Component_ID);
8114 
8115  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
8116  // h->opposite()->facet()->Patch_Index = Vertex_number;
8117 
8118  put(this->facet_normal,
8119  face(opposite(h, pMesh), pMesh),
8120  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
8121 
8122  g = next(next(h, pMesh), pMesh);
8123 #ifdef DBG_Retriangulation
8124  std::cout << "split face" << std::endl;
8125 #endif
8126  h = CGAL::Euler::split_face(h, g, pMesh);
8127 
8128  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
8129  put(this->facet_Component_Number,
8130  face(opposite(h, pMesh), pMesh),
8131  Component_ID);
8132 
8133  put(this->facet_normal, face(h, pMesh), Triangle_Normal(pMesh, _pm, h));
8134  put(this->facet_normal,
8135  face(opposite(h, pMesh), pMesh),
8136  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
8137 
8138  put(this->Facet_Flag, face(h, pMesh), TO_BE_REMOVED);
8139  // h->facet()->Patch_Index = Vertex_number;
8140 
8141  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
8142  // h->opposite()->facet()->Patch_Index = Vertex_number;
8143  }
8144 
8145  else if((type == 14) || (type == 15))
8146  {
8147  if(get(this->Vertex_Sign, target(g, pMesh)) == NOSIGN)
8148  put(this->Vertex_Sign, target(g, pMesh), MINUS);
8149  if(get(this->Vertex_Sign, target(next(g, pMesh), pMesh)) == NOSIGN)
8150  put(this->Vertex_Sign, target(next(g, pMesh), pMesh), PLUS);
8151  if(get(this->Vertex_Sign, target(next(next(g, pMesh), pMesh), pMesh)) ==
8152  NOSIGN)
8153  put(this->Vertex_Sign, target(next(next(g, pMesh), pMesh), pMesh), MINUS);
8154  if(get(this->Vertex_Sign,
8155  target(next(next(next(g, pMesh), pMesh), pMesh), pMesh)) == NOSIGN)
8156  put(this->Vertex_Sign,
8157  target(next(next(next(g, pMesh), pMesh), pMesh), pMesh),
8158  PLUS);
8159 
8160 
8161  g = next(g, pMesh);
8162 #ifdef DBG_Retriangulation
8163  std::cout << "split face" << std::endl;
8164 #endif
8165  h = CGAL::Euler::split_face(h, g, pMesh);
8166 
8167  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
8168  put(this->facet_Component_Number,
8169  face(opposite(h, pMesh), pMesh),
8170  Component_ID);
8171 
8172  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
8173  // h->opposite()->facet()->Patch_Index = Vertex_number;
8174 
8175  put(this->facet_normal,
8176  face(opposite(h, pMesh), pMesh),
8177  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
8178 
8179  g = next(next(h, pMesh), pMesh);
8180 #ifdef DBG_Retriangulation
8181  std::cout << "split face" << std::endl;
8182 #endif
8183  h = CGAL::Euler::split_face(h, g, pMesh);
8184 
8185  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
8186  put(this->facet_Component_Number,
8187  face(opposite(h, pMesh), pMesh),
8188  Component_ID);
8189 
8190  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
8191  // h->opposite()->facet()->Patch_Index = Vertex_number;
8192 
8193  put(this->facet_normal,
8194  face(opposite(h, pMesh), pMesh),
8195  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
8196 
8197  g = next(next(h, pMesh), pMesh);
8198 #ifdef DBG_Retriangulation
8199  std::cout << "split face" << std::endl;
8200 #endif
8201  h = CGAL::Euler::split_face(h, g, pMesh);
8202 
8203  put(this->facet_Component_Number, face(h, pMesh), Component_ID);
8204  put(this->facet_Component_Number,
8205  face(opposite(h, pMesh), pMesh),
8206  Component_ID);
8207 
8208  put(this->facet_normal, face(h, pMesh), Triangle_Normal(pMesh, _pm, h));
8209  put(this->facet_normal,
8210  face(opposite(h, pMesh), pMesh),
8211  Triangle_Normal(pMesh, _pm, opposite(h, pMesh)));
8212 
8213  put(this->Facet_Flag, face(h, pMesh), TO_BE_REMOVED);
8214  // h->facet()->Patch_Index = Vertex_number;
8215  put(this->Facet_Flag, face(opposite(h, pMesh), pMesh), TO_BE_REMOVED);
8216  // h->opposite()->facet()->Patch_Index = Vertex_number;
8217  }
8218 }
8219 
8220 
8221 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
8222 typename Compression_Valence_Component< HalfedgeGraph,
8223  PointMap,
8224  VertexColorMap >::Vector
8226  Normal_Patch(const halfedge_descriptor &const_h,
8227  const unsigned int &valence,
8228  const HalfedgeGraph &_pMesh,
8229  const PointMap *_pm)
8230 {
8232 
8233  halfedge_descriptor h = const_h;
8234  int type = Find_Type(_pMesh, h, valence);
8235 
8236  double area[5] = {0, 0, 0, 0, 0};
8237 
8238  Vector *normals = new Vector[5];
8239  Vector normal = Vector(0.0, 0.0, 0.0);
8240  for(int i = 0; i < 5; i++)
8241  {
8242  normals[i] = Vector(0.0, 0.0, 0.0);
8243  }
8244 
8245  // Triangle
8246  if((type == 1) || (type == 2) || (type == 4))
8247  {
8248  normals[1] = Triangle_Normal(_pMesh, _pm, h);
8249  area[1] = Area_Facet_Triangle(h, _pMesh, _pm);
8250  }
8251  else if(type == 3)
8252  {
8253  normals[1] = Triangle_Normal(_pMesh, _pm, h);
8254  area[1] = Area_Facet_Triangle(h, _pMesh, _pm);
8255  }
8256 
8257  // quadrangle
8258  else if((type == 5) || (type == 8))
8259  {
8260  normals[1] = Triangle_Normal(_pMesh, _pm, h);
8261  area[1] = Area_Facet_Triangle(h, _pMesh, _pm);
8262  h = opposite(prev(h, _pMesh), _pMesh);
8263  normals[2] = Triangle_Normal(_pMesh, _pm, h);
8264  area[2] = Area_Facet_Triangle(h, _pMesh, _pm);
8265  }
8266 
8267  else if((type == 6) || (type == 7))
8268  {
8269  normals[1] = Triangle_Normal(_pMesh, _pm, h);
8270  area[1] = Area_Facet_Triangle(h, _pMesh, _pm);
8271 
8272  h = opposite(next(h, _pMesh), _pMesh);
8273  normals[2] = Triangle_Normal(_pMesh, _pm, h);
8274  area[2] = Area_Facet_Triangle(h, _pMesh, _pm);
8275  }
8276 
8277  // pentagone
8278  else if((type == 9) || (type == 12))
8279  {
8280  normals[1] = Triangle_Normal(_pMesh, _pm, h);
8281  area[1] = Area_Facet_Triangle(h, _pMesh, _pm);
8282 
8283  h = opposite(prev(h, _pMesh), _pMesh);
8284  normals[2] = Triangle_Normal(_pMesh, _pm, h);
8285  area[2] = Area_Facet_Triangle(h, _pMesh, _pm);
8286 
8287  h = opposite(next(h, _pMesh), _pMesh);
8288  normals[3] = Triangle_Normal(_pMesh, _pm, h);
8289  area[3] = Area_Facet_Triangle(h, _pMesh, _pm);
8290  }
8291 
8292 
8293  else if(type == 10)
8294  {
8295  normals[1] = Triangle_Normal(_pMesh, _pm, h);
8296  area[1] = Area_Facet_Triangle(h, _pMesh, _pm);
8297 
8298  h = opposite(next(h, _pMesh), _pMesh);
8299  normals[2] = Triangle_Normal(_pMesh, _pm, h);
8300  area[2] = Area_Facet_Triangle(h, _pMesh, _pm);
8301 
8302  h = opposite(prev(h, _pMesh), _pMesh);
8303  normals[3] = Triangle_Normal(_pMesh, _pm, h);
8304  area[3] = Area_Facet_Triangle(h, _pMesh, _pm);
8305  }
8306 
8307  else if(type == 11)
8308  {
8309  halfedge_descriptor g = h;
8310  normals[1] = Triangle_Normal(_pMesh, _pm, h);
8311  area[1] = Area_Facet_Triangle(h, _pMesh, _pm);
8312 
8313  h = opposite(prev(g, _pMesh), _pMesh);
8314  normals[2] = Triangle_Normal(_pMesh, _pm, h);
8315  area[2] = Area_Facet_Triangle(h, _pMesh, _pm);
8316 
8317  h = opposite(next(g, _pMesh), _pMesh);
8318  normals[3] = Triangle_Normal(_pMesh, _pm, h);
8319  area[3] = Area_Facet_Triangle(h, _pMesh, _pm);
8320  }
8321 
8322  // Hexagone
8323  else if((type == 13) || (type == 16))
8324  {
8326  normals[1] = Triangle_Normal(_pMesh, _pm, h);
8327  area[1] = Area_Facet_Triangle(h, _pMesh, _pm);
8328 
8329  h = opposite(prev(h, _pMesh), _pMesh);
8330  g = h;
8331  normals[2] = Triangle_Normal(_pMesh, _pm, h);
8332  area[2] = Area_Facet_Triangle(h, _pMesh, _pm);
8333 
8334  h = opposite(prev(g, _pMesh), _pMesh);
8335  normals[3] = Triangle_Normal(_pMesh, _pm, h);
8336  area[3] = Area_Facet_Triangle(h, _pMesh, _pm);
8337 
8338  h = opposite(next(g, _pMesh), _pMesh);
8339  normals[4] = Triangle_Normal(_pMesh, _pm, h);
8340  area[4] = Area_Facet_Triangle(h, _pMesh, _pm);
8341  }
8342 
8343  else if((type == 14) || (type == 15))
8344  {
8346  normals[1] = Triangle_Normal(_pMesh, _pm, h);
8347  area[1] = Area_Facet_Triangle(h, _pMesh, _pm);
8348 
8349  h = opposite(next(h, _pMesh), _pMesh);
8350  g = h;
8351  normals[2] = Triangle_Normal(_pMesh, _pm, h);
8352  area[2] = Area_Facet_Triangle(h, _pMesh, _pm);
8353 
8354  h = opposite(prev(g, _pMesh), _pMesh);
8355  normals[3] = Triangle_Normal(_pMesh, _pm, h);
8356  area[3] = Area_Facet_Triangle(h, _pMesh, _pm);
8357 
8358  h = opposite(next(g, _pMesh), _pMesh);
8359  normals[4] = Triangle_Normal(_pMesh, _pm, h);
8360  area[4] = Area_Facet_Triangle(h, _pMesh, _pm);
8361  }
8362 
8363  for(unsigned int i = 0; i < (valence - 2); i++)
8364  area[0] = area[0] + area[i + 1];
8365 
8366  for(unsigned int i = 0; i < (valence - 2); i++)
8367  area[i + 1] = area[i + 1] / area[0];
8368 
8369  for(unsigned int i = 0; i < (valence - 2); i++)
8370  normal = normal + FEVV::Math::Vector::scalar_mult<
8372  normals[i + 1], area[i + 1], gt);
8373 
8374  if(area[0] == 0.0)
8375  normal = Vector(0.0, 0.0, 0.0);
8376 
8377  double length =
8378  FEVV::Math::Vector::l2_distance< FEVV::Geometry_traits< HalfedgeGraph > >(
8379  normal, gt);
8380  if(length != 0)
8382  FEVV::Geometry_traits< HalfedgeGraph > >(normal, 1.0 / length, gt);
8383 
8384  delete[] normals;
8385  return normal;
8386 }
8387 
8388 
8389 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
8390 typename Compression_Valence_Component< HalfedgeGraph,
8391  PointMap,
8392  VertexColorMap >::Vector
8395  const Vector &normal,
8396  Vector &T2,
8397  const HalfedgeGraph &_pMesh,
8398  const PointMap *_pm)
8399 {
8401 
8402  Point3d P = get(*_pm, target(h, _pMesh));
8403  Point3d Q = get(*_pm, target(opposite(h, _pMesh), _pMesh));
8404 
8405  Vector T1 = Vector(0.0, 0.0, 0.0);
8406  Vector u = FEVV::Math::Vector::sub< FEVV::Geometry_traits< HalfedgeGraph > >(
8407  P, Q, gt);
8408 
8409  double length =
8410  FEVV::Math::Vector::l2_distance< FEVV::Geometry_traits< HalfedgeGraph > >(
8411  u, gt);
8412  if(length != 0)
8414  FEVV::Geometry_traits< HalfedgeGraph > >(u, 1.0 / length, gt);
8415 
8416  double product =
8417  FEVV::Math::Vector::l2_distance< FEVV::Geometry_traits< HalfedgeGraph > >(
8418  u, gt) *
8420  normal, gt);
8421 
8422  // cosine
8423  double dot =
8424  FEVV::Math::Vector::dot_product< FEVV::Geometry_traits< HalfedgeGraph > >(
8425  u, normal, gt);
8426  double cosine = 0;
8427  if(product != 0)
8428  cosine = dot / product;
8429 
8430  if(cosine > 1.0)
8431  cosine = 1.0;
8432  if(cosine < -1.0)
8433  cosine = -1.0;
8434 
8435  double cosine_rad = std::acos(cosine);
8436 
8437  double beta_rad = 0;
8438  if(cosine_rad <= PI / 2)
8439  beta_rad = PI / 2 - cosine_rad;
8440  else
8441  beta_rad = cosine_rad - PI / 2;
8442  double beta = std::cos(beta_rad);
8443 
8444  if(beta != 0)
8445  {
8448  normal, cosine, gt); // = cosine * normal
8449  Vector tmp2 = u - tmp1; // = u - cosine * normal
8452  tmp2, 1.0 / beta, gt); // = (u - cosine * normal) / beta
8453  }
8454  else
8455  T1 = Vector(0.0, 0.0, 0.0);
8456 
8458  FEVV::Geometry_traits< HalfedgeGraph > >(normal, T1, gt);
8459 
8460  return T1;
8461 }
8462 
8463 
8464 static inline int
8465 Signe(const double &x)
8466 {
8467  return (x < 0.) ? -1 : 1;
8468 }
8469 
8470 template< typename T >
8471 static inline T
8472 square(const T x)
8473 {
8474  return x * x;
8475 }
8476 
8477 
8478 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
8479 Point_Int
8481  Frenet_Rotation(const Point_Int &Dist,
8482  const Vector &T1,
8483  const Vector &T2,
8484  const Vector &normal)
8485 {
8486  typedef Eigen::Matrix3d Matrix;
8487 
8488  Matrix R;
8489  R << T1[0], T2[0], normal[0], T1[1], T2[1], normal[1], T1[2], T2[2],
8490  normal[2];
8491  Matrix M = R;
8492  R.transposeInPlace();
8493  Vector Dist1(Dist.x, Dist.y, Dist.z);
8494  // Vector Dist2 = Rt * Dist1; // MT
8495  Matrix D1;
8496  D1 << 1, 0, 0, 0, 1, 0, 0, 0, 1;
8497  Matrix D2;
8498  D2 << 0, 1, 0, 1, 0, 0, 0, 0, 1;
8499  Matrix D3;
8500  D3 << -1, 0, 0, 0, -1, 0, 0, 0, 1;
8501  Matrix D4;
8502  D4 << 1, 0, 0, 0, 0, 1, 0, 1, 0;
8503  Matrix D5;
8504  D5 << 1, 0, 0, 0, -1, 0, 0, 0, -1;
8505  Matrix *S = new Matrix[16];
8506 
8507  // Verify in order to find the smallest rotation angle.
8508  if(std::abs(M(0, 2)) > std::abs(M(1, 2)))
8509  S[0] = D2;
8510  else
8511  S[0] = D1;
8512  M = S[0] * M;
8513 
8514  if(M(1, 2) < 0)
8515  S[1] = D3;
8516  else
8517  S[1] = D1;
8518 
8519  M = S[1] * M;
8520 
8522  double phi = -100;
8523 
8524  if(square(M(0, 2)) + square(M(1, 2)) == 0)
8525  phi = 0;
8526  else
8527  phi = Signe(-1 * M(0, 2)) *
8528  std::acos(M(1, 2) / std::sqrt(square(M(0, 2)) + square(M(1, 2))));
8529 
8530  Matrix R1;
8531  R1 << std::cos(phi), -std::sin(phi), 0, std::sin(phi), std::cos(phi), 0, 0, 0,
8532  1;
8533 
8534  S[2] << 1, -std::tan(phi / 2), 0, 0, 1, 0, 0, 0, 1;
8535  S[3] << 1, 0, 0, std::sin(phi), 1, 0, 0, 0, 1;
8536  S[4] = S[2];
8537 
8538  Matrix R1inv;
8539  R1inv << std::cos(phi), std::sin(phi), 0, -std::sin(phi), std::cos(phi), 0, 0,
8540  0, 1;
8541 
8542  M = R1inv * M;
8543 
8544  if(std::abs(M(1, 2)) > std::abs(M(2, 2)))
8545  S[5] = D4;
8546  else
8547  S[5] = D1;
8548 
8549  M = S[5] * M;
8550 
8551  if(M(2, 2) < 0)
8552  S[6] = D5;
8553  else
8554  S[6] = D1;
8555 
8556  M = S[6] * M;
8557  double psi = -100;
8558 
8560  if(square(M(1, 2)) + square(M(2, 2)) == 0)
8561  psi = 0;
8562  else
8563  psi = Signe(-1 * M(1, 2)) *
8564  std::acos(M(2, 2) / std::sqrt(square(M(1, 2)) + square(M(2, 2))));
8565 
8566  Matrix R2;
8567  R2 << 1, 0, 0, 0, std::cos(psi), -std::sin(psi), 0, std::sin(psi),
8568  std::cos(psi);
8569  S[7] << 1, 0, 0, 0, 1, -std::tan(psi / 2), 0, 0, 1;
8570  S[8] << 1, 0, 0, 0, 1, 0, 0, std::sin(psi), 1;
8571  S[9] = S[7];
8572 
8573  Matrix R2inv;
8574  R2inv << 1, 0, 0, 0, std::cos(psi), std::sin(psi), 0, -std::sin(psi),
8575  std::cos(psi);
8576  M = R2inv * M;
8577 
8578  if(std::abs(M(0, 1)) > std::abs(M(1, 1)))
8579  S[10] = D2;
8580  else
8581  S[10] = D1;
8582  M = S[10] * M;
8583 
8584  if(M(1, 1) < 0)
8585  S[11] = D3;
8586  else
8587  S[11] = D1;
8588  M = S[11] * M;
8589  double theta = -100;
8590 
8592  if(square(M(0, 1)) + square(M(1, 1)) == 0)
8593  theta = 0;
8594  else
8595  theta = Signe(-1 * M(0, 1)) *
8596  std::acos(M(1, 1) / std::sqrt(square(M(0, 1)) + square(M(1, 1))));
8597 
8598  S[12] << 1, -std::tan(theta / 2), 0, 0, 1, 0, 0, 0, 1;
8599  S[13] << 1, 0, 0, std::sin(theta), 1, 0, 0, 0, 1;
8600  S[14] = S[12];
8601 
8602  Matrix R3;
8603  R3 << std::cos(theta), -std::sin(theta), 0, std::sin(theta), std::cos(theta),
8604  0, 0, 0, 1;
8605  Matrix R3inv = R3.inverse();
8606  /*Matrix S16 = */ R3inv *M; // MT //ELO useless-line
8607 
8608  Eigen::Vector3d u;
8609  u << Dist.x, Dist.y, Dist.z;
8610  Matrix m_inter;
8611 
8612  // Procedure of the bijection.
8613  for(int i = 0; i < 15; i++)
8614  {
8615  if((i == 0) || (i == 1) || (i == 5) || (i == 6) || (i == 10) || (i == 11))
8616  m_inter = S[i];
8617  else
8618  m_inter << S[i](0, 0), -S[i](0, 1), -S[i](0, 2), -S[i](1, 0), S[i](1, 1),
8619  -S[i](1, 2), -S[i](2, 0), -S[i](2, 1), S[i](2, 2);
8620  u = m_inter * u;
8621 
8622  int x = 0, y = 0, z = 0;
8623  x = ceil(u(0) - 0.5);
8624  y = ceil(u(1) - 0.5);
8625  z = ceil(u(2) - 0.5);
8626 
8627  u << x, y, z;
8628  }
8629 
8630  Point_Int New_Coordinates;
8631  New_Coordinates.x = (int)u(0);
8632  New_Coordinates.y = (int)u(1);
8633  New_Coordinates.z = (int)u(2);
8634 
8635  delete[] S;
8636  return New_Coordinates;
8637 }
8638 
8639 //#define DBG_Inverse_Frenet_Rotation
8640 
8641 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
8642 Point_Int
8644  Inverse_Frenet_Rotation(const Point_Int &Frenet,
8645  const Vector &T1,
8646  const Vector &T2,
8647  const Vector &normal)
8648 {
8649 
8650 #ifdef DBG_Inverse_Frenet_Rotation
8651  static unsigned int dbg_Inverse_Frenet_Rotation_call_cnt = 0;
8652  std::cout << __func__ << " call #" << ++dbg_Inverse_Frenet_Rotation_call_cnt
8653  << std::endl;
8654 #endif
8655 
8656  typedef Eigen::Matrix3d Matrix;
8657 
8658  Matrix R;
8659  R << T1[0], T2[0], normal[0], T1[1], T2[1], normal[1], T1[2], T2[2],
8660  normal[2];
8661  Matrix M = R;
8662 
8663  Matrix D1;
8664  D1 << 1, 0, 0, 0, 1, 0, 0, 0, 1;
8665  Matrix D2;
8666  D2 << 0, 1, 0, 1, 0, 0, 0, 0, 1;
8667  Matrix D3;
8668  D3 << -1, 0, 0, 0, -1, 0, 0, 0, 1;
8669  Matrix D4;
8670  D4 << 1, 0, 0, 0, 0, 1, 0, 1, 0;
8671  Matrix D5;
8672  D5 << 1, 0, 0, 0, -1, 0, 0, 0, -1;
8673  Matrix *S = new Matrix[16];
8674 
8675  // Verify in order to find the smallest rotation angle.
8676  if(std::abs(M(0, 2)) > std::abs(M(1, 2)))
8677  S[0] = D2;
8678  else
8679  S[0] = D1;
8680  M = S[0] * M;
8681 
8682  if(M(1, 2) < 0)
8683  S[1] = D3;
8684  else
8685  S[1] = D1;
8686 
8687  M = S[1] * M;
8688 
8690  double phi = -100;
8691 
8692  if(square(M(0, 2)) + square(M(1, 2)) == 0)
8693  phi = 0;
8694  else
8695  phi = Signe(-1 * M(0, 2)) *
8696  std::acos(M(1, 2) / std::sqrt(square(M(0, 2)) + square(M(1, 2))));
8697 
8698  Matrix R1;
8699  R1 << std::cos(phi), -std::sin(phi), 0, std::sin(phi), std::cos(phi), 0, 0, 0,
8700  1;
8701 
8702  S[2] << 1, -std::tan(phi / 2), 0, 0, 1, 0, 0, 0, 1;
8703  S[3] << 1, 0, 0, std::sin(phi), 1, 0, 0, 0, 1;
8704  S[4] = S[2];
8705 
8706  // Matrix R1inv = inverse_matrix(R1);
8707  Matrix R1inv;
8708  R1inv << std::cos(phi), std::sin(phi), 0, -std::sin(phi), std::cos(phi), 0, 0,
8709  0, 1;
8710 
8711  M = R1inv * M;
8712 
8713  if(std::abs(M(1, 2)) > std::abs(M(2, 2)))
8714  S[5] = D4;
8715  else
8716  S[5] = D1;
8717 
8718  M = S[5] * M;
8719 
8720  if(M(2, 2) < 0)
8721  S[6] = D5;
8722  else
8723  S[6] = D1;
8724 
8725  M = S[6] * M;
8726  double psi = -100;
8727 
8729  if(square(M(1, 2)) + square(M(2, 2)) == 0)
8730  psi = 0;
8731  else
8732  psi = Signe(-1 * M(1, 2)) *
8733  std::acos(M(2, 2) / std::sqrt(square(M(1, 2)) + square(M(2, 2))));
8734 
8735  Matrix R2;
8736  R2 << 1, 0, 0, 0, std::cos(psi), -std::sin(psi), 0, std::sin(psi),
8737  std::cos(psi);
8738  S[7] << 1, 0, 0, 0, 1, -std::tan(psi / 2), 0, 0, 1;
8739  S[8] << 1, 0, 0, 0, 1, 0, 0, std::sin(psi), 1;
8740  S[9] = S[7];
8741 
8742  // Matrix R2inv = inverse_matrix(R2);
8743  Matrix R2inv;
8744  R2inv << 1, 0, 0, 0, std::cos(psi), std::sin(psi), 0, -std::sin(psi),
8745  std::cos(psi);
8746  M = R2inv * M;
8747 
8748  if(std::abs(M(0, 1)) > std::abs(M(1, 1)))
8749  S[10] = D2;
8750  else
8751  S[10] = D1;
8752  M = S[10] * M;
8753 
8754  if(M(1, 1) < 0)
8755  S[11] = D3;
8756  else
8757  S[11] = D1;
8758  M = S[11] * M;
8759  double theta = -100;
8760 
8762  if(square(M(0, 1)) + square(M(1, 1)) == 0)
8763  theta = 0;
8764  else
8765  theta = Signe(-1 * M(0, 1)) *
8766  std::acos(M(1, 1) / std::sqrt(square(M(0, 1)) + square(M(1, 1))));
8767 
8768  S[12] << 1, -std::tan(theta / 2), 0, 0, 1, 0, 0, 0, 1;
8769  S[13] << 1, 0, 0, std::sin(theta), 1, 0, 0, 0, 1;
8770  S[14] = S[12];
8771 
8772  Matrix R3;
8773  R3 << std::cos(theta), -std::sin(theta), 0, std::sin(theta), std::cos(theta),
8774  0, 0, 0, 1;
8775  Matrix R3inv = R3.inverse();
8776  /*Matrix S16 = */ R3inv *M; // MT //ELO useless-line
8777 
8778  Eigen::Vector3d u;
8779  u << Frenet.x, Frenet.y, Frenet.z;
8780  Matrix m_inter;
8781 
8782  for(int i = 14; i > -1; i--)
8783  {
8784  m_inter = S[i];
8785 
8786 #ifdef DBG_Inverse_Frenet_Rotation
8787  if(dbg_Inverse_Frenet_Rotation_call_cnt == 1596)
8788  {
8789  std::cout << __func__ << " mark #1"
8790  << " i=" << i << " u=" << u(0) << " " << u(1) << " " << u(2)
8791  << " m_inter=" << m_inter(0, 0) << " " << m_inter(1, 0) << " "
8792  << m_inter(2, 0) << " " << m_inter(0, 1) << " " << m_inter(1, 1)
8793  << " " << m_inter(2, 1) << " " << m_inter(0, 2) << " "
8794  << m_inter(1, 2) << " " << m_inter(2, 2) << std::endl;
8795  }
8796 #endif
8797 
8798  // ELO-porting-note:
8799  // u = -1 * m_inter * u;
8800  // calls
8801  // 1) MatrixC33 operator* ( RT const& c, MatrixC33 const& m )
8802  // at
8803  // Mepp1.github/src/components/Compression/Compression_Valence/src/Matrix3X3.h:253
8804  // with c = -1
8805  // 2) Vector_3 operator* ( MatrixC33 const& m, Vector_3 const& v )
8806  // at
8807  // Mepp1.github/src/components/Compression/Compression_Valence/src/Matrix3X3.h:263
8808  u = -1 * m_inter * u;
8809 
8810  int x = 0, y = 0, z = 0;
8811  x = -std::ceil(u(0) - 0.5);
8812  y = -std::ceil(u(1) - 0.5);
8813  z = -std::ceil(u(2) - 0.5);
8814 
8815 #ifdef DBG_Inverse_Frenet_Rotation
8816  if(dbg_Inverse_Frenet_Rotation_call_cnt == 1596)
8817  {
8818  std::cout << __func__ << " mark #2"
8819  << " i=" << i << " u=" << u(0) << " " << u(1) << " " << u(2)
8820  << " x=" << x << " y=" << y << " z=" << z << std::endl;
8821  }
8822 #endif
8823 
8824  u << x, y, z;
8825 #ifdef DBG_Inverse_Frenet_Rotation
8826  if(dbg_Inverse_Frenet_Rotation_call_cnt == 1596)
8827  {
8828  std::cout << __func__ << " mark #3"
8829  << " i=" << i << " u=" << u(0) << " " << u(1) << " " << u(2)
8830  << std::endl;
8831  }
8832 #endif
8833  }
8834 
8835  Point_Int Dist;
8836  Dist.x = (int)u(0);
8837  Dist.y = (int)u(1);
8838  Dist.z = (int)u(2);
8839 
8840 #ifdef DBG_Inverse_Frenet_Rotation
8841  if(dbg_Inverse_Frenet_Rotation_call_cnt == 1596)
8842  {
8843  std::cout << __func__ << " mark #4"
8844  << " Dist=" << Dist.x << " " << Dist.y << " " << Dist.z
8845  << std::endl;
8846  }
8847 #endif
8848 
8849  delete[] S;
8850  return Dist;
8851 }
8852 
8853 
8854 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
8855 Color_Unit
8858  const int &valence,
8859  const HalfedgeGraph &_pMesh)
8860 {
8861  halfedge_descriptor g = h;
8862 
8863  Color_Unit Average_color;
8864  Average_color.c0 = 0;
8865  Average_color.c1 = 0;
8866  Average_color.c2 = 0;
8867 
8868  for(int i = 0; i < valence; i++)
8869  {
8870  Color_Unit col = Get_Vertex_Color(g, _pMesh);
8871  Average_color.c0 += col.c0;
8872  Average_color.c1 += col.c1;
8873  Average_color.c2 += col.c2;
8874 
8875  g = next(g, _pMesh);
8876  }
8877 
8878  Color_Unit Resulting_color;
8879  Resulting_color.c0 = floor((float)Average_color.c0 / valence + 0.5);
8880  Resulting_color.c1 = floor((float)Average_color.c1 / valence + 0.5);
8881  Resulting_color.c2 = floor((float)Average_color.c2 / valence + 0.5);
8882 
8883  return Resulting_color;
8884 }
8885 
8886 
8887 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
8888 int
8890  Regulation(HalfedgeGraph &_pMesh,
8891  const bool /*Normal_flipping*/,
8892  const bool Use_metric,
8893  const float &Metric_thread,
8894  const bool Use_forget_metric,
8895  const int &Forget_value,
8896  const int &Component_ID,
8897  const PointMap *_pm)
8898 {
8899  double Max_color, Mean_color;
8900  int Temp_NV = 0;
8901  int Number_facets;
8902  this->Calculate_Edge_Color_Difference(
8903  _pMesh, Component_ID, Max_color, Mean_color, Temp_NV);
8904  this->Recalculate_Component_Area(_pMesh, _pm, Component_ID, Number_facets);
8905  double Mean_area =
8906  (double)this->ComponentArea[Component_ID] / (double)Number_facets;
8907 
8908  // Initialization
8909  Init(_pMesh);
8910 
8911 
8912  // Number of removed vertices and number of connectivity symbols
8913  int Number_vertices = 0;
8914  int Number_symbol = 0;
8915 
8916  auto halfedge_iterator_pair = halfedges(_pMesh);
8917  halfedge_iterator hi = halfedge_iterator_pair.first;
8918 
8919  while(
8920  (get(this->vertex_Seed_Edge, target(*hi, _pMesh)) != 2 * Component_ID) ||
8921  (get(this->vertex_Seed_Edge, target(opposite(*hi, _pMesh), _pMesh)) !=
8922  2 * Component_ID + 1))
8923  hi++;
8924 
8925  halfedge_descriptor First_halfedge = *hi;
8926 
8927  put(this->Vertex_Flag, target(First_halfedge, _pMesh), CONQUERED);
8928  put(this->Vertex_Flag,
8929  target(opposite(First_halfedge, _pMesh), _pMesh),
8930  CONQUERED);
8931 
8932  std::queue< halfedge_descriptor > Halfedges;
8933  Halfedges.push(First_halfedge);
8934 
8936 
8937  while(!Halfedges.empty())
8938  {
8939  h = Halfedges.front();
8940  Halfedges.pop();
8941 
8942  size_t valence = out_degree(target(next(h, _pMesh), _pMesh), _pMesh);
8943  // int Component_ID = h->next()->vertex()->Component_Number;
8944 
8945  if((get(this->Facet_Flag, face(h, _pMesh)) == CONQUERED) ||
8946  (get(this->Facet_Flag, face(h, _pMesh)) == TO_BE_REMOVED))
8947  continue;
8948 
8949  else if((get(this->Vertex_Flag, target(next(h, _pMesh), _pMesh)) == FREE) &&
8950  (valence == 3) &&
8951  (Is_Border_Vertex(next(h, _pMesh), _pMesh) ==
8952  false)) // if valence is 3, remove the front vertex.
8953  {
8954  halfedge_descriptor g = h;
8955  int type = 1; // ant type of valence 3
8956 
8957  // Check if the manifold property is violated.
8958  // bool Manifold_condition = Is_Manifold_Property_Violated(h, type,
8959  // valence);
8960 
8961  // calculate error caused by the removal. This metric decides if the
8962  // vertex can be removed or not.
8963  bool Geometric_metric_condition = false;
8964  if(Use_metric == true)
8965  {
8966  if(Use_forget_metric == true)
8967  {
8968  if(FEVV::size_of_vertices(_pMesh) > (unsigned)Forget_value)
8969  Geometric_metric_condition = false;
8970  else
8971  Geometric_metric_condition = Is_Geometric_Metric_Violated(
8972  _pMesh, _pm, h, type, valence, Metric_thread);
8973  }
8974 
8975  else
8976  Geometric_metric_condition = Is_Geometric_Metric_Violated(
8977  _pMesh, _pm, h, type, valence, Metric_thread);
8978  }
8979  bool Is_Color_Too_Important = false;
8980 
8981 #ifdef USE_COLOR_METRIC
8982  if(this->IsColored)
8983  {
8984  Is_Color_Too_Important = this->Error_Projected_Surface(
8985  _pMesh, _pm, h, Component_ID, Mean_color, Mean_area);
8986  }
8987 #endif
8988 
8989  // remove the front vertex if its removal does not viloate the manifold
8990  // property and some metrics
8991  bool Check_all_condition = false;
8992 
8993  if((!Geometric_metric_condition) && (!Is_Color_Too_Important))
8994  Check_all_condition = true;
8995 
8996  // All conditions are goods. Remove the front vertex
8997  if(Check_all_condition)
8998  {
8999  Number_vertices++;
9000  Number_symbol++;
9001 
9002  // Insertion of a symbol 3 to the list
9003  this->InterConnectivity.push_front(0);
9004 
9005  Point3d Geo_info = get(*_pm, target(next(h, _pMesh), _pMesh));
9006  Point_Int Geo = Change_Real_Int(Geo_info, Component_ID);
9007 
9008  Point3d Barycenter = Barycenter_Patch_Before_Removal(g, _pMesh, _pm);
9009  Point_Int BC = Change_Real_Int(Barycenter, Component_ID);
9010 
9011 
9012  if((this->IsColored) && (!this->IsOneColor))
9013  {
9014  Color_Unit Removed_vertex_color;
9015 
9016  Removed_vertex_color = Get_Vertex_Color(next(h, _pMesh), _pMesh);
9017 
9018  Color_Unit Average_color;
9019  Average_color = Get_Average_Vertex_Color_Lee(g, valence, _pMesh);
9020 
9021  Color_Unit Color_diff = Removed_vertex_color - Average_color;
9022 
9023  this->InterVertexColor.push_front(Color_diff);
9024  }
9025 
9026  g = h;
9027 
9028  // P, Q, R are used to compute the normal of triangle after removal
9029  Point3d P = get(*_pm, target(g, _pMesh));
9030  g = next(opposite(next(g, _pMesh), _pMesh), _pMesh);
9031  Point3d Q = get(*_pm, target(g, _pMesh));
9032  g = next(opposite(next(g, _pMesh), _pMesh), _pMesh);
9033  Point3d R = get(*_pm, target(g, _pMesh));
9034  g = h;
9035 
9036  Vector normal = Triangle_Normal(_pMesh, P, Q, R);
9037  Vector T2 = Vector(0.0, 0.0, 0.0);
9038  Vector T1 = Calculate_T1_T2(h, normal, T2, _pMesh, _pm);
9039 
9040  if(T1 == Vector(0.0, 0.0, 0.0))
9041  {
9042  T1 = Vector(1, 0, 0);
9043  T2 = Vector(0, 1, 0);
9044  normal = Vector(0, 0, 1);
9045  }
9046 
9047  else if(normal == Vector(0.0, 0.0, 0.0))
9048  {
9049  T1 = Vector(1, 0, 0);
9050  T2 = Vector(0, 1, 0);
9051  normal = Vector(0, 0, 1);
9052  }
9053  else if(T2 == Vector(0.0, 0.0, 0.0))
9054  {
9055  T1 = Vector(1, 0, 0);
9056  T2 = Vector(0, 1, 0);
9057  normal = Vector(0, 0, 1);
9058  }
9059 
9060  Point_Int Dist = Geo - BC;
9061  Point_Int Frenet_Coordinates;
9062 
9063  if(this->Is_Bijection_Enabled)
9064  Frenet_Coordinates = Frenet_Rotation(Dist, T1, T2, normal);
9065  else
9066  Frenet_Coordinates = Dist;
9067 
9068  this->InterGeometry.push_front(Frenet_Coordinates);
9069 
9070  g = next(h, _pMesh);
9071  put(this->Vertex_Flag, target(g, _pMesh), TO_BE_REMOVED);
9072  put(this->Facet_Flag, face(g, _pMesh), TO_BE_REMOVED);
9073 
9074  g = prev(opposite(g, _pMesh), _pMesh);
9075  put(this->Vertex_Flag, target(opposite(g, _pMesh), _pMesh), CONQUERED);
9076  put(this->Facet_Flag, face(g, _pMesh), TO_BE_REMOVED);
9077 
9078  if(!CGAL::is_border_edge(prev(g, _pMesh), _pMesh))
9079  {
9080  halfedge_descriptor h1 = opposite(prev(g, _pMesh), _pMesh);
9081  put(this->Facet_Flag, face(h1, _pMesh), CONQUERED);
9082  put(this->Vertex_Flag, target(next(h1, _pMesh), _pMesh), CONQUERED);
9083  if(!CGAL::is_border_edge(next(h1, _pMesh), _pMesh))
9084  Halfedges.push(opposite(next(h1, _pMesh), _pMesh));
9085  if(!CGAL::is_border_edge(prev(h1, _pMesh), _pMesh))
9086  Halfedges.push(opposite(prev(h1, _pMesh), _pMesh));
9087  }
9088  g = prev(opposite(g, _pMesh), _pMesh);
9089  put(this->Vertex_Flag, target(opposite(g, _pMesh), _pMesh), CONQUERED);
9090  put(this->Facet_Flag, face(g, _pMesh), TO_BE_REMOVED);
9091  if(!CGAL::is_border_edge(prev(g, _pMesh), _pMesh))
9092  {
9093  halfedge_descriptor h2 = opposite(prev(g, _pMesh), _pMesh);
9094  put(this->Facet_Flag, face(h2, _pMesh), CONQUERED);
9095  put(this->Vertex_Flag, target(next(h2, _pMesh), _pMesh), CONQUERED);
9096  if(!CGAL::is_border_edge(next(h2, _pMesh), _pMesh))
9097  Halfedges.push(opposite(next(h2, _pMesh), _pMesh));
9098  if(!CGAL::is_border_edge(prev(h2, _pMesh), _pMesh))
9099  Halfedges.push(opposite(prev(h2, _pMesh), _pMesh));
9100  }
9101  }
9102 
9103  else
9104  {
9105  this->InterConnectivity.push_front(1);
9106  Number_symbol++;
9107  put(this->Facet_Flag, face(h, _pMesh), CONQUERED);
9108  put(this->Vertex_Flag, target(next(h, _pMesh), _pMesh), CONQUERED);
9109  if(!CGAL::is_border_edge(next(h, _pMesh), _pMesh))
9110  Halfedges.push(opposite(next(h, _pMesh), _pMesh));
9111  if(!CGAL::is_border_edge(prev(h, _pMesh), _pMesh))
9112  Halfedges.push(opposite(prev(h, _pMesh), _pMesh));
9113  }
9114  }
9115  else // NULL triangle
9116  {
9117  this->InterConnectivity.push_front(1);
9118  Number_symbol++;
9119  put(this->Facet_Flag, face(h, _pMesh), CONQUERED);
9120  put(this->Vertex_Flag, target(next(h, _pMesh), _pMesh), CONQUERED);
9121  if(!CGAL::is_border_edge(next(h, _pMesh), _pMesh))
9122  Halfedges.push(opposite(next(h, _pMesh), _pMesh));
9123  if(!CGAL::is_border_edge(prev(h, _pMesh), _pMesh))
9124  Halfedges.push(opposite(prev(h, _pMesh), _pMesh));
9125  }
9126  }
9127 
9128 
9129  // Removal of all vertices with TO_BE_REMOVED flag
9130  vertex_iterator pVertex;
9131  for(pVertex = vertices(_pMesh).first; pVertex != vertices(_pMesh).second;)
9132  {
9133  vertex_descriptor vh = *pVertex;
9134  pVertex++;
9135 
9136  if(get(this->Vertex_Flag, vh) == TO_BE_REMOVED)
9137  {
9138  halfedge_descriptor temp = halfedge(vh, _pMesh);
9139  temp = CGAL::Euler::remove_center_vertex(temp, _pMesh);
9140  put(this->facet_Component_Number, face(temp, _pMesh), Component_ID);
9141  }
9142  }
9143 
9144  if((this->IsColored) && (!this->IsOneColor))
9145  {
9146  while(!this->InterVertexColor.empty())
9147  {
9148  Color_Unit Col = this->InterVertexColor.front();
9149  this->InterVertexColor.pop_front();
9150  this->VertexColor[Component_ID].push_front(Col);
9151  }
9152  }
9153  while(!InterConnectivity.empty())
9154  {
9155  int Symbol = this->InterConnectivity.front();
9156  this->InterConnectivity.pop_front();
9157  this->Connectivity[Component_ID].push_front(Symbol);
9158  }
9159 
9160  while(!InterGeometry.empty())
9161  {
9162  Point_Int Geo = InterGeometry.front();
9163  InterGeometry.pop_front();
9164  this->Geometry[Component_ID].push_front(Geo);
9165  }
9166 
9167  this->NumberSymbol[Component_ID].push_front(Number_symbol);
9168  this->NumberVertices[Component_ID].push_front(Number_vertices);
9169 
9170  this->DumpSymbolRegulation = Number_symbol;
9171 
9172 
9173  return Number_vertices;
9174 }
9175 
9176 
9177 // function imported from
9178 // Mepp1.github/src/mepp/Polyhedron/polyhedron_shared_items.h
9179 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9180 void
9182  compute_normals(const HalfedgeGraph &_pMesh, const PointMap *_pm)
9183 {
9184  compute_normals_per_facet(_pMesh, _pm);
9185  compute_normals_per_vertex(_pMesh);
9186 #if 0
9187  compute_normals_per_halfedge(); // ajout Céline
9188 #endif
9189 }
9190 
9191 
9192 // normals per facet
9193 // function imported from
9194 // Mepp1.github/src/mepp/Polyhedron/polyhedron_shared_items.h
9195 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9196 void
9198  compute_normals_per_facet(const HalfedgeGraph &_pMesh, const PointMap *_pm)
9199 {
9200  face_iterator fi_begin = faces(_pMesh).first;
9201  face_iterator fi_end = faces(_pMesh).second;
9202  for(face_iterator fi = fi_begin; fi != fi_end; ++fi)
9203  compute_facet_normal(*fi, _pMesh, _pm);
9204 }
9205 
9206 
9207 // normals per vertex
9208 // function imported from
9209 // Mepp1.github/src/mepp/Polyhedron/polyhedron_shared_items.h
9210 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9211 void
9213  compute_normals_per_vertex(const HalfedgeGraph &_pMesh)
9214 {
9215  vertex_iterator vi_begin = vertices(_pMesh).first;
9216  vertex_iterator vi_end = vertices(_pMesh).second;
9217  for(vertex_iterator vi = vi_begin; vi != vi_end; ++vi)
9218  compute_vertex_normal(*vi, _pMesh);
9219 }
9220 
9221 
9222 // function imported from
9223 // Mepp1.github/src/mepp/Polyhedron/polyhedron_shared_items.h
9224 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9225 void
9228  const HalfedgeGraph &_pMesh,
9229  const PointMap *_pm)
9230 {
9232 
9233  Vector sum = Vector(0.0, 0.0, 0.0);
9234 
9235  CGAL::Halfedge_around_face_circulator< HalfedgeGraph > facet_begin(
9236  halfedge(f, _pMesh), _pMesh);
9237  CGAL::Halfedge_around_face_circulator< HalfedgeGraph > h = facet_begin;
9238 
9239  do
9240  {
9241  Point3d p1 = get(*_pm, target(*h, _pMesh));
9242  Point3d p2 = get(*_pm, target(next(*h, _pMesh), _pMesh));
9243  Point3d p3 = get(*_pm, target(next(next(*h, _pMesh), _pMesh), _pMesh));
9244 
9245  Vector v1 =
9246  FEVV::Math::Vector::sub< FEVV::Geometry_traits< HalfedgeGraph > >(
9247  p2, p1, gt);
9248  Vector v2 =
9249  FEVV::Math::Vector::sub< FEVV::Geometry_traits< HalfedgeGraph > >(
9250  p3, p2, gt);
9251 
9254 
9255  double sqnorm = FEVV::Math::Vector::dot_product<
9256  FEVV::Geometry_traits< HalfedgeGraph > >(normal, normal, gt);
9257  if(sqnorm != 0)
9258  {
9261  normal, 1.0 / std::sqrt(sqnorm), gt);
9262  }
9263  sum = sum + normal;
9264  } while(++h != facet_begin);
9265 
9266  double sqnorm =
9267  FEVV::Math::Vector::dot_product< FEVV::Geometry_traits< HalfedgeGraph > >(
9268  sum, sum, gt);
9269  if(sqnorm != 0.0)
9270  {
9271  put(this->facet_normal,
9272  f,
9275  sum, 1.0 / std::sqrt(sqnorm), gt));
9276  }
9277  else
9278  {
9279  put(this->facet_normal, f, Vector(0.0, 0.0, 0.0));
9280  // TRACE("degenerate face\n");
9281  }
9282 };
9283 
9284 
9285 // function imported from
9286 // Mepp1.github/src/mepp/Polyhedron/polyhedron_shared_items.h
9287 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9288 void
9291  const HalfedgeGraph &_pMesh)
9292 {
9294 
9295  Vector normal = Vector(0.0, 0.0, 0.0);
9296 
9297  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > pHalfedge(v, _pMesh);
9298  CGAL::Halfedge_around_target_circulator< HalfedgeGraph > begin = pHalfedge;
9299 
9300  CGAL_For_all(pHalfedge, begin)
9301  {
9302  if(!CGAL::is_border_edge(*pHalfedge, _pMesh))
9303  {
9304  normal = normal + get(this->facet_normal, face(*pHalfedge, _pMesh));
9305  }
9306  }
9307 
9308  double sqnorm =
9309  FEVV::Math::Vector::dot_product< FEVV::Geometry_traits< HalfedgeGraph > >(
9310  normal, normal, gt);
9311  if(sqnorm != 0.0f)
9312  {
9313  put(this->vertex_normal,
9314  v,
9317  normal, 1.0 / std::sqrt(sqnorm), gt));
9318  }
9319  else
9320  {
9321  put(this->vertex_normal, v, Vector(0.0, 0.0, 0.0));
9322  }
9323 }
9324 
9325 
9326 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9327 int
9329  Estimate_Geometry_Quantization(double volume,
9330  double area,
9331  int number_vertices)
9332 {
9333  double C = (double)volume / (double)area / number_vertices;
9334 
9335  double a = -1.248;
9336  double b = -0.954;
9337 
9338  int Q = floor(a * log(C) + b + 0.5);
9339 
9340  return Q;
9341 }
9342 
9343 
9344 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9345 int
9347  Get_Correct_Vector(int i, int j, int k)
9348 {
9349  int Correct_symbol = -1;
9350 
9351  if((i == 0) && (j == 0) && (k == 0))
9352  Correct_symbol = 0;
9353 
9354  else if((i == 1) && (j == 0) && (k == 0))
9355  Correct_symbol = 1;
9356 
9357  else if((i == 0) && (j == 1) && (k == 0))
9358  Correct_symbol = 2;
9359 
9360  else if((i == 1) && (j == 1) && (k == 0))
9361  Correct_symbol = 3;
9362 
9363  else if((i == 0) && (j == 0) && (k == 1))
9364  Correct_symbol = 4;
9365 
9366  else if((i == 1) && (j == 0) && (k == 1))
9367  Correct_symbol = 5;
9368 
9369  else if((i == 0) && (j == 1) && (k == 1))
9370  Correct_symbol = 6;
9371  else
9372  Correct_symbol = 7;
9373 
9374  return Correct_symbol;
9375 }
9376 
9377 
9378 // ported from
9379 // Mepp1 Compression_Valence/src/Compression_Valence_Basemesh_builder.h
9380 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9381 void
9383  build_mesh(HalfedgeGraph &_pMesh,
9384  PointMap *_pm,
9385  VertexColorMap *_v_cm,
9386  const std::vector< Point3d > &vlist, // points list
9387  const std::vector< int > &flist, // faces list
9388  const std::vector< float > &clist, // vertex-color list
9389  const std::vector< int > &Color_index_list)
9390 {
9391  assert(vlist.size() != 0);
9392  assert(flist.size() != 0);
9393 
9394  typedef typename boost::property_traits< VertexColorMap >::value_type Color;
9395 
9396  // add vertices
9397 
9398  size_t Number_vertex = vlist.size();
9399  std::vector< vertex_descriptor > vertex_index_to_descriptor;
9400  vertex_index_to_descriptor.reserve(Number_vertex);
9401  for(size_t i = 0; i < Number_vertex; i++)
9402  {
9403  // create vertex
9404  vertex_descriptor v = add_vertex(_pMesh);
9405  vertex_index_to_descriptor.push_back(v);
9406 
9407  // set vertex geometry
9408  const Point3d &Pt = vlist[i];
9409  put(*_pm, v, Pt);
9410 
9411  // set vertex color
9412  if(!clist.empty())
9413  {
9414  Color tmp_color(clist[3 * i + 0], clist[3 * i + 1], clist[3 * i + 2]);
9415  put(*_v_cm, v, tmp_color);
9416  }
9417  if(!Color_index_list.empty())
9418  {
9419  // TODO-elo:
9420  // Vertex_Color_Index seems to be unused in the rest of the code ;
9421  // remove the Color_index_list parameter and this block when confirmed
9422  // not ported:
9423  // v->Vertex_Color_Index = (*Color_index_list)[i];
9424  throw std::runtime_error("Compression_Valence_Component::build_mesh(): "
9425  "Vertex Color Index not supported, fix it!");
9426  }
9427 
9428  init_vertex_attributes(v);
9429  }
9430 
9431  // add faces
9432 
9433  size_t Number_facet = flist.size() / 3;
9434 
9435  for(size_t i = 0; i < Number_facet; i++)
9436  {
9437  // ELO flist contains indices of face-vertices, 3 vertices per face
9438  std::vector< vertex_descriptor > face_vertices;
9439  face_vertices.push_back(vertex_index_to_descriptor[flist[3 * i + 0]]);
9440  face_vertices.push_back(vertex_index_to_descriptor[flist[3 * i + 1]]);
9441  face_vertices.push_back(vertex_index_to_descriptor[flist[3 * i + 2]]);
9442 
9443  face_descriptor currentFace = CGAL::Euler::add_face(face_vertices, _pMesh);
9444  if(currentFace == GraphTraits::null_face())
9445  {
9446  throw std::runtime_error("Compression_Valence_Component::build_mesh(): "
9447  "failed to create face!");
9448  }
9449  }
9450 }
9451 
9452 
9453 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9454 bool
9456  Remove_Edges(HalfedgeGraph &_pMesh,
9457  const halfedge_descriptor &h,
9458  const int &type)
9459 {
9460  bool check = false;
9461  halfedge_descriptor g = h;
9462 
9463  // triangle
9464 
9465  if((type == 1) || (type == 2) || (type == 4))
9466  {
9467  if(get(this->Vertex_Sign, target(next(g, _pMesh), _pMesh)) == NOSIGN)
9468  put(this->Vertex_Sign, target(next(g, _pMesh), _pMesh), PLUS);
9469  }
9470 
9471  else if(type == 3)
9472  {
9473  if(get(this->Vertex_Sign, target(next(g, _pMesh), _pMesh)) == NOSIGN)
9474  put(this->Vertex_Sign, target(next(g, _pMesh), _pMesh), MINUS);
9475  }
9476 
9477 
9478  // quadrangle
9479  else if((type == 5) || (type == 8))
9480  {
9481  // verification
9482  if(get(this->Facet_Flag, face(opposite(prev(g, _pMesh), _pMesh), _pMesh)) !=
9483  FREE)
9484  check = true;
9485  if(check == false)
9486  {
9487  g = prev(g, _pMesh);
9488  CGAL::Euler::join_face(g, _pMesh);
9489 
9490  g = h;
9491  if(get(this->Vertex_Sign, target(next(g, _pMesh), _pMesh)) == NOSIGN)
9492  put(this->Vertex_Sign, target(next(g, _pMesh), _pMesh), PLUS);
9493  if(get(this->Vertex_Sign,
9494  target(next(next(g, _pMesh), _pMesh), _pMesh)) == NOSIGN)
9495  put(this->Vertex_Sign,
9496  target(next(next(g, _pMesh), _pMesh), _pMesh),
9497  MINUS);
9498  }
9499  }
9500 
9501  else if((type == 6) || (type == 7))
9502  {
9503  // verification
9504  if(get(this->Facet_Flag, face(opposite(next(g, _pMesh), _pMesh), _pMesh)) !=
9505  FREE)
9506  check = true;
9507  if(check == false)
9508  {
9509  g = next(g, _pMesh);
9510  CGAL::Euler::join_face(g, _pMesh);
9511 
9512  g = h;
9513  if(get(this->Vertex_Sign, target(next(g, _pMesh), _pMesh)) == NOSIGN)
9514  put(this->Vertex_Sign, target(next(g, _pMesh), _pMesh), MINUS);
9515  if(get(this->Vertex_Sign,
9516  target(next(next(g, _pMesh), _pMesh), _pMesh)) == NOSIGN)
9517  put(this->Vertex_Sign,
9518  target(next(next(g, _pMesh), _pMesh), _pMesh),
9519  PLUS);
9520  }
9521  }
9522 
9523  // pentagone
9524  else if((type == 9) || (type == 12))
9525  {
9526  g = opposite(prev(g, _pMesh), _pMesh);
9527  if(get(this->Facet_Flag, face(g, _pMesh)) != FREE)
9528  check = true;
9529  g = opposite(next(g, _pMesh), _pMesh);
9530  if(get(this->Facet_Flag, face(g, _pMesh)) != FREE)
9531  check = true;
9532 
9533  if(check == false)
9534  {
9535  g = prev(h, _pMesh);
9536  g = CGAL::Euler::join_face(g, _pMesh);
9537  g = next(g, _pMesh);
9538  g = CGAL::Euler::join_face(g, _pMesh);
9539 
9540  g = h;
9541  if(get(this->Vertex_Sign, target(next(g, _pMesh), _pMesh)) == NOSIGN)
9542  put(this->Vertex_Sign, target(next(g, _pMesh), _pMesh), PLUS);
9543  if(get(this->Vertex_Sign,
9544  target(next(next(g, _pMesh), _pMesh), _pMesh)) == NOSIGN)
9545  put(this->Vertex_Sign,
9546  target(next(next(g, _pMesh), _pMesh), _pMesh),
9547  MINUS);
9548  if(get(this->Vertex_Sign,
9549  target(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh)) ==
9550  NOSIGN)
9551  put(this->Vertex_Sign,
9552  target(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh),
9553  PLUS);
9554  }
9555  }
9556 
9557  else if(type == 10)
9558  {
9559  g = opposite(next(g, _pMesh), _pMesh);
9560  if(get(this->Facet_Flag, face(g, _pMesh)) != FREE)
9561  check = true;
9562 
9563  g = opposite(prev(g, _pMesh), _pMesh);
9564  if(get(this->Facet_Flag, face(g, _pMesh)) != FREE)
9565  check = true;
9566 
9567  if(check == false)
9568  {
9569  g = opposite(next(h, _pMesh), _pMesh);
9570  g = CGAL::Euler::join_face(g, _pMesh);
9571  g = CGAL::Euler::join_face(g, _pMesh);
9572 
9573 
9574  g = h;
9575  if(get(this->Vertex_Sign, target(next(g, _pMesh), _pMesh)) == NOSIGN)
9576  put(this->Vertex_Sign, target(next(g, _pMesh), _pMesh), PLUS);
9577  if(get(this->Vertex_Sign,
9578  target(next(next(g, _pMesh), _pMesh), _pMesh)) == NOSIGN)
9579  put(this->Vertex_Sign,
9580  target(next(next(g, _pMesh), _pMesh), _pMesh),
9581  MINUS);
9582  if(get(this->Vertex_Sign,
9583  target(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh)) ==
9584  NOSIGN)
9585  put(this->Vertex_Sign,
9586  target(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh),
9587  PLUS);
9588  }
9589  }
9590 
9591  else if(type == 11)
9592  {
9593  if(get(this->Facet_Flag, face(opposite(next(g, _pMesh), _pMesh), _pMesh)) !=
9594  FREE)
9595  check = true;
9596  if(get(this->Facet_Flag, face(opposite(prev(g, _pMesh), _pMesh), _pMesh)) !=
9597  FREE)
9598  check = true;
9599 
9600  if(check == false)
9601  {
9602  g = next(g, _pMesh);
9603  g = CGAL::Euler::join_face(g, _pMesh);
9604  g = prev(g, _pMesh);
9605  g = CGAL::Euler::join_face(g, _pMesh);
9606 
9607  g = h;
9608 
9609  if(get(this->Vertex_Sign, target(next(g, _pMesh), _pMesh)) == NOSIGN)
9610  put(this->Vertex_Sign, target(next(g, _pMesh), _pMesh), MINUS);
9611  if(get(this->Vertex_Sign,
9612  target(next(next(g, _pMesh), _pMesh), _pMesh)) == NOSIGN)
9613  put(this->Vertex_Sign,
9614  target(next(next(g, _pMesh), _pMesh), _pMesh),
9615  PLUS);
9616  if(get(this->Vertex_Sign,
9617  target(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh)) ==
9618  NOSIGN)
9619  put(this->Vertex_Sign,
9620  target(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh),
9621  MINUS);
9622  }
9623  }
9624 
9625  else if((type == 13) || (type == 16))
9626  {
9627  g = opposite(prev(g, _pMesh), _pMesh);
9628  if(get(this->Facet_Flag, face(g, _pMesh)) != FREE)
9629  check = true;
9630  if(get(this->Facet_Flag, face(opposite(next(g, _pMesh), _pMesh), _pMesh)) !=
9631  FREE)
9632  check = true;
9633  if(get(this->Facet_Flag, face(opposite(prev(g, _pMesh), _pMesh), _pMesh)) !=
9634  FREE)
9635  check = true;
9636 
9637  if(check == false)
9638  {
9639  g = opposite(prev(h, _pMesh), _pMesh);
9640  g = CGAL::Euler::join_face(g, _pMesh);
9641  g = CGAL::Euler::join_face(g, _pMesh);
9642  g = CGAL::Euler::join_face(g, _pMesh);
9643 
9644  g = h;
9645  if(get(this->Vertex_Sign, target(next(g, _pMesh), _pMesh)) == NOSIGN)
9646  put(this->Vertex_Sign, target(next(g, _pMesh), _pMesh), PLUS);
9647  if(get(this->Vertex_Sign,
9648  target(next(next(g, _pMesh), _pMesh), _pMesh)) == NOSIGN)
9649  put(this->Vertex_Sign,
9650  target(next(next(g, _pMesh), _pMesh), _pMesh),
9651  MINUS);
9652  if(get(this->Vertex_Sign,
9653  target(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh)) ==
9654  NOSIGN)
9655  put(this->Vertex_Sign,
9656  target(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh),
9657  PLUS);
9658  if(get(this->Vertex_Sign,
9659  target(next(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh),
9660  _pMesh)) == NOSIGN)
9661  put(this->Vertex_Sign,
9662  target(next(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh),
9663  _pMesh),
9664  MINUS);
9665  }
9666  }
9667 
9668  else if((type == 14) || (type == 15))
9669  {
9670  g = opposite(next(g, _pMesh), _pMesh);
9671  if(get(this->Facet_Flag, face(g, _pMesh)) != FREE)
9672  check = true;
9673  if(get(this->Facet_Flag, face(opposite(next(g, _pMesh), _pMesh), _pMesh)) !=
9674  FREE)
9675  check = true;
9676  if(get(this->Facet_Flag, face(opposite(prev(g, _pMesh), _pMesh), _pMesh)) !=
9677  FREE)
9678  check = true;
9679 
9680  if(check == false)
9681  {
9682  g = opposite(next(h, _pMesh), _pMesh);
9683  g = CGAL::Euler::join_face(g, _pMesh);
9684  g = CGAL::Euler::join_face(g, _pMesh);
9685  g = CGAL::Euler::join_face(g, _pMesh);
9686 
9687  g = h;
9688  if(get(this->Vertex_Sign, target(next(g, _pMesh), _pMesh)) == NOSIGN)
9689  put(this->Vertex_Sign, target(next(g, _pMesh), _pMesh), MINUS);
9690  if(get(this->Vertex_Sign,
9691  target(next(next(g, _pMesh), _pMesh), _pMesh)) == NOSIGN)
9692  put(this->Vertex_Sign,
9693  target(next(next(g, _pMesh), _pMesh), _pMesh),
9694  PLUS);
9695  if(get(this->Vertex_Sign,
9696  target(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh)) ==
9697  NOSIGN)
9698  put(this->Vertex_Sign,
9699  target(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh),
9700  MINUS);
9701  if(get(this->Vertex_Sign,
9702  target(next(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh),
9703  _pMesh)) == NOSIGN)
9704  put(this->Vertex_Sign,
9705  target(next(next(next(next(g, _pMesh), _pMesh), _pMesh), _pMesh),
9706  _pMesh),
9707  PLUS);
9708  }
9709  }
9710 
9711  return check;
9712 }
9713 
9714 
9715 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9716 void
9718  Get_Coefficient_Up_Quantization(const int &Correct_symbol, int coeff[3])
9719 {
9720  if(Correct_symbol == 0)
9721  {
9722  coeff[0] = -1;
9723  coeff[1] = -1;
9724  coeff[2] = -1;
9725  }
9726  else if(Correct_symbol == 1)
9727  {
9728  coeff[0] = 1;
9729  coeff[1] = -1;
9730  coeff[2] = -1;
9731  }
9732  else if(Correct_symbol == 2)
9733  {
9734  coeff[0] = -1;
9735  coeff[1] = 1;
9736  coeff[2] = -1;
9737  }
9738  else if(Correct_symbol == 3)
9739  {
9740  coeff[0] = 1;
9741  coeff[1] = 1;
9742  coeff[2] = -1;
9743  }
9744  else if(Correct_symbol == 4)
9745  {
9746  coeff[0] = -1;
9747  coeff[1] = -1;
9748  coeff[2] = 1;
9749  }
9750  else if(Correct_symbol == 5)
9751  {
9752  coeff[0] = 1;
9753  coeff[1] = -1;
9754  coeff[2] = 1;
9755  }
9756  else if(Correct_symbol == 6)
9757  {
9758  coeff[0] = -1;
9759  coeff[1] = 1;
9760  coeff[2] = 1;
9761  }
9762  else if(Correct_symbol == 7)
9763  {
9764  coeff[0] = 1;
9765  coeff[1] = 1;
9766  coeff[2] = 1;
9767  }
9768 }
9769 
9770 
9771 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9772 void
9775 {
9776  // ELO-note:
9777  // some vertex attribute must be initialized,
9778  // see
9779  // Mepp1.github/src/components/Compression/Compression_Valence/src/Compression_Valence_Items.h:87
9780  // Seed_Edge = -1;
9781  // Region_Number = -1;
9782  // Removal_Order = -1;
9783  // Valid_Vertex = true;
9784  // JCW_Move_Error[0] = 0;
9785  // JCW_Move_Error[1] = 0;
9786  // JCW_Move_Error[2] = 0;
9787  // only the 3 first are used for now
9788  put(this->vertex_Seed_Edge, v, -1);
9789  put(this->vertex_Region_Number, v, -1);
9790  put(this->vertex_Removal_Order, v, -1);
9791 }
9792 
9793 
9794 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9795 void
9797  truncate_colors(const HalfedgeGraph &_pMesh, VertexColorMap *_v_cm)
9798 {
9799  typedef typename boost::property_traits< VertexColorMap >::value_type Color;
9800 
9801  // loop over vertices
9802  vertex_iterator vi_begin = vertices(_pMesh).first;
9803  vertex_iterator vi_end = vertices(_pMesh).second;
9804  for(vertex_iterator vi = vi_begin; vi != vi_end; ++vi)
9805  {
9806  Color c = get(*_v_cm, *vi);
9807 
9808  if( c[0] <= 1 && c[1] <= 1 && c[2] <= 1 )
9809  continue; // no need to truncate
9810 
9811  // truncate to 1
9812  double c0 = std::min(1.0/*double*/, static_cast<double>(c[0]));
9813  double c1 = std::min(1.0/*double*/, static_cast<double>(c[1]));
9814  double c2 = std::min(1.0/*double*/, static_cast<double>(c[2]));
9815 
9816  put(*_v_cm, *vi, Color(c0, c1, c2));
9817  //DBG put(*_v_cm, *vi, Color(0, 0, 0));
9818  }
9819 }
9820 
9821 
9822 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9823 void
9825  DBG_print_mesh_geometry(const HalfedgeGraph &_pMesh,
9826  const PointMap *_pm,
9827  const std::string &header)
9828 {
9829  std::cout << header << " mesh-geometry:" << std::endl;
9830 
9831  size_t count = 0;
9832  auto vertex_iterator_pair = vertices(_pMesh);
9833  vertex_iterator pVertex = vertex_iterator_pair.first;
9834  vertex_iterator pVertex_end = vertex_iterator_pair.second;
9835  for(; pVertex != pVertex_end; ++pVertex)
9836  {
9837  count++;
9838  auto p3d = get(*_pm, *pVertex);
9839  std::cout << "V#" << count << " point: " << p3d[0] << " " << p3d[1] << " "
9840  << p3d[2] << std::endl;
9841  }
9842 }
9843 
9844 template< typename HalfedgeGraph, typename PointMap, typename VertexColorMap >
9845 void
9847  DBG_print_mesh_vertexcolor(const HalfedgeGraph &_pMesh,
9848  const VertexColorMap *_v_cm,
9849  const std::string &header)
9850 {
9851  typedef typename boost::property_traits< VertexColorMap >::value_type Color;
9852 
9853  std::cout << header << " mesh-vertexcolor:" << std::endl;
9854 
9855  if(!_v_cm)
9856  {
9857  std::cout << header << "THE MESH HAS NO VERTEX COLOR MAP!" << std::endl;
9858  return;
9859  }
9860 
9861  size_t count = 0;
9862  auto vertex_iterator_pair = vertices(_pMesh);
9863  vertex_iterator pVertex = vertex_iterator_pair.first;
9864  vertex_iterator pVertex_end = vertex_iterator_pair.second;
9865  for(; pVertex != pVertex_end; ++pVertex)
9866  {
9867  count++;
9868  Color c = get(*_v_cm, *pVertex);
9869  std::cout << "V#" << count << " color: " << c[0] << " " << c[1] << " "
9870  << c[2] << std::endl;
9871  }
9872 }
9873 
9874 
9875 #if defined _MSC_VER
9876 #pragma warning(pop)
9877 #endif
fixed_CGAL_Euler_add_vertex_and_face_to_border
boost::graph_traits< Graph >::halfedge_descriptor fixed_CGAL_Euler_add_vertex_and_face_to_border(typename boost::graph_traits< Graph >::halfedge_descriptor h1, typename boost::graph_traits< Graph >::halfedge_descriptor h2, Graph &g)
Definition: Compression_Valence_Common.h:240
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
Compression_Valence_Component
Compression valence component.
Definition: Compression_Valence_Component.h:211
Compression_Valence_Component::Volume
double Volume(const Point3d &A, const Point3d &B, const Point3d &C, const Point3d &D, const HalfedgeGraph &_pMesh)
Definition: Compression_Valence_Component.inl:7618
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
Color_Unit
Struct of integer color components.
Definition: Compression_Valence_Component.h:119
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
PLUS
const int PLUS
The plus tag for retriangulation.
Definition: Compression_Valence_Common.h:39
Compression_Valence_Component::Calculate_Geometry_Color_Offset_Range
void Calculate_Geometry_Color_Offset_Range(void)
Calculates the geometry color offset range. This function is needed since the coder/decoder deals onl...
Definition: Compression_Valence_Component.inl:3649
Arithmetic_Codec::encode
void encode(unsigned bit, Static_Bit_Model &)
Definition: arithmetic_codec.inl:243
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
Compression_Valence_Component::Barycenter_Patch_Before_Removal
Point3d Barycenter_Patch_Before_Removal(const halfedge_descriptor &h, const HalfedgeGraph &_pMesh, const PointMap *_pm)
gives the position of the barycenter of the patch for regulation conquest.
Definition: Compression_Valence_Component.inl:7756
Compression_Valence_Component::Get_Vertex_Color
Color_Unit Get_Vertex_Color(const halfedge_descriptor &h, const HalfedgeGraph &_pMesh)
gets a color of front vertex of h.
Definition: Compression_Valence_Component.inl:7663
Vector
AIFMesh::Vector Vector
Definition: Graph_properties_aif.h:22
Compression_Valence_Component::Is_Geometric_Metric_Violated
bool Is_Geometric_Metric_Violated(const HalfedgeGraph &_pMesh, const PointMap *_pm, const halfedge_descriptor &h, const int &type, const unsigned int &valence, const float &Threshold)
Query if this object is geometric violated. Here, we define a geometric_metric to preserve maximum th...
Definition: Compression_Valence_Component.inl:7268
Compression_Valence_Component::Decompress_Each_Step
int Decompress_Each_Step(HalfedgeGraph &_pMesh, PointMap *_pm, VertexColorMap *_v_cm)
Decompress the each step to visualize intermediate meshes.
Definition: Compression_Valence_Component.inl:5921
FEVV::Math::Vector::l2_distance
static double l2_distance(const ElementType v1[DIM], const ElementType v2[DIM])
Compute ||v1 - v2||_L2 norm (distance between v1 and v2)
Definition: MatrixOperations.hpp:588
Compression_Valence_Component::halfedge_descriptor
GraphTraits::halfedge_descriptor halfedge_descriptor
Definition: Compression_Valence_Component.h:218
Compression_Valence_Component::Frenet_Rotation
Point_Int Frenet_Rotation(const Point_Int &Dist, const Vector &T1, const Vector &T2, const Vector &normal)
finds a bijection through a rotation transformation in 3D with only integer coordinates.
Definition: Compression_Valence_Component.inl:8481
Compression_Valence_Component::vertex_to_string
std::string vertex_to_string(const vertex_descriptor &v, const PointMap *_pm)
Definition: Compression_Valence_Component.inl:1263
Compression_Valence_Component::Normal_Patch
Vector Normal_Patch(const halfedge_descriptor &const_h, const unsigned int &valence, const HalfedgeGraph &_pMesh, const PointMap *_pm)
calculates a normal vector of a patch caused by a removal of a front vertex.
Definition: Compression_Valence_Component.inl:8226
Compression_Valence_Component::Adaptive_Quantization
void Adaptive_Quantization(HalfedgeGraph &pMesh, PointMap *_pm, VertexColorMap *_v_cm, const int &NVertices, const bool Is_normal_flipping_selected, const bool Is_use_metric_selected, const float &Metric_thread, const bool Is_use_forget_metric_selected, const int &Forget_value, const int &Qbit)
Adaptive quantization which not only decimates a input mesh but also adapts quantization precision fo...
Definition: Compression_Valence_Component.inl:875
Compression_Valence_Component::build_mesh
void build_mesh(HalfedgeGraph &_pMesh, PointMap *_pm, VertexColorMap *_v_cm, const std::vector< Point3d > &vlist, const std::vector< int > &flist, const std::vector< float > &clist, const std::vector< int > &Color_index_list)
Definition: Compression_Valence_Component.inl:9383
Compression_Valence_Component::Point3d
FEVV::Geometry_traits< HalfedgeGraph >::Point Point3d
Definition: Compression_Valence_Component.h:221
Compression_Valence_Component::Is_Border_Vertex
bool Is_Border_Vertex(const halfedge_descriptor &h, const HalfedgeGraph &mesh)
Query if 'h' is border vertex.
Definition: Compression_Valence_Component.inl:6731
Compression_Valence_Component::Remove_Last_Phase_Elements
void Remove_Last_Phase_Elements(const int &Component_ID)
When the last simplification operation has to be cancelled, we need to remove its elements in order n...
Definition: Compression_Valence_Component.inl:3520
Compression_Valence_Component::DBG_print_mesh_vertexcolor
void DBG_print_mesh_vertexcolor(const HalfedgeGraph &_pMesh, const VertexColorMap *_v_cm, const std::string &header=std::string())
Definition: Compression_Valence_Component.inl:9847
NOSIGN
const int NOSIGN
The nosign tag for retriangulation.
Definition: Compression_Valence_Common.h:41
Compression_Valence_Component::Diminush_Geometry_Quantization_Precision
void Diminush_Geometry_Quantization_Precision(HalfedgeGraph &pMesh, const int &Component_ID, PointMap *_pm)
Decreasing of quantization resolution based on the prediction of PENG. Opposite function is Augment_G...
Definition: Compression_Valence_Component.inl:5152
LAB_To_RGB
void LAB_To_RGB(float L, float A, float B, float *rgb)
Lab to rgb.
Definition: Compression_Valence_Common.h:141
Compression_Valence_Component::Estimate_Geometry_Quantization
int Estimate_Geometry_Quantization(double volume, double area, int number_vertices)
Estimate geometry quantization.
Definition: Compression_Valence_Component.inl:9329
Vertex_iterator
EnrichedPolyhedron::Vertex_iterator Vertex_iterator
Definition: boolops_polyhedra.hpp:41
Compression_Valence_Component::Quantization
void Quantization(HalfedgeGraph &pMesh, const PointMap *pm)
Definition: Compression_Valence_Component.inl:568
Compression_Valence_Component::edge_to_string
std::string edge_to_string(const halfedge_descriptor &h, const HalfedgeGraph &_pMesh, const PointMap *_pm)
Definition: Compression_Valence_Component.inl:1315
F
double F(double input)
Definition: rgb_to_lab.h:14
Compression_Valence_Component::Augment_Geometry_Quantization_Precision
void Augment_Geometry_Quantization_Precision(HalfedgeGraph &pMesh, Arithmetic_Codec &Decoder, const int &Component_ID, PointMap *_pm)
Refines quantization precision of mesh geometry.
Definition: Compression_Valence_Component.inl:4869
OTHER_COORDINATE
const int OTHER_COORDINATE
The other coordinate tag for seed gate.
Definition: Compression_Valence_Common.h:45
Compression_Valence_Component::Calculate_Edge_Color_Difference
void Calculate_Edge_Color_Difference(HalfedgeGraph &pMesh, const int &Component_ID, double &Max_color, double &Mean_color, int &Number_of_vertices)
Calculates the edge color difference.
Definition: Compression_Valence_Component.inl:4305
FEVV::DataStructures::AIF::opposite
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor opposite(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor h, const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns the halfedge with source and target swapped.
Definition: Graph_traits_aif.h:625
FEVV::Geometry_traits
Refer to Geometry_traits_documentation_dummy for further documentation on provided types and algorith...
Definition: Geometry_traits.h:162
TEMP_FLAG
const int TEMP_FLAG
Definition: Compression_Valence_Common.h:37
Point
AIFMesh::Point Point
Definition: Graph_properties_aif.h:21
Point_Int::x
int x
The x coordinate.
Definition: Compression_Valence_Component.h:34
Compression_Valence_Component::Color_Initialization
void Color_Initialization(HalfedgeGraph &pMesh, VertexColorMap *v_cm)
Color initialization.
Definition: Compression_Valence_Component.inl:672
Compression_Valence_Component::Un_Regulation
void Un_Regulation(HalfedgeGraph &_pMesh, Arithmetic_Codec &Decoder, const int &Component_ID, PointMap *_pm, VertexColorMap *_v_cm)
Decoding of the regulation conquest.
Definition: Compression_Valence_Component.inl:2283
Compression_Valence_Component::keep_intermediate_mesh
void keep_intermediate_mesh(const HalfedgeGraph &_pMesh, const VertexColorMap *_v_cm, std::vector< HalfedgeGraph * > *intermediate_meshes, std::vector< VertexColorMap * > *intermediate_vertexColorMaps)
Store a copy of the current mesh and vertex color map to be able to display all levels of decompressi...
Definition: Compression_Valence_Component.inl:6552
Compression_Valence_Component::Global_Initialization
void Global_Initialization(HalfedgeGraph &pMesh, const int &Quantization_bit, const char *File_name, const PointMap *pm, VertexColorMap *v_cm)
Global initialization to select the input gate.
Definition: Compression_Valence_Component.inl:224
Compression_Valence_Component::compute_normals
void compute_normals(const HalfedgeGraph &_pMesh, const PointMap *_pm)
Definition: Compression_Valence_Component.inl:9182
Compression_Valence_Component::Get_Coefficient_Up_Quantization
void Get_Coefficient_Up_Quantization(const int &Correct_symbol, int coeff[3])
Gets a coefficient up quantization.
Definition: Compression_Valence_Component.inl:9718
Compression_Valence_Component::Init
void Init(HalfedgeGraph &mesh)
Initialize all flags of verticeces and facets to FREE and give order to vertices (manifold property c...
Definition: Compression_Valence_Component.inl:1190
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::Operators::print_halfedge
void print_halfedge(const typename boost::graph_traits< HalfedgeGraph >::halfedge_descriptor &h, PointMap pm, const HalfedgeGraph &g)
Print the source and the target coordinates of one halfedge.
Definition: print_halfedge.hpp:29
FREE
const int FREE
Definition: Compression_Valence_Common.h:34
Color_Unit::c0
int c0
Definition: Compression_Valence_Component.h:120
Compression_Valence_Component::Multiple_Components_Initialization
void Multiple_Components_Initialization(HalfedgeGraph &pMesh, const PointMap *pm, const int &Quantization_bit)
Definition: Compression_Valence_Component.inl:252
FEVV::PMapsContainer
std::map< std::string, boost::any > PMapsContainer
Definition: properties.h:99
Signe
static int Signe(const double &x)
Definition: Compression_Valence_Component.inl:8465
Compression_Valence_Component::Calculate_T1_T2
Vector Calculate_T1_T2(const halfedge_descriptor &h, const Vector &normal, Vector &T2, const HalfedgeGraph &_pMesh, const PointMap *_pm)
Calculates the base vectors of new coordinates system which is frenet system.
Definition: Compression_Valence_Component.inl:8394
Compression_Valence_Component::vertex_iterator
GraphTraits::vertex_iterator vertex_iterator
Definition: Compression_Valence_Component.h:215
C2_QUANTIZATION
const int C2_QUANTIZATION
Definition: Compression_Valence_Common.h:32
FEVV::Math::Vector::cross_product
static std::vector< ElementType > cross_product(const ElementType v1[DIM], const ElementType v2[DIM])
Definition: MatrixOperations.hpp:460
Compression_Valence_Component::compute_vertex_normal
void compute_vertex_normal(const vertex_descriptor &v, const HalfedgeGraph &_pMesh)
Definition: Compression_Valence_Component.inl:9290
Compression_Valence_Component.h
Compression_Valence_Component::face_descriptor
GraphTraits::face_descriptor face_descriptor
Definition: Compression_Valence_Component.h:216
C1_QUANTIZATION
const int C1_QUANTIZATION
Definition: Compression_Valence_Common.h:31
Compression_Valence_Component::init_vertex_attributes
void init_vertex_attributes(const vertex_descriptor &v)
Definition: Compression_Valence_Component.inl:9774
Compression_Valence_Component::Write_Base_Mesh
void Write_Base_Mesh(const HalfedgeGraph &pMesh, Arithmetic_Codec &Enc, unsigned &Connectivity_size, unsigned &Color_size, const int &Num_color_base_mesh, const PointMap *_pm)
Writes a base mesh.
Definition: Compression_Valence_Component.inl:3543
Compression_Valence_Component::Un_Decimation_Conquest
void Un_Decimation_Conquest(HalfedgeGraph &pMesh, Arithmetic_Codec &Decoder, const int &Component_ID, PointMap *_pm, VertexColorMap *_v_cm)
Decoding of the decimation conquest.
Definition: Compression_Valence_Component.inl:2600
Adaptive_Data_Model::set_alphabet
void set_alphabet(unsigned number_of_symbols)
Definition: arithmetic_codec.inl:935
Compression_Valence_Component::Recalculate_Component_Area
void Recalculate_Component_Area(HalfedgeGraph &pMesh, const PointMap *_pm, const int &Component_ID, int &Number_facets)
Update the area of each component.
Definition: Compression_Valence_Component.inl:4839
Adaptive_Data_Model
Adaptive data model.
Definition: arithmetic_codec.hpp:120
FEVV::DataStructures::AIF::faces
std::pair< typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::face_iterator, typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::face_iterator > faces(const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns an iterator range over all faces of the mesh.
Definition: Graph_traits_aif.h:679
FEVV::Filters::is_triangle_mesh
bool is_triangle_mesh(const FaceGraph &g)
Function determining if mesh g is a pure triangular mesh.
Definition: is_triangle_mesh.hpp:29
Compression_Valence_Component::write_intermediate_mesh
void write_intermediate_mesh(HalfedgeGraph &_pMesh, const VertexColorMap *_v_cm)
Write intermediate mesh to file.
Definition: Compression_Valence_Component.inl:6501
FEVV::Operators::Geometry::triangle_area
double triangle_area(const typename GeometryTraits::Point &a, const typename GeometryTraits::Point &b, const typename GeometryTraits::Point &c, const GeometryTraits &gt)
Compute the area of a triangle (given by 3 points).
Definition: triangles.hpp:106
Compression_Valence_Component::face_iterator
GraphTraits::face_iterator face_iterator
Definition: Compression_Valence_Component.h:217
Compression_Valence_Component::vertex_descriptor
GraphTraits::vertex_descriptor vertex_descriptor
Definition: Compression_Valence_Component.h:214
Arithmetic_Codec::decode
unsigned decode(Static_Bit_Model &)
Definition: arithmetic_codec.inl:271
Compression_Valence_Component::Regulation
int Regulation(HalfedgeGraph &_pMesh, const bool Normal_flipping, const bool Use_metric, const float &Metric_thread, const bool Use_forget_metric, const int &Forget_value, const int &Component_ID, const PointMap *_pm)
Removal of a set of independent vertices.
Definition: Compression_Valence_Component.inl:8890
Compression_Valence_Component::compute_normals_per_vertex
void compute_normals_per_vertex(const HalfedgeGraph &_pMesh)
Definition: Compression_Valence_Component.inl:9213
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
CONQUERED
const int CONQUERED
Definition: Compression_Valence_Common.h:35
PI
const double PI
Definition: Compression_Valence_Common.h:51
Compression_Valence_Component::Barycenter_Patch_After_Removal
Point3d Barycenter_Patch_After_Removal(const halfedge_descriptor &h, const int &valence, const HalfedgeGraph &_pMesh, const PointMap *_pm)
gives the position of the barycenter of the patch for decimation conquest.
Definition: Compression_Valence_Component.inl:7790
FEVV::vertex_color
@ vertex_color
Definition: properties.h:47
Compression_Valence_Component::v_inf_to_v
bool v_inf_to_v(const vertex_descriptor &v1, const vertex_descriptor &v2, const PointMap *_pm)
Definition: Compression_Valence_Component.inl:1295
FEVV::Math::Vector::scalar_mult
static std::vector< ElementType > scalar_mult(const std::vector< ElementType > &v1, ElementType coef)
Compute v1 * coef.
Definition: MatrixOperations.hpp:714
Compression_Valence_Component::Error_Projected_Surface
bool Error_Projected_Surface(const HalfedgeGraph &_pMesh, const PointMap *_pm, const halfedge_descriptor &_h, const int &_Component_ID, const double &Mean_color, const double &Mean_area)
Calculate an error cause by a vertex removal and decide in order not to remove an important vertex.
Definition: Compression_Valence_Component.inl:6312
Point_Int::z
int z
The z coordinate.
Definition: Compression_Valence_Component.h:36
Compression_Valence_Component::Inverse_Frenet_Rotation
Point_Int Inverse_Frenet_Rotation(const Point_Int &Frenet, const Vector &T1, const Vector &T2, const Vector &normal)
Inverse operation of frenet rotation. This permits to refind the original coordinates.
Definition: Compression_Valence_Component.inl:8644
Compression_Valence_Component::Retriangulation
void Retriangulation(HalfedgeGraph &pMesh, const halfedge_descriptor &ch, const unsigned &valence, const unsigned &Vertex_number, const int &Component_ID, const PointMap *_pm)
Retriangulates the hole left by a removal of a vertex.
Definition: Compression_Valence_Component.inl:7820
Compression_Valence_Component::halfedge_to_string
std::string halfedge_to_string(const halfedge_descriptor &h, const HalfedgeGraph &_pMesh, const PointMap *_pm)
Definition: Compression_Valence_Component.inl:1277
Compression_Valence_Component::GraphTraits
boost::graph_traits< HalfedgeGraph > GraphTraits
Definition: Compression_Valence_Component.h:213
Arithmetic_Codec::start_encoder
void start_encoder(void)
Definition: arithmetic_codec.inl:636
Arithmetic_Codec::get_bits
unsigned get_bits(unsigned number_of_bits)
Definition: arithmetic_codec.inl:221
Compression_Valence_Common.h
Compression_Valence_Component::Augment_Color_Quantization_Precision
void Augment_Color_Quantization_Precision(HalfedgeGraph &_pMesh, Arithmetic_Codec &Decoder, const int &Component_ID, VertexColorMap *_v_cm)
Refine quantization precision of mesh color coordinates.
Definition: Compression_Valence_Component.inl:6021
triangles.hpp
Point_Int
Point.
Definition: Compression_Valence_Component.h:32
Compression_Valence_Component::Compression
void Compression(HalfedgeGraph &pMesh, const char *File_Name, const int &Qbit, unsigned &Connectivity_size, unsigned &Color_size, unsigned &Total_size, const PointMap *_pm)
Compressions.
Definition: Compression_Valence_Component.inl:3903
FEVV::DataStructures::AIF::AIFVector
Definition: AIFProperties.h:173
FEVV::Operators::Geometry::acos
T acos(T cosine)
Safe call to the std::acos function.
Definition: AngleOperations.hpp:64
Compression_Valence_Component::DBG_print_mesh_geometry
void DBG_print_mesh_geometry(const HalfedgeGraph &_pMesh, const PointMap *_pm, const std::string &header=std::string())
Definition: Compression_Valence_Component.inl:9825
LIMIT_NUMBER
const int LIMIT_NUMBER
Definition: Compression_Valence_Component.inl:48
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
Arithmetic_Codec::put_bits
void put_bits(unsigned data, unsigned number_of_bits)
Definition: arithmetic_codec.inl:197
MINUS
@ MINUS
Definition: boolops_definitions.hpp:55
MINIMUM_PREDICTION_NUMBER
const int MINIMUM_PREDICTION_NUMBER
Definition: Compression_Valence_Component.inl:47
FEVV::size_of_faces
boost::graph_traits< MeshT >::faces_size_type size_of_faces(const MeshT &g)
Real current number of faces of the mesh. Generic version.
Definition: Graph_traits_extension.h:80
Compression_Valence_Component::Remove_Edges
bool Remove_Edges(HalfedgeGraph &_pMesh, const halfedge_descriptor &h, const int &type)
Remove edges to create a hole.
Definition: Compression_Valence_Component.inl:9456
Compression_Valence_Component::Get_Average_Vertex_Color_After_Removal
Color_Unit Get_Average_Vertex_Color_After_Removal(const halfedge_descriptor &h, const int &valence, const HalfedgeGraph &_pMesh)
Gets an average color of neighboring vertices ( After removal of front vertex of h)
Definition: Compression_Valence_Component.inl:8857
FEVV::DataStructures::AIF::prev
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor prev(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor h, const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns the previous halfedge around its face.
Definition: Graph_traits_aif.h:612
FEVV::Filters::write_mesh
void write_mesh(const std::string &filename, FEVV::CGALPointSet &g, PMapsContainer &pmaps)
Write mesh to file.
Definition: cgal_point_set_writer.hpp:42
generic_writer.hpp
Compression_Valence_Component::Triangle_Normal
Vector Triangle_Normal(const HalfedgeGraph &_pMesh, const PointMap *_pm, const halfedge_descriptor &h)
Gives a normal vector of the triangle containing the halfedge_handle h.
Definition: Compression_Valence_Component.inl:7208
Arithmetic_Codec
Arithmetic codec.
Definition: arithmetic_codec.hpp:154
Point_Int::y
int y
The y coordinate.
Definition: Compression_Valence_Component.h:35
boost::get
boost::property_map< FEVV::DataStructures::AIF::AIFMesh, boost::vertex_index_t >::const_type get(const boost::vertex_index_t &, const FEVV::DataStructures::AIF::AIFMesh &)
Returns the vertex index property map of the mesh.
Definition: Graph_properties_aif.h:108
msdm2::vertex_descriptor
boost::graph_traits< MeshT >::vertex_descriptor vertex_descriptor
Definition: msdm2_surfacemesh.h:33
Compression_Valence_Component::print_vertex
void print_vertex(const std::string &title, const vertex_descriptor &v, const PointMap *_pm)
Definition: Compression_Valence_Component.inl:1251
Color_Unit::c1
int c1
Definition: Compression_Valence_Component.h:121
Compression_Valence_Component::Write_Info
void Write_Info(HalfedgeGraph &pMesh)
Write information of each LoD at decompression in a file.
Definition: Compression_Valence_Component.inl:6678
Adaptive_Data_Model::reset
void reset(void)
Definition: arithmetic_codec.inl:1020
Compression_Valence_Component::Get_Average_Vertex_Color_Lee
Color_Unit Get_Average_Vertex_Color_Lee(const halfedge_descriptor &h, const int &valence, const HalfedgeGraph &_pMesh)
Gets an average vertex color prediction using Lee's method.
Definition: Compression_Valence_Component.inl:7672
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
Point3d
EnrichedPolyhedron::Point_3 Point3d
Definition: boolops_cpolyhedron_builder.hpp:27
Graph_traits_extension.h
Compression_Valence_Component::Change_Real_Int
Point_Int Change_Real_Int(const Point3d &pt, const int &Component_ID)
Change from real to int point(related to quantization bit)
Definition: Compression_Valence_Component.inl:6233
Compression_Valence_Component::Is_Manifold_Property_Violated
bool Is_Manifold_Property_Violated(const HalfedgeGraph &_pMesh, const halfedge_descriptor &h, const int &type, const int &valence)
Query if removal of this vertex would violate the manifold_property or not.
Definition: Compression_Valence_Component.inl:6843
Compression_Valence_Component::Diminush_Color_Quantization_Precision
void Diminush_Color_Quantization_Precision(HalfedgeGraph &pMesh, const int Component_ID, VertexColorMap *_v_cm)
Reduces quantization precision of color coordinates.
Definition: Compression_Valence_Component.inl:4620
C0_QUANTIZATION
const int C0_QUANTIZATION
Definition: Compression_Valence_Common.h:30
FEVV::DataStructures::AIF::out_degree
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::degree_size_type out_degree(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_descriptor u, const FEVV::DataStructures::AIF::AIFMesh &)
Definition: Graph_traits_aif.h:528
Compression_Valence_Component::Get_Correct_Vector
int Get_Correct_Vector(int i, int j, int k)
ADAPTIVE_QUANTIZATION : gets symbols to correct Vector of under_quantization.
Definition: Compression_Valence_Component.inl:9347
square
static T square(const T x)
Definition: Compression_Valence_Component.inl:8472
Compression_Valence_Component::Simplification
void Simplification(HalfedgeGraph &pMesh, const PointMap *_pm, const int &NVertices, const bool Is_normal_flipping_selected, const bool Is_use_metric_selected, const float &Metric_thread, const bool Is_use_forget_metric_selected, const int &Forget_value)
Mesh Simplification which applies iteratively decimation and regulation in pair.
Definition: Compression_Valence_Component.inl:3797
Compression_Valence_Component::Find_Type
int Find_Type(const HalfedgeGraph &_pMesh, const halfedge_descriptor &h, const int &valence)
To find a correspondent type to retriangulate.
Definition: Compression_Valence_Component.inl:6755
Compression_Valence_Component::Is_Normal_Flipping_Occured
bool Is_Normal_Flipping_Occured(const HalfedgeGraph &_pMesh, const PointMap *_pm, const halfedge_descriptor &h, const unsigned &valence)
Query if removal of the front vertex can cause a normal flipping problem.
Definition: Compression_Valence_Component.inl:7082
Compression_Valence_Component::Vector
FEVV::Geometry_traits< HalfedgeGraph >::Vector Vector
Definition: Compression_Valence_Component.h:220
Compression_Valence_Component::halfedge_iterator
GraphTraits::halfedge_iterator halfedge_iterator
Definition: Compression_Valence_Component.h:219
FEVV::vertex_normal
@ vertex_normal
Definition: properties.h:35
Compression_Valence_Component::Change_Int_Real
Point3d Change_Int_Real(const Point_Int &pt, const int &Component_ID)
Change from int to real point(related to quantization bit)
Definition: Compression_Valence_Component.inl:6278
Compression_Valence_Component::print_halfedge
void print_halfedge(const std::string &title, const halfedge_descriptor &h, const HalfedgeGraph &_pMesh, const PointMap *_pm)
Definition: Compression_Valence_Component.inl:1226
Compression_Valence_Component::Decompress_Init
void Decompress_Init(HalfedgeGraph &pMesh, PointMap *_pm, VertexColorMap *_v_cm, bool &has_color, const std::string &Input_File_Name)
Initialize the Decompression by loading the base mesh into pMesh. aka decompress the first (simplest)...
Definition: Compression_Valence_Component.inl:5471
Compression_Valence_Component::Area_Facet_Triangle
double Area_Facet_Triangle(const typename boost::graph_traits< HalfedgeGraph >::halfedge_descriptor &h, const HalfedgeGraph &mesh, const PointMap *pm)
Gives an area of the triangle which contain the halfedge_handle h.
Definition: Compression_Valence_Component.inl:7571
MatrixOperations.hpp
Compression_Valence_Component::compute_facet_normal
void compute_facet_normal(const face_descriptor &f, const HalfedgeGraph &_pMesh, const PointMap *_pm)
Definition: Compression_Valence_Component.inl:9227
Compression_Valence_Component::truncate_colors
void truncate_colors(const HalfedgeGraph &_pMesh, VertexColorMap *_v_cm)
Definition: Compression_Valence_Component.inl:9797
Compression_Valence_Component::copy_mesh
static void copy_mesh(const HalfedgeGraph &_pMesh, const VertexColorMap *_v_cm, HalfedgeGraph &mesh_copy, VertexColorMap *v_cm_copy)
Copy the current mesh and vertex-color map to a new mesh and vertex-color map. If v_cm_copy == nullpt...
Definition: Compression_Valence_Component.inl:6521
Compression_Valence_Component::compute_normals_per_facet
void compute_normals_per_facet(const HalfedgeGraph &_pMesh, const PointMap *_pm)
Definition: Compression_Valence_Component.inl:9198
FEVV::Math::Vector::dot_product
static ElementType dot_product(const ElementType v1[DIM], const ElementType v2[DIM])
Compute v1 * v2 scalar product.
Definition: MatrixOperations.hpp:421
FEVV::size_of_vertices
boost::graph_traits< MeshT >::vertices_size_type size_of_vertices(const MeshT &g)
Real current number of vertices of the mesh. Generic version.
Definition: Graph_traits_extension.h:29
Compression_Valence_Component::Main_Function
std::string Main_Function(HalfedgeGraph &pMesh, PointMap *_pm, VertexColorMap *_v_cm, const std::string &Input_File_Name, const std::string &File_Name, const int &Qbit, const int &NVertices, const bool Is_normal_flipping_selected, const bool Is_use_metric_selected, const float &Metric_thread, const bool Is_use_forget_metric_selected, const int &Forget_value, const bool Is_compression_selected, const bool Is_adaptive_quantization_selected, const bool Is_bijection_selected)
Main function of compression.
Definition: Compression_Valence_Component.inl:56
Arithmetic_Codec::write_to_file
unsigned write_to_file(FILE *code_file)
Definition: arithmetic_codec.inl:732
Color_Unit::c2
int c2
Definition: Compression_Valence_Component.h:122
Compression_Valence_Component::Decimation_Conquest
int Decimation_Conquest(HalfedgeGraph &pMesh, const PointMap *_pm, const bool Is_normal_flipping_selected, const bool Is_use_metric_selected, const float &Metric_thread, const bool Is_use_forget_metric_selected, const int &Forget_value, const int &Component_ID)
Removal of a set of independent vertices.
Definition: Compression_Valence_Component.inl:1342
TO_BE_REMOVED
const int TO_BE_REMOVED
Definition: Compression_Valence_Common.h:36
FEVV::DataStructures::AIF::AIFPoint
Definition: AIFProperties.h:31
Compression_Valence_Component::Decompression_All_From_File
std::string Decompression_All_From_File(HalfedgeGraph &_pMesh, PointMap *_pm, VertexColorMap *_v_cm, bool do_write_info, std::vector< HalfedgeGraph * > *intermediate_meshes, std::vector< VertexColorMap * > *intermediate_vertexColorMaps, int stop_level=-1, bool do_write_intermediate_meshes=false)
Decompression of all LoDs from file, or until a specified level. The finest LoD is visualized without...
Definition: Compression_Valence_Component.inl:6584
FEVV::DataStructures::AIF::put
void put(const typename FEVV::DataStructures::AIF::PropertyMap< ValueT > &pm, KeyT k, const ValueT &v)
Specialization of put(pmap, key, value) for AIF.
Definition: Graph_properties_aif.h:214
Arithmetic_Codec::stop_encoder
unsigned stop_encoder(void)
Definition: arithmetic_codec.inl:697
AC_BUFFER
#define AC_BUFFER
Definition: Compression_Valence_Component.inl:45
COLOR_NUMBER
#define COLOR_NUMBER
Definition: Compression_Valence_Component.inl:43
RGB_To_LAB
void RGB_To_LAB(float r, float g, float b, float *lab)
Rgb to lab.
Definition: Compression_Valence_Common.h:66
FEVV::DataStructures::AIF::remove_face
void remove_face(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::face_descriptor f, FEVV::DataStructures::AIF::AIFMesh &sm)
Removes f from the mesh.
Definition: Graph_traits_aif.h:971