Point Cloud Library (PCL)  1.9.1-dev
point_cloud_color_handlers.hpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2012-, Open Perception, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of the copyright holder(s) nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 #ifndef PCL_POINT_CLOUD_COLOR_HANDLERS_IMPL_HPP_
39 #define PCL_POINT_CLOUD_COLOR_HANDLERS_IMPL_HPP_
40 
41 #include <set>
42 #include <map>
43 
44 #include <pcl/pcl_macros.h>
45 #include <pcl/common/colors.h>
46 
47 ///////////////////////////////////////////////////////////////////////////////////////////
48 template <typename PointT> vtkSmartPointer<vtkDataArray>
50 {
51  if (!capable_ || !cloud_)
52  return nullptr;
53 
55  scalars->SetNumberOfComponents (3);
56 
57  vtkIdType nr_points = cloud_->points.size ();
58  scalars->SetNumberOfTuples (nr_points);
59 
60  // Get a random color
61  unsigned char* colors = new unsigned char[nr_points * 3];
62 
63  // Color every point
64  for (vtkIdType cp = 0; cp < nr_points; ++cp)
65  {
66  colors[cp * 3 + 0] = static_cast<unsigned char> (r_);
67  colors[cp * 3 + 1] = static_cast<unsigned char> (g_);
68  colors[cp * 3 + 2] = static_cast<unsigned char> (b_);
69  }
70  scalars->SetArray (colors, 3 * nr_points, 0, vtkUnsignedCharArray::VTK_DATA_ARRAY_DELETE);
71  return scalars;
72 }
73 
74 ///////////////////////////////////////////////////////////////////////////////////////////
75 template <typename PointT> vtkSmartPointer<vtkDataArray>
77 {
78  if (!capable_ || !cloud_)
79  return nullptr;
80 
82  scalars->SetNumberOfComponents (3);
83 
84  vtkIdType nr_points = cloud_->points.size ();
85  scalars->SetNumberOfTuples (nr_points);
86 
87  // Get a random color
88  unsigned char* colors = new unsigned char[nr_points * 3];
89  double r, g, b;
91 
92  int r_ = static_cast<int> (pcl_lrint (r * 255.0)),
93  g_ = static_cast<int> (pcl_lrint (g * 255.0)),
94  b_ = static_cast<int> (pcl_lrint (b * 255.0));
95 
96  // Color every point
97  for (vtkIdType cp = 0; cp < nr_points; ++cp)
98  {
99  colors[cp * 3 + 0] = static_cast<unsigned char> (r_);
100  colors[cp * 3 + 1] = static_cast<unsigned char> (g_);
101  colors[cp * 3 + 2] = static_cast<unsigned char> (b_);
102  }
103  scalars->SetArray (colors, 3 * nr_points, 0, vtkUnsignedCharArray::VTK_DATA_ARRAY_DELETE);
104  return scalars;
105 }
106 
107 ///////////////////////////////////////////////////////////////////////////////////////////
108 template <typename PointT> void
110  const PointCloudConstPtr &cloud)
111 {
113  // Handle the 24-bit packed RGB values
114  field_idx_ = pcl::getFieldIndex<PointT> ("rgb", fields_);
115  if (field_idx_ != -1)
116  {
117  capable_ = true;
118  return;
119  }
120  else
121  {
122  field_idx_ = pcl::getFieldIndex<PointT> ("rgba", fields_);
123  if (field_idx_ != -1)
124  capable_ = true;
125  else
126  capable_ = false;
127  }
128 }
129 
130 ///////////////////////////////////////////////////////////////////////////////////////////
131 template <typename PointT> vtkSmartPointer<vtkDataArray>
133 {
134  if (!capable_ || !cloud_)
135  return nullptr;
136 
137  // Get the RGB field index
138  std::vector<pcl::PCLPointField> fields;
139  int rgba_index = -1;
140  rgba_index = pcl::getFieldIndex<PointT> ("rgb", fields);
141  if (rgba_index == -1)
142  rgba_index = pcl::getFieldIndex<PointT> ("rgba", fields);
143 
144  int rgba_offset = fields[rgba_index].offset;
145 
147  scalars->SetNumberOfComponents (3);
148 
149  vtkIdType nr_points = cloud_->points.size ();
150  scalars->SetNumberOfTuples (nr_points);
151  unsigned char* colors = scalars->GetPointer (0);
152 
153  int j = 0;
154  // If XYZ present, check if the points are invalid
155  int x_idx = -1;
156  for (std::size_t d = 0; d < fields_.size (); ++d)
157  if (fields_[d].name == "x")
158  x_idx = static_cast<int> (d);
159 
160  pcl::RGB rgb;
161  if (x_idx != -1)
162  {
163  // Color every point
164  for (vtkIdType cp = 0; cp < nr_points; ++cp)
165  {
166  // Copy the value at the specified field
167  if (!std::isfinite (cloud_->points[cp].x) ||
168  !std::isfinite (cloud_->points[cp].y) ||
169  !std::isfinite (cloud_->points[cp].z))
170  continue;
171 
172  memcpy (&rgb, (reinterpret_cast<const char *> (&cloud_->points[cp])) + rgba_offset, sizeof (pcl::RGB));
173  colors[j ] = rgb.r;
174  colors[j + 1] = rgb.g;
175  colors[j + 2] = rgb.b;
176  j += 3;
177  }
178  }
179  else
180  {
181  // Color every point
182  for (vtkIdType cp = 0; cp < nr_points; ++cp)
183  {
184  int idx = static_cast<int> (cp) * 3;
185  memcpy (&rgb, (reinterpret_cast<const char *> (&cloud_->points[cp])) + rgba_offset, sizeof (pcl::RGB));
186  colors[idx ] = rgb.r;
187  colors[idx + 1] = rgb.g;
188  colors[idx + 2] = rgb.b;
189  }
190  }
191  return scalars;
192 }
193 
194 ///////////////////////////////////////////////////////////////////////////////////////////
195 template <typename PointT>
197  pcl::visualization::PointCloudColorHandler<PointT>::PointCloudColorHandler (cloud)
198 {
199  // Check for the presence of the "H" field
200  field_idx_ = pcl::getFieldIndex<PointT> ("h", fields_);
201  if (field_idx_ == -1)
202  {
203  capable_ = false;
204  return;
205  }
206 
207  // Check for the presence of the "S" field
208  s_field_idx_ = pcl::getFieldIndex<PointT> ("s", fields_);
209  if (s_field_idx_ == -1)
210  {
211  capable_ = false;
212  return;
213  }
214 
215  // Check for the presence of the "V" field
216  v_field_idx_ = pcl::getFieldIndex<PointT> ("v", fields_);
217  if (v_field_idx_ == -1)
218  {
219  capable_ = false;
220  return;
221  }
222  capable_ = true;
223 }
224 
225 ///////////////////////////////////////////////////////////////////////////////////////////
226 template <typename PointT> vtkSmartPointer<vtkDataArray>
228 {
229  if (!capable_ || !cloud_)
230  return nullptr;
231 
233  scalars->SetNumberOfComponents (3);
234 
235  vtkIdType nr_points = cloud_->points.size ();
236  scalars->SetNumberOfTuples (nr_points);
237  unsigned char* colors = scalars->GetPointer (0);
238 
239  int idx = 0;
240  // If XYZ present, check if the points are invalid
241  int x_idx = -1;
242 
243  for (std::size_t d = 0; d < fields_.size (); ++d)
244  if (fields_[d].name == "x")
245  x_idx = static_cast<int> (d);
246 
247  if (x_idx != -1)
248  {
249  // Color every point
250  for (vtkIdType cp = 0; cp < nr_points; ++cp)
251  {
252  // Copy the value at the specified field
253  if (!std::isfinite (cloud_->points[cp].x) ||
254  !std::isfinite (cloud_->points[cp].y) ||
255  !std::isfinite (cloud_->points[cp].z))
256  continue;
257 
258  ///@todo do this with the point_types_conversion in common, first template it!
259 
260  float h = cloud_->points[cp].h;
261  float v = cloud_->points[cp].v;
262  float s = cloud_->points[cp].s;
263 
264  // Fill color data with HSV here:
265  // restrict the hue value to [0,360[
266  h = h < 0.0f ? h - (((int)h)/360 - 1)*360 : h - (((int)h)/360)*360;
267 
268  // restrict s and v to [0,1]
269  if (s > 1.0f) s = 1.0f;
270  if (s < 0.0f) s = 0.0f;
271  if (v > 1.0f) v = 1.0f;
272  if (v < 0.0f) v = 0.0f;
273 
274  if (s == 0.0f)
275  {
276  colors[idx] = colors[idx+1] = colors[idx+2] = v*255;
277  }
278  else
279  {
280  // calculate p, q, t from HSV-values
281  float a = h / 60;
282  int i = std::floor (a);
283  float f = a - i;
284  float p = v * (1 - s);
285  float q = v * (1 - s * f);
286  float t = v * (1 - s * (1 - f));
287 
288  switch (i)
289  {
290  case 0:
291  colors[idx] = v*255; colors[idx+1] = t*255; colors[idx+2] = p*255; break;
292  case 1:
293  colors[idx] = q*255; colors[idx+1] = v*255; colors[idx+2] = p*255; break;
294  case 2:
295  colors[idx] = p*255; colors[idx+1] = v*255; colors[idx+2] = t*255; break;
296  case 3:
297  colors[idx] = p*255; colors[idx+1] = q*255; colors[idx+2] = v*255; break;
298  case 4:
299  colors[idx] = t*255; colors[idx+1] = p*255; colors[idx+2] = v*255; break;
300  case 5:
301  colors[idx] = v*255; colors[idx+1] = p*255; colors[idx+2] = q*255; break;
302  }
303  }
304  idx +=3;
305  }
306  }
307  else
308  {
309  // Color every point
310  for (vtkIdType cp = 0; cp < nr_points; ++cp)
311  {
312  float h = cloud_->points[cp].h;
313  float v = cloud_->points[cp].v;
314  float s = cloud_->points[cp].s;
315 
316  // Fill color data with HSV here:
317  // restrict the hue value to [0,360[
318  h = h < 0.0f ? h - (((int)h)/360 - 1)*360 : h - (((int)h)/360)*360;
319 
320  // restrict s and v to [0,1]
321  if (s > 1.0f) s = 1.0f;
322  if (s < 0.0f) s = 0.0f;
323  if (v > 1.0f) v = 1.0f;
324  if (v < 0.0f) v = 0.0f;
325 
326  if (s == 0.0f)
327  {
328  colors[idx] = colors[idx+1] = colors[idx+2] = v*255;
329  }
330  else
331  {
332  // calculate p, q, t from HSV-values
333  float a = h / 60;
334  int i = std::floor (a);
335  float f = a - i;
336  float p = v * (1 - s);
337  float q = v * (1 - s * f);
338  float t = v * (1 - s * (1 - f));
339 
340  switch (i)
341  {
342  case 0:
343  colors[idx] = v*255; colors[idx+1] = t*255; colors[idx+2] = p*255; break;
344  case 1:
345  colors[idx] = q*255; colors[idx+1] = v*255; colors[idx+2] = p*255; break;
346  case 2:
347  colors[idx] = p*255; colors[idx+1] = v*255; colors[idx+2] = t*255; break;
348  case 3:
349  colors[idx] = p*255; colors[idx+1] = q*255; colors[idx+2] = v*255; break;
350  case 4:
351  colors[idx] = t*255; colors[idx+1] = p*255; colors[idx+2] = v*255; break;
352  case 5:
353  colors[idx] = v*255; colors[idx+1] = p*255; colors[idx+2] = q*255; break;
354  }
355  }
356  idx +=3;
357  }
358  }
359  return scalars;
360 }
361 
362 ///////////////////////////////////////////////////////////////////////////////////////////
363 template <typename PointT> void
365  const PointCloudConstPtr &cloud)
366 {
368  field_idx_ = pcl::getFieldIndex<PointT> (field_name_, fields_);
369  if (field_idx_ != -1)
370  capable_ = true;
371  else
372  capable_ = false;
373 }
374 
375 ///////////////////////////////////////////////////////////////////////////////////////////
376 template <typename PointT> vtkSmartPointer<vtkDataArray>
378 {
379  if (!capable_ || !cloud_)
380  return nullptr;
381 
382  auto scalars = vtkSmartPointer<vtkFloatArray>::New ();
383  scalars->SetNumberOfComponents (1);
384 
385  vtkIdType nr_points = cloud_->points.size ();
386  scalars->SetNumberOfTuples (nr_points);
387 
388  using FieldList = typename pcl::traits::fieldList<PointT>::type;
389 
390  float* colors = new float[nr_points];
391  float field_data;
392 
393  int j = 0;
394  // If XYZ present, check if the points are invalid
395  int x_idx = -1;
396  for (std::size_t d = 0; d < fields_.size (); ++d)
397  if (fields_[d].name == "x")
398  x_idx = static_cast<int> (d);
399 
400  if (x_idx != -1)
401  {
402  // Color every point
403  for (vtkIdType cp = 0; cp < nr_points; ++cp)
404  {
405  // Copy the value at the specified field
406  if (!std::isfinite (cloud_->points[cp].x) || !std::isfinite (cloud_->points[cp].y) || !std::isfinite (cloud_->points[cp].z))
407  continue;
408 
409  const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&cloud_->points[cp]);
410  memcpy (&field_data, pt_data + fields_[field_idx_].offset, pcl::getFieldSize (fields_[field_idx_].datatype));
411 
412  colors[j] = field_data;
413  j++;
414  }
415  }
416  else
417  {
418  // Color every point
419  for (vtkIdType cp = 0; cp < nr_points; ++cp)
420  {
421  const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&cloud_->points[cp]);
422  memcpy (&field_data, pt_data + fields_[field_idx_].offset, pcl::getFieldSize (fields_[field_idx_].datatype));
423 
424  if (!std::isfinite (field_data))
425  continue;
426 
427  colors[j] = field_data;
428  j++;
429  }
430  }
431  scalars->SetArray (colors, j, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
432  return scalars;
433 }
434 
435 ///////////////////////////////////////////////////////////////////////////////////////////
436 template <typename PointT> void
438  const PointCloudConstPtr &cloud)
439 {
441  // Handle the 24-bit packed RGBA values
442  field_idx_ = pcl::getFieldIndex<PointT> ("rgba", fields_);
443  if (field_idx_ != -1)
444  capable_ = true;
445  else
446  capable_ = false;
447 }
448 
449 ///////////////////////////////////////////////////////////////////////////////////////////
450 template <typename PointT> vtkSmartPointer<vtkDataArray>
452 {
453  if (!capable_ || !cloud_)
454  return nullptr;
455 
457  scalars->SetNumberOfComponents (4);
458 
459  vtkIdType nr_points = cloud_->points.size ();
460  scalars->SetNumberOfTuples (nr_points);
461  unsigned char* colors = scalars->GetPointer (0);
462 
463  int j = 0;
464  // If XYZ present, check if the points are invalid
465  int x_idx = -1;
466  for (std::size_t d = 0; d < fields_.size (); ++d)
467  if (fields_[d].name == "x")
468  x_idx = static_cast<int> (d);
469 
470  if (x_idx != -1)
471  {
472  // Color every point
473  for (vtkIdType cp = 0; cp < nr_points; ++cp)
474  {
475  // Copy the value at the specified field
476  if (!std::isfinite (cloud_->points[cp].x) ||
477  !std::isfinite (cloud_->points[cp].y) ||
478  !std::isfinite (cloud_->points[cp].z))
479  continue;
480 
481  colors[j ] = cloud_->points[cp].r;
482  colors[j + 1] = cloud_->points[cp].g;
483  colors[j + 2] = cloud_->points[cp].b;
484  colors[j + 3] = cloud_->points[cp].a;
485  j += 4;
486  }
487  }
488  else
489  {
490  // Color every point
491  for (vtkIdType cp = 0; cp < nr_points; ++cp)
492  {
493  int idx = static_cast<int> (cp) * 4;
494  colors[idx ] = cloud_->points[cp].r;
495  colors[idx + 1] = cloud_->points[cp].g;
496  colors[idx + 2] = cloud_->points[cp].b;
497  colors[idx + 3] = cloud_->points[cp].a;
498  }
499  }
500  return scalars;
501 }
502 
503 ///////////////////////////////////////////////////////////////////////////////////////////
504 template <typename PointT> void
506 {
508  field_idx_ = pcl::getFieldIndex<PointT> ("label", fields_);
509  if (field_idx_ != -1)
510  {
511  capable_ = true;
512  return;
513  }
514 }
515 
516 ///////////////////////////////////////////////////////////////////////////////////////////
517 template <typename PointT> vtkSmartPointer<vtkDataArray>
519 {
520  if (!capable_ || !cloud_)
521  return nullptr;
522 
524  scalars->SetNumberOfComponents (3);
525 
526  vtkIdType nr_points = cloud_->points.size ();
527  scalars->SetNumberOfTuples (nr_points);
528  unsigned char* colors = scalars->GetPointer (0);
529 
530 
531  std::map<std::uint32_t, pcl::RGB> colormap;
532  if (!static_mapping_)
533  {
534  std::set<std::uint32_t> labels;
535  // First pass: find unique labels
536  for (vtkIdType i = 0; i < nr_points; ++i)
537  labels.insert (cloud_->points[i].label);
538 
539  // Assign Glasbey colors in ascending order of labels
540  std::size_t color = 0;
541  for (std::set<std::uint32_t>::iterator iter = labels.begin (); iter != labels.end (); ++iter, ++color)
542  colormap[*iter] = GlasbeyLUT::at (color % GlasbeyLUT::size ());
543  }
544 
545  int j = 0;
546  for (vtkIdType cp = 0; cp < nr_points; ++cp)
547  {
548  if (pcl::isFinite (cloud_->points[cp]))
549  {
550  const pcl::RGB& color = static_mapping_ ? GlasbeyLUT::at (cloud_->points[cp].label % GlasbeyLUT::size ()) : colormap[cloud_->points[cp].label];
551  colors[j ] = color.r;
552  colors[j + 1] = color.g;
553  colors[j + 2] = color.b;
554  j += 3;
555  }
556  }
557 
558  return scalars;
559 }
560 
561 #endif // PCL_POINT_CLOUD_COLOR_HANDLERS_IMPL_HPP_
562 
#define pcl_lrint(x)
Definition: pcl_macros.h:168
virtual void setInputCloud(const PointCloudConstPtr &cloud)
Set the input cloud to be used.
bool isFinite(const PointT &pt)
Tests if the 3D components of a point are all finite param[in] pt point to be tested return true if f...
Definition: point_tests.h:55
static RGB at(std::size_t color_id)
Get a color from the lookup table with a given id.
This file defines compatibility wrappers for low level I/O functions.
Definition: convolution.h:45
virtual void setInputCloud(const PointCloudConstPtr &cloud)
Set the input cloud to be used.
virtual void setInputCloud(const PointCloudConstPtr &cloud)
Set the input cloud to be used.
vtkSmartPointer< vtkDataArray > getColor() const override
Obtain the actual color for the input dataset as a VTK data array.
PointCloudColorHandlerHSVField(const PointCloudConstPtr &cloud)
Constructor.
static std::size_t size()
Get the number of colors in the lookup table.
Base Handler class for PointCloud colors.
PCL_EXPORTS void getRandomColors(double &r, double &g, double &b, double min=0.2, double max=2.8)
Get (good) random values for R/G/B.
std::vector< pcl::PCLPointField > fields_
The list of fields available for this PointCloud.
A structure representing RGB color information.
virtual void setInputCloud(const PointCloudConstPtr &cloud)
Set the input cloud to be used.
vtkSmartPointer< vtkDataArray > getColor() const override
Obtain the actual color for the input dataset as a VTK data array.
vtkSmartPointer< vtkDataArray > getColor() const override
Obtain the actual color for the input dataset as a VTK data array.
vtkSmartPointer< vtkDataArray > getColor() const override
Obtain the actual color for the input dataset as a VTK data array.
vtkSmartPointer< vtkDataArray > getColor() const override
Obtain the actual color for the input dataset as a VTK data array.
int getFieldSize(const int datatype)
Obtains the size of a specific field data type in bytes.
Definition: io.h:152
vtkSmartPointer< vtkDataArray > getColor() const override
Obtain the actual color for the input dataset as a VTK data array.
PointCloudConstPtr cloud_
A pointer to the input dataset.
int field_idx_
The index of the field holding the data that represents the color.
A point structure representing Euclidean xyz coordinates, and the RGB color.
virtual void setInputCloud(const PointCloudConstPtr &cloud)
Set the input cloud to be used.
bool capable_
True if this handler is capable of handling the input data, false otherwise.
vtkSmartPointer< vtkDataArray > getColor() const override
Obtain the actual color for the input dataset as a VTK data array.
Defines all the PCL and non-PCL macros used.