AsciiIO.cpp
Go to the documentation of this file.
1 
28  /*
29  * AsciiIO.cpp
30  *
31  * Created on: 09.03.2011
32  * Author: Thomas Wiemann
33  */
34 
35 #include <fstream>
36 #include <string.h>
37 #include <algorithm>
38 
39 using std::ifstream;
40 
41 #include <boost/filesystem.hpp>
42 
43 #include "lvr2/io/AsciiIO.hpp"
44 #include "lvr2/io/Progress.hpp"
45 #include "lvr2/io/Timestamp.hpp"
46 
47 namespace lvr2
48 {
49 
50 
52  string filename,
53  const int &xPos, const int& yPos, const int& zPos,
54  const int &rPos, const int& gPos, const int& bPos, const int &iPos)
55 {
56  // Check extension
57  boost::filesystem::path selectedFile(filename);
58  string extension(selectedFile.extension().string());
59 
60  if ( extension != ".pts" && extension != ".3d" && extension != ".xyz" && extension != ".txt" )
61  {
62  cout << "»" << extension << "« is not a valid file extension." << endl;
63  return ModelPtr();
64  }
65  // Count lines in file to estimate the number of present points
66  size_t lines_in_file = countLines(filename);
67 
68  if ( lines_in_file < 2 )
69  {
70  cout << timestamp << "AsciiIO: Too few lines in file (has to be > 2)." << endl;
71  return ModelPtr();
72  }
73 
74  // Open file
75  ifstream in;
76  in.open(filename.c_str());
77 
78  // Read first two lines, ignore the first one
79  char buffer[2048];
80  in.getline(buffer, 2048);
81  in.getline(buffer, 2048);
82 
83  // Get number of entries in test line and analize
84  int num_columns = AsciiIO::getEntriesInLine(filename);
85 
86  // Reopen file and read data
87  in.close();
88  in.open(filename.c_str());
89 
90  // Again skip first line
91  in.getline(buffer, 2048);
92 
93  // Buffer related variables
94  size_t numPoints = 0;
95 
96  floatArr points;
97  ucharArr pointColors;
98  floatArr pointIntensities;
99 
100  // Alloc memory for points
101  numPoints = lines_in_file - 1;
102  points = floatArr( new float[ numPoints * 3 ] );
103  ModelPtr model(new Model);
104  model->m_pointCloud = PointBufferPtr( new PointBuffer);
105 
106  // (Some) sanity checks for given paramters
107  if(rPos > num_columns || gPos > num_columns || bPos > num_columns || iPos > num_columns)
108  {
109  cout << timestamp << "Error: At least one attribute index is larger than the number of columns" << endl;
110  // Retrun empty model
111  return ModelPtr();
112  }
113 
114  // Check for color and intensity
115  bool has_color = (rPos > -1 && gPos > -1 && bPos > -1);
116  bool has_intensity = (iPos > -1);
117 
118  // Alloc buffer memory for additional attributes
119  if ( has_color )
120  {
121  pointColors = ucharArr( new uint8_t[ numPoints * 3 ] );
122  }
123 
124  if ( has_intensity )
125  {
126  pointIntensities = floatArr( new float[ numPoints ] );
127  }
128 
129  // Read data form file
130  size_t c = 0;
131  while (in.good() && c < numPoints)
132  {
133  float x, y, z, intensity, dummy;
134  unsigned int r, g, b;
135 
136  for(int i = 0; i < num_columns; i++)
137  {
138  if(i == xPos)
139  {
140  in >> x;
141  }
142  else if(i == yPos)
143  {
144  in >> y;
145  }
146  else if(i == zPos)
147  {
148  in >> z;
149  }
150  else if(i == rPos)
151  {
152  in >> r;
153  }
154  else if(i == gPos)
155  {
156  in >> g;
157  }
158  else if(i == bPos)
159  {
160  in >> b;
161  }
162  else if(i == iPos)
163  {
164  in >> intensity;
165  }
166  else
167  {
168  in >> dummy;
169  }
170 
171  }
172 
173  // Read according to determined format
174  if(has_color)
175  {
176  pointColors[ c * 3 ] = (unsigned char) r;
177  pointColors[ c * 3 + 1 ] = (unsigned char) g;
178  pointColors[ c * 3 + 2 ] = (unsigned char) b;
179 
180  }
181 
182  if (has_intensity)
183  {
184  pointIntensities[c] = intensity;
185 
186  }
187 
188  points[ c * 3 ] = x;
189  points[ c * 3 + 1 ] = y;
190  points[ c * 3 + 2 ] = z;
191  c++;
192  }
193 
194  // Sanity check
195  if(c != numPoints)
196  {
197  cout << timestamp << "Warning: Point count / line count mismatch: "
198  << numPoints << " / " << c << endl;
199  }
200 
201  // Assign buffers
202  size_t numColors = 0;
203  size_t numIntensities = 0;
204 
205  if(has_color)
206  {
207  numColors = numPoints;
208  model->m_pointCloud->setColorArray(pointColors, numColors);
209 
210  }
211 
212  if(has_intensity)
213  {
214  numIntensities = numPoints;
215  model->m_pointCloud->addFloatChannel(pointIntensities, "intensities", numIntensities, 1);
216 
217  }
218 
219 
220  model->m_pointCloud->setPointArray(points, numPoints);
221 
222  this->m_model = model;
223  return model;
224 }
225 
226 
228 {
229  // Check extension
230  boost::filesystem::path selectedFile(filename);
231  string extension(selectedFile.extension().string());
232 
233  if ( extension != ".pts" && extension != ".3d" && extension != ".xyz" && extension != ".txt" )
234  {
235  cout << "»" << extension << "« is not a valid file extension." << endl;
236  return ModelPtr();
237  }
238  // Count lines in file to estimate the number of present points
239  int lines_in_file = countLines(filename);
240 
241  if ( lines_in_file < 2 )
242  {
243  cout << timestamp << "AsciiIO: Too few lines in file (has to be > 2)." << endl;
244  return ModelPtr();
245  }
246  // Open the given file. Skip the first line (as it may
247  // contain meta data in some formats). Then try to guess
248  // the additional data using some heuristics that apply for
249  // most data formats: If 4 values per point are, given
250  // the 4th value usually is a reflectence information.
251  // Six entries suggest RGB information, seven entries
252  // intensity and RGB.
253 
254  // Open file
255  ifstream in;
256  in.open(filename.c_str());
257 
258  // Read first to lines, ignore the first one
259  char buffer[2048];
260  in.getline(buffer, 2048);
261  in.getline(buffer, 2048);
262 
263  // Get number of entries in test line and analize
264  int num_attributes = AsciiIO::getEntriesInLine(filename) - 3;
265  bool has_color = (num_attributes == 3) || (num_attributes == 4);
266  bool has_intensity = (num_attributes == 1) || (num_attributes == 4);
267 
268  if(has_color || has_intensity)
269  {
270  cout << timestamp << "Autodetected the following attributes" << endl;
271  cout << timestamp << "Color: " << has_color << endl;
272  cout << timestamp << "Intensity: " << has_intensity << endl;
273 
274  if(has_color && has_intensity)
275  {
276  return read(filename, 0, 1, 2, 4, 5, 6, 3);
277  }
278  else if(has_color)
279  {
280  return read(filename, 0, 1, 2, 3, 4, 5);
281  }
282  else if(has_intensity)
283  {
284  if(num_attributes == 1)
285  {
286  return read(filename, 0, 1, 2, -1, -1, -1, 3);
287  }
288  else
289  {
290  return read(filename, 0, 1, 2, -1, -1, -1, 6);
291  }
292  }
293  }
294  return read(filename, 0, 1, 2);
295 
296 }
297 
298 
299 
300 void AsciiIO::save( std::string filename )
301 {
302 
303  if ( !this->m_model->m_pointCloud ) {
304  std::cerr << "No point buffer available for output." << std::endl;
305  return;
306  }
307 
308  size_t pointcount( 0 ), buf ( 0 );
309 
310  floatArr points;
311  ucharArr pointColors;
312  floatArr pointIntensities;
313 
314  unsigned w;
315  pointcount = this->m_model->m_pointCloud->numPoints();
316  points = this->m_model->m_pointCloud->getPointArray();
317 // points = this->m_model->m_pointCloud->getIndexedPointArray( pointcount );
318 
319 
320 // pointColors = this->m_model->m_pointCloud->getIndexedPointColorArray( buf );
321 // pointColors = this->m_model->m_pointCloud->getColorArray(buf);
322  auto colors = this->m_model->m_pointCloud->getChannel<unsigned char>("colors");
323  if(colors)
324  {
325  pointColors = (*colors).dataPtr();
326  buf = (*colors).numElements();
327  /* We need the same amount of color information and points. */
328  if ( pointcount != buf )
329  {
330  pointColors.reset();
331  std::cerr << "Amount of points and color information is"
332  " not equal. Color information won't be written" << std::endl;
333  }
334  }
335  // pointIntensities = this->m_model->m_pointCloud->getPointIntensityArray( buf );
336  auto intensity = this->m_model->m_pointCloud->getChannel<float>("intensities");
337  if(intensity)
338  {
339  pointIntensities = (*intensity).dataPtr();
340  buf = (*intensity).numElements();
341 
342 
343  /* We need the same amount of intensity values and points. */
344  if ( pointcount != buf )
345  {
346  pointIntensities.reset();
347  std::cerr << "Amount of points and intensity values are"
348  " not equal. Intensity information will not be written." << std::endl;
349  }
350  }
351 
352  /* Prepare file for writing. */
353  std::ofstream out( filename.c_str() );
354 
355  if ( !out.is_open() ) {
356  std::cerr << "Could not open file »" << filename
357  << "« for output." << std::endl;
358  return;
359  }
360 
361  for ( size_t i(0); i < pointcount; i++ )
362  {
363  out << points[i * 3] << " "
364  << points[i * 3 + 1] << " "
365  << points[i * 3 + 2];
366  if ( pointIntensities )
367  {
368  out << " " << pointIntensities[i];
369  }
370  if ( pointColors )
371  {
372  /* Bad behaviour of C++ output streams: We have to cast the uchars
373  * to unsigned integers. */
374  out << " " << (unsigned int) pointColors[i * 3]
375  << " " << (unsigned int) pointColors[i * 3 + 1]
376  << " " << (unsigned int) pointColors[i * 3 + 2];
377  }
378  out << std::endl;
379  }
380 
381  out.close();
382 
383 }
384 
385 
387 {
388  // Open file for reading
389  ifstream in(filename.c_str());
390 
391  // Count lines in file
392  size_t c = 0;
393  char line[2048];
394  while(in.good())
395  {
396  in.getline(line, 1024);
397  c++;
398  }
399  in.close();
400  return c;
401 }
402 
403 
405 {
406 
407  ifstream in(filename.c_str());
408 
409  // Get first line from file and skip it (possibly metadata)
410  char line[1024];
411  in.getline(line, 1024);
412 
413  // Get second line -> hopefully point data
414  in.getline(line, 1024);
415 
416  in.close();
417 
418  // Get number of blanks
419  int c = 0;
420  char* pch = strtok(line, " ");
421  while(pch){
422  c++;
423  pch = strtok(NULL, " ");
424  }
425 
426  return c;
427 }
428 
429 
430 } // namespace lvr
A class to handle point information with an arbitrarily large number of attribute channels...
Definition: PointBuffer.hpp:51
static int getEntriesInLine(string filename)
Helper method. Returns the number of columns in the given file.
Definition: AsciiIO.cpp:404
static Timestamp timestamp
A global time stamp object for program runtime measurement.
Definition: Timestamp.hpp:116
boost::shared_array< unsigned char > ucharArr
Definition: DataStruct.hpp:137
std::shared_ptr< PointBuffer > PointBufferPtr
Read and write pointclouds from .pts and .3d files.
ModelPtr m_model
Definition: BaseIO.hpp:104
static size_t countLines(string filename)
TODO: Coordinate mapping for ascii files.
Definition: AsciiIO.cpp:386
boost::shared_array< float > floatArr
Definition: DataStruct.hpp:133
std::shared_ptr< Model > ModelPtr
Definition: Model.hpp:80
virtual ModelPtr read(string filename)
Reads the given file and stores point and color information in the given parameters.
Definition: AsciiIO.cpp:227
virtual void save(string filename)
Definition: AsciiIO.cpp:300
#define NULL
Definition: mydefs.hpp:141


lvr2
Author(s): Thomas Wiemann , Sebastian Pütz , Alexander Mock , Lars Kiesow , Lukas Kalbertodt , Tristan Igelbrink , Johan M. von Behren , Dominik Feldschnieders , Alexander Löhr
autogenerated on Mon Feb 28 2022 22:46:06