MEPP2 Project
Binary_batch_encoder.h
Go to the documentation of this file.
1 // Copyright (c) 2012-2022 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 
12 #pragma once
13 
14 #include <boost/graph/graph_traits.hpp>
15 #include <boost/graph/properties.hpp>
17 
18 #include <iostream>
19 #include <fstream>
20 #include <iomanip>
21 #include <list>
22 #include <vector>
23 #include <utility>
24 
25 #ifdef _MSC_VER
26 #pragma warning(push)
27 #pragma warning(disable : 4146 26812 26451)
28 #endif
29 
31 
32 #if defined _MSC_VER
33 #pragma warning(pop)
34 #endif
35 
36 namespace FEVV {
37 namespace Filters {
38 
44 template<
45  typename HalfedgeGraph,
46  typename PointMap,
49  typename vertex_descriptor =
51  typename Geometry = FEVV::Geometry_traits< HalfedgeGraph > >
53 {
54 private:
56 public:
60  static void init_measure_file(const std::string& csv_file_path)
61  {
62  std::ofstream csv_file;
63  csv_file.open(csv_file_path);
64  csv_file
65  << "NUM_BATCH,SIZE_BITMASK,SIZE_CONNECTIVITY,SIZE_RESIDUALS,BITMASK_"
66  "ENTROPY,CONNECTIVITY_ENTROPY,RESIDUALS_ENTROPY,DISTORTION_RMSE,"
67  "DISTORTION_HAUSDORFF,NBVALUESBITMASK,NBVALUESCONNECTIVITY,NBVALUESOTHERINFO,"
68  "SIZEOTHERINFO,ENTROPYOTHERINFO,SIZE_HEADER,NUM_VERTICES"
69  << "\n";
70 
71  csv_file.close();
72  }
74  static void add_line_measure_file(const std::string &csv_file_path,
75  int num_batch,
76  std::pair< int, double > &data_bitmask, // returned by Binary_batch_encoder::encode_bitmask (gives the the actual size of the bitmask and the entropy)
77  std::pair< int, double > &data_connectivity,// returned by Binary_batch_encoder::encode_bitmask
78  std::pair< int, double > &data_residuals,// returned by Binary_batch_encoder::encode_residuals
79  std::pair< int, double > &data_other_info,// returned by Binary_batch_encoder::encode_bitmask
80  double dist_RMSE, // Distortion value
81  double dist_hausdorff, // Distortion value
82  size_t num_values_bitmask,
83  size_t num_values_connectivity,
84  size_t num_values_other_info,
85  size_t size_header, // size of encoded header
86  size_t num_vertices)
87  {
88  std::ofstream csv_file;
89 
90  csv_file.open(csv_file_path, std::ofstream::app);
91  csv_file << num_batch << "," << data_bitmask.first << ","
92  << data_connectivity.first << "," << data_residuals.first << ","
93  << data_bitmask.second << "," << data_connectivity.second << ","
94  << data_residuals.second << "," << dist_RMSE << "," << dist_hausdorff << ","
95  << num_values_bitmask << "," << num_values_connectivity << ","
96  << num_values_other_info << "," << data_other_info.first << ","
97  << data_other_info.second << "," << size_header << ","
98  << num_vertices << "\n";
99 
100  csv_file.close();
101  }
102 
105  size_t quantize_encode_coarse_mesh(HalfedgeGraph &g,
106  PointMap &pm,
107  const Geometry &gt,
108  draco::EncoderBuffer &buffer
109  )
110  {
111  auto iterator_pair = vertices(g);
112  auto faces_pair = faces(g);
113  auto num_faces_ = std::distance(faces_pair.first, faces_pair.second);
114  auto num_positions_ =
115  std::distance(iterator_pair.first, iterator_pair.second);
116  size_t original_size = buffer.size();
117  if(num_faces_ == 0)
118  {
119  return 0;
120  }
121 
122  g_draco.SetNumFaces(num_faces_);
123  draco::PointCloud *out_point_cloud_ =
124  static_cast< draco::PointCloud * >(&g_draco);
125  out_point_cloud_->set_num_points(
126  3 * static_cast<unsigned int>(num_faces_));
127 
128  draco::GeometryAttribute va;
129  va.Init(draco::GeometryAttribute::POSITION,
130  nullptr,
131  3,
132  draco::DT_INT32, // \todo Why to not use uint32 instead?
133  false,
134  sizeof(int32_t) * 3,
135  0);
136  int pos_att_id_ = out_point_cloud_->AddAttribute(va, false, static_cast<unsigned int>(num_positions_));
137 
138  // Add vertex position coordinates
139  std::map< vertex_descriptor, int > vertex_pos;
140 
141  int pos_num = 0;
142  auto vi = iterator_pair.first;
143  std::vector< uint32_t > vertex_data;
144  vertex_data.reserve(num_positions_ * 3);
145  for( ; vi != iterator_pair.second; ++vi, ++pos_num)
146  {
147  vertex_pos.insert(std::pair< vertex_descriptor, int >(*vi, pos_num));
148  uint32_t val[3];
149  const Point& pos = get(pm, *vi);
150  val[0] = static_cast< uint32_t >(gt.get_x(pos));
151  val[1] = static_cast< uint32_t >(gt.get_y(pos));
152  val[2] = static_cast< uint32_t >(gt.get_z(pos));
153  vertex_data.push_back(val[0]);
154  vertex_data.push_back(val[1]);
155  vertex_data.push_back(val[2]);
156  out_point_cloud_->attribute(pos_att_id_)
157  ->SetAttributeValue(draco::AttributeValueIndex(pos_num), val);
158  }
159 
160  // Add connectivity data
161  int pos_face = 0;
162  auto iterator_pair_f = faces(g);
163  auto fi = iterator_pair_f.first;
164  for( ; fi != iterator_pair_f.second; ++fi, ++pos_face)
165  {
166  std::vector< vertex_descriptor > vertices_of_face;
167  vertices_of_face.reserve(3);
168  boost::iterator_range<
169  CGAL::Vertex_around_face_iterator< HalfedgeGraph > >
170  iterator_range_vf = CGAL::vertices_around_face(halfedge(*fi, g), g);
171  for(auto vf : iterator_range_vf)
172  vertices_of_face.push_back(vf);
173  for(int i = 0; i < 3; ++i)
174  {
175  const draco::PointIndex vert_id(3 * pos_face + i);
176  vertex_descriptor vertex = vertices_of_face[i];
177  int vertex_id = (vertex_pos.find(vertex))->second;
178  out_point_cloud_->attribute(pos_att_id_)
179  ->SetPointMapEntry(vert_id, draco::AttributeValueIndex(vertex_id));
180  }
181  }
182  draco::Mesh::Face face;
183  for(draco::FaceIndex i(0); i < static_cast<uint32_t>(num_faces_); ++i)
184  {
185  for(int c = 0; c < 3; ++c)
186  face[c] = 3 * i.value() + c;
187  g_draco.SetFace(i, face);
188  }
189 
190  draco::Encoder encoder;
192  encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, -1);
193  const draco::Status status = encoder.EncodeMeshToBuffer(g_draco, &buffer);
194 
195  return (buffer.size() - original_size) * 8;
196  }
199  std::pair< int, double > encode_bitmask(const std::list< bool > &bitmask,
200  draco::EncoderBuffer &buffer)
201  {
202  draco::RAnsBitEncoder encoder;
203  int size_buffer = static_cast< int >(buffer.size());
204  draco::EncodeVarint((int)bitmask.size(), &buffer);
205  int nb_true = 0;
206 
207  encoder.StartEncoding();
208  auto it = bitmask.begin(), it_e = bitmask.end();
209  for( ; it != it_e; ++it)
210  {
211  encoder.EncodeBit(*it);
212  if(*it == true)
213  {
214  nb_true += 1;
215  }
216  }
217  encoder.EndEncoding(&buffer);
218 
219  double bitmask_entropy = draco::ComputeBinaryShannonEntropy(
220  static_cast< uint32_t >(bitmask.size()), nb_true);
221 
222  return std::make_pair(static_cast< int >((buffer.size()) - size_buffer) * 8,
223  bitmask_entropy);
224  }
227  std::pair< int, double >
228  encode_residuals(const std::list< std::vector< Vector > > &residuals,
229  draco::EncoderBuffer &buffer,
230  int bit_quantization)
231  {
232  int size_buffer = static_cast< int >(buffer.size());
233  draco::EncodeVarint((int)residuals.size(), &buffer);
234  if((int)residuals.size() > 0)
235  {
236  size_t nb_residuals = residuals.front().size(); // either one or two residuals per vertex split
237 
238  int i = 0;
239 
240  int32_t *p_in = new int32_t[residuals.size() * nb_residuals * 3];
241  uint32_t *p_out = new uint32_t[residuals.size() * nb_residuals * 3];
242 
243  auto residuals_it = residuals.begin(), residuals_it_e = residuals.end();
244 
245  for( ; residuals_it != residuals_it_e; ++residuals_it, ++i)
246  {
247  for(size_t j = 0; j < nb_residuals; j++)
248  {
249 
250  int32_t x = static_cast< int32_t >(((*residuals_it)[j])[0]);
251  int32_t y = static_cast< int32_t >(((*residuals_it)[j])[1]);
252  int32_t z = static_cast< int32_t >(((*residuals_it)[j])[2]);
253 
254  p_in[nb_residuals * 3 * i + 3 * j + 0] = x;
255  p_in[nb_residuals * 3 * i + 3 * j + 1] = y;
256  p_in[nb_residuals * 3 * i + 3 * j + 2] = z;
257  }
258  }
259  draco::ConvertSignedIntsToSymbols(
260  p_in, static_cast< int >(residuals.size() * nb_residuals * 3), p_out);
261  // entropy computation
262  uint32_t max = 0;
263  for(size_t i = 0; i < residuals.size() * nb_residuals * 3; i++)
264  {
265  if(p_out[i] > max)
266  {
267  max = p_out[i];
268  }
269  }
270  auto stream_2_entropy_bits = draco::ComputeShannonEntropy(
271  p_out,
272  static_cast< int >(residuals.size() * nb_residuals * 3),
273  max,
274  nullptr);
275 
276 
277  // delete pointers in
278  delete[] p_in;
279 
280 
281  // encode the prediction
282  draco::SymbolBitEncoder symbolBitEncoder;
283  symbolBitEncoder.StartEncoding();
284  for(size_t count = 0; count < residuals.size() * nb_residuals * 3; count++)
285  {
286  //auto test = p_out[count];
287  symbolBitEncoder.EncodeLeastSignificantBits32(bit_quantization + 1,
288  p_out[count]);
289  }
290 
291  symbolBitEncoder.EndEncoding(&buffer);
292 
293  size_t num_values = residuals.size() * nb_residuals * 3;
294  int num_values_int = (int)num_values;
295  draco::EncoderBuffer buffer_max_comp;
296 
297  draco::Options *opt = new draco::Options();
298  draco::SetSymbolEncodingCompressionLevel(opt, static_cast< int >(10));
299  draco::EncodeSymbols(p_out, num_values_int, 1, opt, &buffer_max_comp);
300  int size_original_method =
301  (static_cast< int >(buffer.size()) - size_buffer) * 8;
302 
303  delete opt;
304  delete[] p_out;
305  return std::make_pair(size_original_method, stream_2_entropy_bits / static_cast<double>(residuals.size() * nb_residuals * 3));
306  }
307  return std::make_pair(0, 0);
308  }
309 };
310 } // namespace Filters
311 } // namespace FEVV
FEVV::DataStructures::AIF::vertices
std::pair< typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_iterator, typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_iterator > vertices(const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns the iterator range of the vertices of the mesh.
Definition: Graph_traits_aif.h:172
FEVV::DataStructures::AIF::num_vertices
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertices_size_type num_vertices(const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns an upper bound of the number of vertices of the mesh.
Definition: Graph_traits_aif.h:191
FEVV::Filters::Binary_batch_encoder::encode_bitmask
std::pair< int, double > encode_bitmask(const std::list< bool > &bitmask, draco::EncoderBuffer &buffer)
Encodes a bit mask with draco's non-adaptive RAns coder (RAnsBitEncoder).
Definition: Binary_batch_encoder.h:199
FEVV::Filters::Binary_batch_encoder::init_measure_file
static void init_measure_file(const std::string &csv_file_path)
Add column titles to cvs file (to call before the addition of measurement lines).
Definition: Binary_batch_encoder.h:60
FEVV::Geometry_traits
Refer to Geometry_traits_documentation_dummy for further documentation on provided types and algorith...
Definition: Geometry_traits.h:162
FEVV::Filters::Binary_batch_encoder::g_draco
draco::Mesh g_draco
Definition: Binary_batch_encoder.h:55
FEVV::get
FEVV::PCLPointCloudPointMap::value_type get(const FEVV::PCLPointCloudPointMap &pm, FEVV::PCLPointCloudPointMap::key_type key)
Specialization of get(point_map, key) for PCLPointCloud.
Definition: Graph_properties_pcl_point_cloud.h:117
FEVV
Interfaces for plugins These interfaces will be used for different plugins.
Definition: Assert.h:16
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::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
Geometry_traits.h
FEVV::Filters::Binary_batch_encoder::add_line_measure_file
static void add_line_measure_file(const std::string &csv_file_path, int num_batch, std::pair< int, double > &data_bitmask, std::pair< int, double > &data_connectivity, std::pair< int, double > &data_residuals, std::pair< int, double > &data_other_info, double dist_RMSE, double dist_hausdorff, size_t num_values_bitmask, size_t num_values_connectivity, size_t num_values_other_info, size_t size_header, size_t num_vertices)
Add a line of measurements to cvs file.
Definition: Binary_batch_encoder.h:74
FEVV::DataStructures::AIF::AIFVector
Definition: AIFProperties.h:173
FEVV::Filters::Binary_batch_encoder::encode_residuals
std::pair< int, double > encode_residuals(const std::list< std::vector< Vector > > &residuals, draco::EncoderBuffer &buffer, int bit_quantization)
Encodes a set of residuals with draco's entropy coder (SymbolBitEncoder)
Definition: Binary_batch_encoder.h:228
Mesh
FEVV::DataStructures::AIF::AIFMesh Mesh
Definition: test_complying_concepts_aif.cpp:18
FEVV::Filters::Binary_batch_encoder::quantize_encode_coarse_mesh
size_t quantize_encode_coarse_mesh(HalfedgeGraph &g, PointMap &pm, const Geometry &gt, draco::EncoderBuffer &buffer)
Encodes a non-textured quantized mesh with draco single-rate mesh encoder.
Definition: Binary_batch_encoder.h:105
msdm2::vertex_descriptor
boost::graph_traits< MeshT >::vertex_descriptor vertex_descriptor
Definition: msdm2_surfacemesh.h:33
FEVV::DataStructures::AIF::face
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::face_descriptor face(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor h, const FEVV::DataStructures::AIF::AIFMesh &)
Returns the face incident to halfedge h.
Definition: Graph_traits_aif.h:664
FEVV::Filters::Binary_batch_encoder
Encode binary data with draco. Also contains static methods to generate csv files.
Definition: Binary_batch_encoder.h:53
Binary_batch_encoder_draco_nowarning.h
FEVV::DataStructures::AIF::AIFPoint
Definition: AIFProperties.h:31