LVRPointBufferBridge.cpp
Go to the documentation of this file.
1 
34 #include "LVRPointBufferBridge.hpp"
35 #include "LVRModelBridge.hpp"
36 
37 #include <vtkSmartPointer.h>
38 #include <vtkPolyData.h>
39 #include <vtkCellArray.h>
40 #include <vtkPolyDataMapper.h>
41 #include <vtkPoints.h>
42 #include <vtkActor.h>
43 #include <vtkProperty.h>
44 #include <vtkPointData.h>
45 #include <vtkFloatArray.h>
46 #include <vtkIdFilter.h>
47 #include <vtkDataSetSurfaceFilter.h>
48 
49 #include "lvr2/util/Util.hpp"
50 
51 namespace lvr2
52 {
53 
55 {
56 
57  m_vtk_polyData = vtkSmartPointer<vtkPolyData>::New();
58  // use all silders with channel 0
59  m_useSpectralChannel.r = true;
60  m_useSpectralChannel.g = true;
61  m_useSpectralChannel.b = true;
65  m_useGradient = false;
66  m_useNDVI = false;
69  m_spectralGradient = HOT; // default gradientype: HOT
70 
71  m_numPoints = 0;
72  m_hasNormals = false;
73  m_hasColors = false;
74 
75  if(pointCloud)
76  {
77  // Save pc data
78  m_pointBuffer = pointCloud;
79 
80  if(pointCloud->hasColors()) m_hasColors = true;
81  if(pointCloud->hasNormals()) m_hasNormals = true;
82 
83  // default: visible light
87 
88  // Generate vtk actor representation
89  computePointCloudActor(pointCloud);
90 
91  // Save meta information
92  m_numPoints = pointCloud->numPoints();
93 
94  }
95 }
96 
97 template <typename T>
98 bool color_equal(const color<T> &col1, const color<T> &col2)
99 {
100  return col1.r == col2.r && col1.g == col2.g && col1.b == col2.b;
101 }
102 
104 {
105  // do not update if nothing has changed
106  if (color_equal(channels, m_spectralChannels) && color_equal(use_channel, m_useSpectralChannel))
107  {
108  return;
109  }
110 
111  // set new values
112  m_spectralChannels = channels;
113  m_useSpectralChannel = use_channel;
114 
115  // update the view
117 }
118 
119 
121 {
122  size_t n;
123  size_t n_channels;
124  ucharArr spec = m_pointBuffer->getUCharArray("spectral_channels", n, n_channels);
125 
126  // check if we have spectral data
127  if (!spec)
128  {
129  return;
130  }
131 
132  // create colorbuffer
133  vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
134  scalars->SetNumberOfComponents(3);
135  scalars->SetName("Colors");
136  scalars->SetNumberOfTuples(n);
137 
138  #pragma omp parallel for
139  for (vtkIdType i = 0; i < n; i++)
140  {
141  int specIndex = n_channels * i;
142  unsigned char speccolor[3];
143  // if the silder is not enabled the color get the value 0
144  speccolor[0] = m_useSpectralChannel.r ? spec[specIndex + m_spectralChannels.r] : 0;
145  speccolor[1] = m_useSpectralChannel.g ? spec[specIndex + m_spectralChannels.g] : 0;
146  speccolor[2] = m_useSpectralChannel.b ? spec[specIndex + m_spectralChannels.b] : 0;
147 
148 #if VTK_MAJOR_VERSION < 7
149  scalars->SetTupleValue(i, speccolor);
150 #else
151  scalars->SetTypedTuple(i, speccolor); // no idea how the new method is called
152 #endif
153  }
154 
155  // set new colors
156  m_pointCloudActor->GetMapper()->GetInput()->GetPointData()->SetScalars(scalars);
157 }
158 
160 {
161  channels = m_spectralChannels;
162  use_channel = m_useSpectralChannel;
163 }
164 
165 void LVRPointBufferBridge::setSpectralColorGradient(GradientType gradient, size_t channel, bool normalized, bool useNDVI)
166 {
167  // do not update if nothing has changed
168  if (m_spectralGradient == gradient && m_spectralGradientChannel == channel
169  && m_useNormalizedGradient == normalized && m_useNDVI == useNDVI)
170  {
171  return;
172  }
173 
174  // set new values
175  m_spectralGradient = gradient;
176  m_spectralGradientChannel = channel;
178  m_useNDVI = useNDVI;
179 
180  // update the view
182 }
183 
185 {
186  size_t n;
187  size_t n_channels;
188  ucharArr spec = m_pointBuffer->getUCharArray("spectral_channels", n, n_channels);
189 
190  // check if we have spectral data
191  if (!spec)
192  {
193  return;
194  }
195 
196  // calculate the ndvi values
197  float ndviMax = 0;
198  float ndviMin = 1;
199 
200  floatArr ndvi;
201  if (m_useNDVI)
202  {
203  ndvi = floatArr(new float[n]);
204 
205  size_t redStart = Util::getSpectralChannel(400, m_pointBuffer, 0);
206  size_t redEnd = Util::getSpectralChannel(700, m_pointBuffer, 1);
207  size_t nearRedStart = Util::getSpectralChannel(700, m_pointBuffer, n_channels - 2);
208  size_t nearRedEnd = Util::getSpectralChannel(1100, m_pointBuffer, n_channels - 1);
209 
210  #pragma omp parallel for reduction(max : ndviMax), reduction(min : ndviMin)
211  for (int i = 0; i < n; i++)
212  {
213  float redTotal = 0;
214  float nearRedTotal = 0;
215  unsigned char* specPixel = spec.get() + n_channels * i;
216 
217  // sum red and nir
218  for (int channel = redStart; channel < redEnd; channel++)
219  {
220  redTotal += specPixel[channel];
221  }
222  for (int channel = nearRedStart; channel < nearRedEnd; channel++)
223  {
224  nearRedTotal += specPixel[channel];
225  }
226 
227  // use NDVI formula:
228  float red = redTotal / (redEnd - redStart);
229  float nearRed = nearRedTotal / (nearRedEnd - nearRedStart);
230 
231  float val = (nearRed - red) / (nearRed + red);
232  val = (val + 1) / 2; // NDVI is in range [-1, 1] => transform to [0, 1]
233  ndvi[i] = val;
234 
235  // get min and max
236  if (val < ndviMin) ndviMin = val;
237  if (val > ndviMax) ndviMax = val;
238  }
239  }
240 
241  // create colorbuffer
242  vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
243  scalars->SetNumberOfComponents(3);
244  scalars->SetName("Colors");
245  scalars->SetNumberOfTuples(n);
246 
247  // normalize data
248  unsigned char min = 0;
249  unsigned char max = 255;
251  {
252  // get min and max
254  #pragma omp parallel for reduction(max : max_val), reduction(min : min_val)
255  for (int i = 0; i < n; i++)
256  {
257  int specIndex = n_channels * i + m_spectralGradientChannel;
258  if(spec[specIndex] > max_val)
259  {
260  max_val = spec[specIndex];
261  }
262  if(spec[specIndex] < min_val)
263  {
264  min_val = spec[specIndex];
265  }
266  }
267  min = min_val;
268  max = max_val;
269  }
270 
272  {
273  min = ndviMin * 255;
274  max = ndviMax * 255;
275  }
276 
277  // Colormap is used to calculate gradients
278  ColorMap colorMap(max - min);
279 
280  // update all colors
281  #pragma omp parallel for
282  for (int i = 0; i < n; i++)
283  {
284  int specIndex = n_channels * i;
285  float color[3];
286 
287  // get gradient colors
288  if (m_useNDVI)
289  {
290  colorMap.getColor(color, (unsigned char) ((ndvi[i] * 255) - min) , m_spectralGradient);
291  }
292  else
293  {
294  colorMap.getColor(color, spec[specIndex + m_spectralGradientChannel] - min, m_spectralGradient);
295  }
296 
297  unsigned char speccolor[3];
298  speccolor[0] = color[0] * 255;
299  speccolor[1] = color[1] * 255;
300  speccolor[2] = color[2] * 255;
301 
302 #if VTK_MAJOR_VERSION < 7
303  scalars->SetTupleValue(i, speccolor);
304 #else
305  scalars->SetTypedTuple(i, speccolor); // no idea how the new method is called
306 #endif
307  }
308 
309  // set new colors
310  m_pointCloudActor->GetMapper()->GetInput()->GetPointData()->SetScalars(scalars);
311 }
312 
313 void LVRPointBufferBridge::getSpectralColorGradient(GradientType &gradient, size_t &channel, bool &normalized, bool &useNDVI) const
314 {
315  gradient = m_spectralGradient;
316  channel = m_spectralGradientChannel;
317  normalized = m_useNormalizedGradient;
318  useNDVI = m_useNDVI;
319 }
320 
322 {
324 
325  // update the view
326  if(useGradient)
327  {
329  }
330  else
331  {
333  }
334 }
335 
337 {
338  return m_pointBuffer;
339 }
340 
342 {
343  return m_numPoints;
344 }
345 
347 {
348  return m_pointBuffer->hasNormals();
349 }
350 
352 {
353  return m_hasColors;
354 }
355 
357 {
358 }
359 
361 {
362  if(pc)
363  {
364  m_pointCloudActor = vtkSmartPointer<vtkActor>::New();
365 
366  // Setup a poly data object
367  vtkSmartPointer<vtkPolyData> vtk_polyData = vtkSmartPointer<vtkPolyData>::New();
368  vtkSmartPointer<vtkPoints> vtk_points = vtkSmartPointer<vtkPoints>::New();
369 // vtkSmartPointer<vtkCellArray> vtk_cells = vtkSmartPointer<vtkCellArray>::New();
370 
371  //vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
372  //scalars->SetNumberOfComponents(3);
373  //scalars->SetName("Colors");
374 
375  double point[3];
376  double normal[3];
377  size_t n, n_c, n_s_p;
378  size_t n_s_channels, w_color;
379  n = pc->numPoints();
380  n_c = n;
381 
382  floatArr points = pc->getPointArray();
383  ucharArr colors = pc->getColorArray(w_color);
384  ucharArr spec = pc->getUCharArray("spectral_channels", n_s_p, n_s_channels);
385  floatArr normals = pc->getNormalArray();
386 
387 
388  std::cout << lvr2::timestamp << " " << n << " Points" << std::endl;
389  vtkSmartPointer<vtkFloatArray> pts_data = vtkSmartPointer<vtkFloatArray>::New();
390  pts_data->SetNumberOfComponents(3);
391  pts_data->SetVoidArray(points.get(), n * 3, 1);
392  vtk_points->SetData(pts_data);
393  std::cout << lvr2::timestamp << "Mapped" << std::endl;
394 
395  vtkSmartPointer<vtkCellArray> vtk_cells = vtkSmartPointer<vtkCellArray>::New();
396  vtkSmartPointer<vtkIdTypeArray> cells = vtkSmartPointer<vtkIdTypeArray>::New();
397  vtkIdType* cell_buf = new vtkIdType[n * 2];
398  for(size_t i = 0; i < n; i++)
399  {
400  size_t i2 = 2 * i;
401  cell_buf[i2 + 0] = static_cast<vtkIdType>(1);
402  cell_buf[i2 + 1] = i;
403 // (*tri_data).InsertValue(i2 + 0 , static_cast<vtkIdType>(3));
404 // (*tri_data).InsertValue(i2 + 1 , static_cast<vtkIdType>(indices[index + 0]));
405 // (*tri_data).InsertValue(i2 + 2 , static_cast<vtkIdType>(indices[index + 1]));
406 // (*tri_data).InsertValue(i2 + 3 , static_cast<vtkIdType>(indices[index + 2]));
407  }
408 
409  cells->SetVoidArray(cell_buf, n * 2, 0, vtkIdTypeArray::VTK_DATA_ARRAY_DELETE);
410  //tri_data->SetVoidArray(tri_buf, n_i * 4, 1);
411  vtk_cells->SetCells(n, cells);
412 
413  vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
414  scalars->SetNumberOfComponents(3);
415  scalars->SetName("Colors");
416 
417 // what was it good for? (Nanana)
418 // if (spec || colors)
419 // {
420 // scalars->SetNumberOfTuples(n_s_p ? n_s_p : n);
421 // }
422 
423  if(spec)
424  {
425  // TODO IS this correct?!
426  // This only works correctly if every point has a spectral value
427  //if (n >= n_s_p) // only take points with spectral information
428  //{
429  // break;
430  //}
431 
432  if(n_s_p == n)
433  {
434  // need to copy spectral values to buffer
435  unsigned char* spec_buf = new unsigned char[n * 3];
436  for(size_t i = 0; i < n; ++i)
437  {
438  size_t specIndex = n_s_channels * i;
439  size_t i2 = 3 * i;
440  spec_buf[i2 + 0] = spec[specIndex + m_spectralChannels.r];
441  spec_buf[i2 + 1] = spec[specIndex + m_spectralChannels.g];
442  spec_buf[i2 + 2] = spec[specIndex + m_spectralChannels.b];
443  }
444  // map buffer and let vtk delete it
445  scalars->SetVoidArray(spec_buf, n * 3, vtkIdTypeArray::VTK_DATA_ARRAY_DELETE);
446  }
447  }
448  else if(colors)
449  {
450  // simply map colors buffer and prevent vtk from deleting it
451  scalars->SetVoidArray(colors.get(), n * w_color, 1);
452  }
453 
454  m_vtk_normals = vtkSmartPointer<vtkDoubleArray>::New();
455  m_vtk_normals->SetNumberOfComponents(3);
456  m_vtk_normals->SetName("Normals");
457 
458  if(normals)
459  {
460  // We need to copy normals becaus of they are not binary compatible
461  // lvr=float -> vtk=double
462  // maybe there will be an api in newer vtk versions..
463  // is there an vtk double type?
464  double* normal_buf = new double[n * 3];
465  for(size_t i = 0; i < n; ++i)
466  {
467  size_t index = 3 * i;
468  normal_buf[index + 0] = normals[index + 0];
469  normal_buf[index + 1] = normals[index + 1];
470  normal_buf[index + 2] = normals[index + 2];
471  }
472  // map buffer and let vtk delete it
473  m_vtk_normals->SetVoidArray(normal_buf, n * 3, vtkIdTypeArray::VTK_DATA_ARRAY_DELETE);
474 
475  }
476 
477 
478  m_vtk_polyData->SetPoints(vtk_points);
479  m_vtk_polyData->SetVerts(vtk_cells);
480 
481 
482  vtkSmartPointer<vtkIdFilter> pointFilter =
483  vtkSmartPointer<vtkIdFilter>::New();
484 
485  pointFilter->SetInputData(m_vtk_polyData);
486 #if VTK890
487  pointFilter->SetCellIdsArrayName("OriginalIds");
488  pointFilter->SetPointIdsArrayName("OriginalIds");
489 #else
490  pointFilter->SetIdsArrayName("OriginalIds");
491 #endif
492  pointFilter->Update();
493 
494 // vtkSmartPointer<vtkDataSetSurfaceFilter> surfaceFilter =
495 // vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
496 // surfaceFilter->SetInputConnection(pointFilter->GetOutputPort());
497 // surfaceFilter->Update();
498 //
499 // m_id_polyData = surfaceFilter->GetOutput();
500 
501 //m_vtk_polyData->GetPointData()->AddArray(ids);
502 
503  if(hasColors() || n_s_p)
504  {
505  m_vtk_polyData->GetPointData()->SetScalars(scalars);
506  }
507 
508  // Create poly data mapper and generate actor
509  vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
510 #ifdef LVR2_USE_VTK5
511  mapper->SetInput(m_vtk_polyData);
512 #else
513  mapper->SetInputData(m_vtk_polyData);
514 #endif
515  m_pointCloudActor->SetMapper(mapper);
516  m_pointCloudActor->GetProperty()->SetColor(1.0, 1.0, 1.0);
517  m_pointCloudActor->GetProperty()->SetPointSize(5);
518  }
519 }
520 
522 {
530  m_useNDVI = b.m_useNDVI;
534 }
535 
536 void LVRPointBufferBridge::setBaseColor(float r, float g, float b)
537 {
538  m_pointCloudActor->GetProperty()->SetColor(r, g, b);
539 }
540 
542 {
543  vtkSmartPointer<vtkProperty> p = m_pointCloudActor->GetProperty();
544  p->SetPointSize(pointSize);
545 }
546 
547 void LVRPointBufferBridge::setOpacity(float opacityValue)
548 {
549  vtkSmartPointer<vtkProperty> p = m_pointCloudActor->GetProperty();
550  p->SetOpacity(opacityValue);
551 }
552 
554 {
555  m_pointCloudActor->GetMapper()->SetScalarVisibility(visible);
556 }
557 
559 {
560  m_pointCloudActor->SetVisibility(visible);
561 }
562 
564 {
565  if(m_hasNormals)
566  {
567  if(visible)
568  {
569  m_pointCloudActor->GetMapper()->GetInput()->GetPointData()->SetNormals(
571  );
572  } else {
573  m_pointCloudActor->GetMapper()->GetInput()->GetPointData()->SetNormals(
574  NULL
575  );
576  }
577  }
578 }
579 
580 vtkSmartPointer<vtkPolyData> LVRPointBufferBridge::getPolyData()
581 {
582  return m_vtk_polyData;
583 }
584 
585 vtkSmartPointer<vtkPolyData> LVRPointBufferBridge::getPolyIDData()
586 {
587  return m_id_polyData;
588 }
589 vtkSmartPointer<vtkActor> LVRPointBufferBridge::getPointCloudActor()
590 {
591  return m_pointCloudActor;
592 }
593 
594 
595 } /* namespace lvr2 */
void useGradient(bool useGradient)
switch between spectral mapping and gradient
void computePointCloudActor(PointBufferPtr pc)
void getSpectralColorGradient(GradientType &gradient, size_t &channel, bool &normalized, bool &useNDVI) const
get the gradienttype, channel, normalizend and ndvi flags
void getColor(float *color, size_t bucket, GradientType gradient=GREY)
Returns three float values for the color of the given bucket.
Definition: ColorMap.cpp:43
static int getSpectralChannel(int wavelength, PointBufferPtr p, int fallback=-1)
Returns the spectral channel index for a given wavelength.
Definition: Util.cpp:35
vtkSmartPointer< vtkPolyData > getPolyIDData()
static Timestamp timestamp
A global time stamp object for program runtime measurement.
Definition: Timestamp.hpp:116
void setOpacity(float opacityValue)
vtkSmartPointer< vtkDoubleArray > m_vtk_normals
boost::shared_array< unsigned char > ucharArr
Definition: DataStruct.hpp:137
void setSpectralColorGradient(GradientType gradient, size_t channel, bool normalized=false, bool ndvi=false)
set the gradienttype, desired channel, if the outputcolor should be normalized and if the NDVI should...
std::shared_ptr< PointBuffer > PointBufferPtr
vtkSmartPointer< vtkActor > m_pointCloudActor
void setBaseColor(float r, float g, float b)
__kf_device__ float3 normalized(const float3 &v)
Definition: temp_utils.hpp:97
void refreshSpectralChannel()
update the view with channel mappings
void getSpectralChannels(color< size_t > &channels, color< bool > &use_channel) const
get spectral channel mappings
boost::shared_array< float > floatArr
Definition: DataStruct.hpp:133
SharedPointer p
GradientType
Identifies a color gradient.
Definition: ColorMap.hpp:50
void refreshSpectralGradient()
update the view with gradient information
void setSpectralChannels(color< size_t > channels, color< bool > use_channel)
set the spectral channel for (r, g, b) and set if it is used
void setColorsVisibility(bool visible)
void setNormalsVisibility(bool visible)
vtkSmartPointer< vtkPolyData > getPolyData()
vtkSmartPointer< vtkPolyData > m_vtk_polyData
LVRPointBufferBridge(PointBufferPtr pointcloud)
vtkSmartPointer< vtkActor > getPointCloudActor()
bool color_equal(const color< T > &col1, const color< T > &col2)
vtkSmartPointer< vtkPolyData > m_id_polyData
#define NULL
Definition: mydefs.hpp:141
PointBufferPtr getPointBuffer()
get the point buffer


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:08