Point Cloud Library (PCL)  1.15.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 #pragma once
39 
40 #include <set>
41 #include <map>
42 #include <stdexcept>
43 
44 #include <pcl/pcl_macros.h>
45 #include <pcl/common/colors.h>
46 #include <pcl/common/io.h> // for getFieldIndex
47 #include <pcl/common/point_tests.h> // for pcl::isFinite
48 
49 
50 namespace pcl
51 {
52 
53 namespace visualization
54 {
55 
56 template <typename PointT> vtkSmartPointer<vtkDataArray>
58 {
59  if (!capable_ || !cloud_)
60  return nullptr;
61 
63  scalars->SetNumberOfComponents (3);
64 
65  vtkIdType nr_points = cloud_->size ();
66  scalars->SetNumberOfTuples (nr_points);
67 
68  // Get a random color
69  unsigned char* colors = new unsigned char[nr_points * 3];
70 
71  // Color every point
72  for (vtkIdType cp = 0; cp < nr_points; ++cp)
73  {
74  colors[cp * 3 + 0] = static_cast<unsigned char> (r_);
75  colors[cp * 3 + 1] = static_cast<unsigned char> (g_);
76  colors[cp * 3 + 2] = static_cast<unsigned char> (b_);
77  }
78  scalars->SetArray (colors, 3 * nr_points, 0, vtkUnsignedCharArray::VTK_DATA_ARRAY_DELETE);
79  return scalars;
80 }
81 
82 
83 template <typename PointT> vtkSmartPointer<vtkDataArray>
85 {
86  if (!capable_ || !cloud_)
87  return nullptr;
88 
90  scalars->SetNumberOfComponents (3);
91 
92  vtkIdType nr_points = cloud_->size ();
93  scalars->SetNumberOfTuples (nr_points);
94 
95  // Get a random color
96  unsigned char* colors = new unsigned char[nr_points * 3];
97  double r, g, b;
99 
100  int r_ = static_cast<int> (pcl_lrint (r * 255.0)),
101  g_ = static_cast<int> (pcl_lrint (g * 255.0)),
102  b_ = static_cast<int> (pcl_lrint (b * 255.0));
103 
104  // Color every point
105  for (vtkIdType cp = 0; cp < nr_points; ++cp)
106  {
107  colors[cp * 3 + 0] = static_cast<unsigned char> (r_);
108  colors[cp * 3 + 1] = static_cast<unsigned char> (g_);
109  colors[cp * 3 + 2] = static_cast<unsigned char> (b_);
110  }
111  scalars->SetArray (colors, 3 * nr_points, 0, vtkUnsignedCharArray::VTK_DATA_ARRAY_DELETE);
112  return scalars;
113 }
114 
115 
116 template <typename PointT> void
118  const PointCloudConstPtr &cloud)
119 {
121  // Handle the 24-bit packed RGB values
122  field_idx_ = pcl::getFieldIndex<PointT> ("rgb", fields_);
123  if (field_idx_ != -1)
124  {
125  capable_ = true;
126  return;
127  }
128  else
129  {
130  field_idx_ = pcl::getFieldIndex<PointT> ("rgba", fields_);
131  if (field_idx_ != -1)
132  capable_ = true;
133  else
134  capable_ = false;
135  }
136 }
137 
138 
139 template <typename PointT> vtkSmartPointer<vtkDataArray>
141 {
142  if (!capable_ || !cloud_)
143  return nullptr;
144 
145  // Get the RGB field index
146  std::vector<pcl::PCLPointField> fields;
147  int rgba_index = -1;
148  rgba_index = pcl::getFieldIndex<PointT> ("rgb", fields);
149  if (rgba_index == -1)
150  rgba_index = pcl::getFieldIndex<PointT> ("rgba", fields);
151 
152  int rgba_offset = fields[rgba_index].offset;
153 
155  scalars->SetNumberOfComponents (3);
156 
157  vtkIdType nr_points = cloud_->size ();
158  scalars->SetNumberOfTuples (nr_points);
159  unsigned char* colors = scalars->GetPointer (0);
160 
161  // If XYZ present, check if the points are invalid
162  int x_idx = -1;
163  for (std::size_t d = 0; d < fields_.size (); ++d)
164  if (fields_[d].name == "x")
165  x_idx = static_cast<int> (d);
166 
167  pcl::RGB rgb;
168  if (x_idx != -1)
169  {
170  int j = 0;
171  // Color every point
172  for (vtkIdType cp = 0; cp < nr_points; ++cp)
173  {
174  // Copy the value at the specified field
175  if (!pcl::isXYZFinite((*cloud_)[cp]))
176  continue;
177  memcpy (&rgb, (reinterpret_cast<const char *> (&(*cloud_)[cp])) + rgba_offset, sizeof (pcl::RGB));
178  colors[j ] = rgb.r;
179  colors[j + 1] = rgb.g;
180  colors[j + 2] = rgb.b;
181  j += 3;
182  }
183  }
184  else
185  {
186  // Color every point
187  for (vtkIdType cp = 0; cp < nr_points; ++cp)
188  {
189  int idx = static_cast<int> (cp) * 3;
190  memcpy (&rgb, (reinterpret_cast<const char *> (&(*cloud_)[cp])) + rgba_offset, sizeof (pcl::RGB));
191  colors[idx ] = rgb.r;
192  colors[idx + 1] = rgb.g;
193  colors[idx + 2] = rgb.b;
194  }
195  }
196  return scalars;
197 }
198 
199 
200 template <typename PointT>
203 {
204  // Check for the presence of the "H" field
205  field_idx_ = pcl::getFieldIndex<PointT> ("h", fields_);
206  if (field_idx_ == -1)
207  {
208  capable_ = false;
209  return;
210  }
211 
212  // Check for the presence of the "S" field
213  s_field_idx_ = pcl::getFieldIndex<PointT> ("s", fields_);
214  if (s_field_idx_ == -1)
215  {
216  capable_ = false;
217  return;
218  }
219 
220  // Check for the presence of the "V" field
221  v_field_idx_ = pcl::getFieldIndex<PointT> ("v", fields_);
222  if (v_field_idx_ == -1)
223  {
224  capable_ = false;
225  return;
226  }
227  capable_ = true;
228 }
229 
230 
231 template <typename PointT> vtkSmartPointer<vtkDataArray>
233 {
234  if (!capable_ || !cloud_)
235  return nullptr;
236 
238  scalars->SetNumberOfComponents (3);
239 
240  vtkIdType nr_points = cloud_->size ();
241  scalars->SetNumberOfTuples (nr_points);
242  unsigned char* colors = scalars->GetPointer (0);
243 
244  int idx = 0;
245  // If XYZ present, check if the points are invalid
246  int x_idx = -1;
247 
248  for (std::size_t d = 0; d < fields_.size (); ++d)
249  if (fields_[d].name == "x")
250  x_idx = static_cast<int> (d);
251 
252  if (x_idx != -1)
253  {
254  // Color every point
255  for (vtkIdType cp = 0; cp < nr_points; ++cp)
256  {
257  // Copy the value at the specified field
258  if (!pcl::isXYZFinite((*cloud_)[cp]))
259  continue;
260 
261  ///@todo do this with the point_types_conversion in common, first template it!
262 
263  float h = (*cloud_)[cp].h;
264  float v = (*cloud_)[cp].v;
265  float s = (*cloud_)[cp].s;
266 
267  // Fill color data with HSV here:
268  // restrict the hue value to [0,360[
269  h = h < 0.0f ? h - (((int)h)/360 - 1)*360 : h - (((int)h)/360)*360;
270 
271  // restrict s and v to [0,1]
272  if (s > 1.0f) s = 1.0f;
273  if (s < 0.0f) s = 0.0f;
274  if (v > 1.0f) v = 1.0f;
275  if (v < 0.0f) v = 0.0f;
276 
277  if (s == 0.0f)
278  {
279  colors[idx] = colors[idx+1] = colors[idx+2] = v*255;
280  }
281  else
282  {
283  // calculate p, q, t from HSV-values
284  float a = h / 60;
285  int i = std::floor (a);
286  float f = a - i;
287  float p = v * (1 - s);
288  float q = v * (1 - s * f);
289  float t = v * (1 - s * (1 - f));
290 
291  switch (i)
292  {
293  case 0:
294  colors[idx] = v*255; colors[idx+1] = t*255; colors[idx+2] = p*255; break;
295  case 1:
296  colors[idx] = q*255; colors[idx+1] = v*255; colors[idx+2] = p*255; break;
297  case 2:
298  colors[idx] = p*255; colors[idx+1] = v*255; colors[idx+2] = t*255; break;
299  case 3:
300  colors[idx] = p*255; colors[idx+1] = q*255; colors[idx+2] = v*255; break;
301  case 4:
302  colors[idx] = t*255; colors[idx+1] = p*255; colors[idx+2] = v*255; break;
303  case 5:
304  colors[idx] = v*255; colors[idx+1] = p*255; colors[idx+2] = q*255; break;
305  }
306  }
307  idx +=3;
308  }
309  }
310  else
311  {
312  // Color every point
313  for (vtkIdType cp = 0; cp < nr_points; ++cp)
314  {
315  float h = (*cloud_)[cp].h;
316  float v = (*cloud_)[cp].v;
317  float s = (*cloud_)[cp].s;
318 
319  // Fill color data with HSV here:
320  // restrict the hue value to [0,360[
321  h = h < 0.0f ? h - (((int)h)/360 - 1)*360 : h - (((int)h)/360)*360;
322 
323  // restrict s and v to [0,1]
324  if (s > 1.0f) s = 1.0f;
325  if (s < 0.0f) s = 0.0f;
326  if (v > 1.0f) v = 1.0f;
327  if (v < 0.0f) v = 0.0f;
328 
329  if (s == 0.0f)
330  {
331  colors[idx] = colors[idx+1] = colors[idx+2] = v*255;
332  }
333  else
334  {
335  // calculate p, q, t from HSV-values
336  float a = h / 60;
337  int i = std::floor (a);
338  float f = a - i;
339  float p = v * (1 - s);
340  float q = v * (1 - s * f);
341  float t = v * (1 - s * (1 - f));
342 
343  switch (i)
344  {
345  case 0:
346  colors[idx] = v*255; colors[idx+1] = t*255; colors[idx+2] = p*255; break;
347  case 1:
348  colors[idx] = q*255; colors[idx+1] = v*255; colors[idx+2] = p*255; break;
349  case 2:
350  colors[idx] = p*255; colors[idx+1] = v*255; colors[idx+2] = t*255; break;
351  case 3:
352  colors[idx] = p*255; colors[idx+1] = q*255; colors[idx+2] = v*255; break;
353  case 4:
354  colors[idx] = t*255; colors[idx+1] = p*255; colors[idx+2] = v*255; break;
355  case 5:
356  colors[idx] = v*255; colors[idx+1] = p*255; colors[idx+2] = q*255; break;
357  }
358  }
359  idx +=3;
360  }
361  }
362  return scalars;
363 }
364 
365 template <typename PointT> void
367  const PointCloudConstPtr &cloud)
368 {
370  // Handle the 24-bit packed RGBA values
371  field_idx_ = pcl::getFieldIndex<PointT> ("rgba", fields_);
372  if (field_idx_ != -1)
373  capable_ = true;
374  else
375  capable_ = false;
376 }
377 
378 
379 template <typename PointT> vtkSmartPointer<vtkDataArray>
381 {
382  if (!capable_ || !cloud_)
383  return nullptr;
384 
386  scalars->SetNumberOfComponents (4);
387 
388  vtkIdType nr_points = cloud_->size ();
389  scalars->SetNumberOfTuples (nr_points);
390  unsigned char* colors = scalars->GetPointer (0);
391 
392  // If XYZ present, check if the points are invalid
393  int x_idx = -1;
394  for (std::size_t d = 0; d < fields_.size (); ++d)
395  if (fields_[d].name == "x")
396  x_idx = static_cast<int> (d);
397 
398  if (x_idx != -1)
399  {
400  int j = 0;
401  // Color every point
402  for (vtkIdType cp = 0; cp < nr_points; ++cp)
403  {
404  // Copy the value at the specified field
405  if (!pcl::isXYZFinite((*cloud_)[cp]))
406  continue;
407 
408  colors[j ] = (*cloud_)[cp].r;
409  colors[j + 1] = (*cloud_)[cp].g;
410  colors[j + 2] = (*cloud_)[cp].b;
411  colors[j + 3] = (*cloud_)[cp].a;
412  j += 4;
413  }
414  }
415  else
416  {
417  // Color every point
418  for (vtkIdType cp = 0; cp < nr_points; ++cp)
419  {
420  int idx = static_cast<int> (cp) * 4;
421  colors[idx ] = (*cloud_)[cp].r;
422  colors[idx + 1] = (*cloud_)[cp].g;
423  colors[idx + 2] = (*cloud_)[cp].b;
424  colors[idx + 3] = (*cloud_)[cp].a;
425  }
426  }
427  return scalars;
428 }
429 
430 
431 template <typename PointT> void
433 {
435  field_idx_ = pcl::getFieldIndex<PointT> ("label", fields_);
436  if (field_idx_ != -1)
437  {
438  capable_ = true;
439  return;
440  }
441 }
442 
443 
444 template <typename PointT> vtkSmartPointer<vtkDataArray>
446 {
447  if (!capable_ || !cloud_)
448  return nullptr;
449 
451  scalars->SetNumberOfComponents (3);
452 
453  vtkIdType nr_points = cloud_->size ();
454  scalars->SetNumberOfTuples (nr_points);
455  unsigned char* colors = scalars->GetPointer (0);
456 
457 
458  std::map<std::uint32_t, pcl::RGB> colormap;
459  if (!static_mapping_)
460  {
461  std::set<std::uint32_t> labels;
462  // First pass: find unique labels
463  for (vtkIdType i = 0; i < nr_points; ++i)
464  labels.insert ((*cloud_)[i].label);
465 
466  // Assign Glasbey colors in ascending order of labels
467  std::size_t color = 0;
468  for (std::set<std::uint32_t>::iterator iter = labels.begin (); iter != labels.end (); ++iter, ++color)
469  colormap[*iter] = GlasbeyLUT::at (color % GlasbeyLUT::size ());
470  }
471 
472  int j = 0;
473  for (vtkIdType cp = 0; cp < nr_points; ++cp)
474  {
475  if (pcl::isFinite ((*cloud_)[cp]))
476  {
477  const pcl::RGB& color = static_mapping_ ? GlasbeyLUT::at ((*cloud_)[cp].label % GlasbeyLUT::size ()) : colormap[(*cloud_)[cp].label];
478  colors[j ] = color.r;
479  colors[j + 1] = color.g;
480  colors[j + 2] = color.b;
481  j += 3;
482  }
483  }
484 
485  return scalars;
486 }
487 
488 // ----
489 // template specializations for PointCloud and PCLPointCloud2 to access certain
490 // data from PointCloudColorHandlerGenericField without needing to know the
491 // cloud type
492 
493 template <typename CloudT> inline int getPointStep(const CloudT&)
494 {
495  return sizeof(typename CloudT::PointType);
496 }
497 
498 template <> inline int
499 getPointStep<pcl::PCLPointCloud2>(const pcl::PCLPointCloud2& cloud) {
500  return cloud.point_step;
501 }
502 
503 // Get cloud data blob
504 template <typename CloudT> inline const std::uint8_t* getCloudData(const CloudT& cloud)
505 {
506  return reinterpret_cast<const std::uint8_t*>(cloud.data());
507 }
508 
509 template <> inline const std::uint8_t* getCloudData<pcl::PCLPointCloud2>(const typename pcl::PCLPointCloud2& cloud) {
510  return cloud.data.data();
511 }
512 
513 // copy of pcl::getFieldIndex() from impl/io.hpp, without the unused template
514 // parameter
515 static int getFieldIndex(const std::string& field_name,
516  const std::vector<pcl::PCLPointField>& fields)
517 {
518  const auto result =
519  std::find_if(fields.begin(), fields.end(), [&field_name](const auto& field) {
520  return field.name == field_name;
521  });
522  if (result == fields.end()) {
523  return -1;
524  }
525  return std::distance(fields.begin(), result);
526 }
527 
528 // Cloud type agnostic isXYZFinite wrappers to check if pointcloud or PCLPointCloud2 at
529 // given index is finite
530 template <typename CloudT> inline bool isXYZFiniteAt(const CloudT& cloud, int index)
531 {
532  return pcl::isXYZFinite(cloud.at(index));
533 }
534 
535 template <> inline bool isXYZFiniteAt(const PCLPointCloud2& cloud, int index)
536 {
537  // get x,y,z field indices
538  const auto x_field_idx = getFieldIndex("x", cloud.fields);
539  const auto y_field_idx = getFieldIndex("y", cloud.fields);
540  const auto z_field_idx = getFieldIndex("z", cloud.fields);
541 
542  // if any missing, error
543  if (x_field_idx == -1 || y_field_idx == -1 || z_field_idx == -1) {
544  throw std::out_of_range("isXYZFiniteAt(): input cloud missing at least one of x, y, z fields");
545  }
546  // get x,y,z field values
547  const auto position_x = index * cloud.point_step + cloud.fields[x_field_idx].offset;
548  const auto position_y = index * cloud.point_step + cloud.fields[y_field_idx].offset;
549  const auto position_z = index * cloud.point_step + cloud.fields[z_field_idx].offset;
550  if (cloud.data.size () >= (position_x + sizeof(float)) &&
551  cloud.data.size () >= (position_y + sizeof(float)) &&
552  cloud.data.size () >= (position_z + sizeof(float))) {
553  const float x = *reinterpret_cast<const float*>(&cloud.data[position_x]);
554  const float y = *reinterpret_cast<const float*>(&cloud.data[position_y]);
555  const float z = *reinterpret_cast<const float*>(&cloud.data[position_z]);
556  return isXYZFinite(PointXYZ(x, y, z));
557  } else {
558  // the last of the three is out of range
559  throw std::out_of_range("isXYZFiniteAt(): requested for index larger than number of points");
560  }
561 }
562 
563 template <typename PointT>
565  const PointCloudConstPtr& cloud, const std::string& field_name)
566 : PointCloudColorHandler<PointT>(cloud), field_name_(field_name)
567 {
568  this->setInputCloud(cloud);
569 }
570 
571 template <typename PointT>
573  : PointCloudColorHandler<PointT>(), field_name_(field_name) {}
574 
576  const PointCloudConstPtr& cloud)
577 {
579  this->fields_ = getFields(*cloud);
580  this->field_idx_ = getFieldIndex(field_name_, this->fields_);
581  this->capable_ = this->field_idx_ != -1;
582 }
583 
584 template <typename PointT> std::string PointCloudColorHandlerGenericField<PointT>::getFieldName() const
585 {
586  return field_name_;
587 }
588 
590 {
591  if (!this->capable_ || !this->cloud_) {
592  return nullptr;
593  }
594 
595  auto scalars = vtkSmartPointer<vtkFloatArray>::New();
596  scalars->SetNumberOfComponents(1);
597 
598  const vtkIdType nr_points = this->cloud_->width * this->cloud_->height;
599  scalars->SetNumberOfTuples(nr_points);
600 
601  // per-point color as a float value. vtk turns that into rgb somehow
602  float* colors = new float[nr_points];
603 
604  // Find X channel
605  int x_channel_idx = -1;
606  for (std::size_t channel_idx = 0; channel_idx < this->fields_.size(); ++channel_idx) {
607  if (this->fields_[channel_idx].name == "x") {
608  x_channel_idx = static_cast<int>(channel_idx);
609  }
610  }
611 
612  size_t point_offset = this->fields_[this->field_idx_].offset;
613  const int point_step = getPointStep<PointCloud>(*this->cloud_);
614  const std::uint8_t* p_data = getCloudData<PointCloud>(*this->cloud_);
615  const std::uint8_t field_type = this->fields_[this->field_idx_].datatype;
616 
617  // current index into colors array
618  int pt_idx = 0;
619 
620  // Color every point
621  for (vtkIdType cp = 0; cp < nr_points; ++cp, point_offset += point_step) {
622 
623  if (x_channel_idx != -1 && !isXYZFiniteAt(*this->cloud_, cp)) {
624  // no x channel in the cloud, or point is infinite
625  continue;
626  } else {
627  // point data at index, field offset already baked into point_offset
628  const std::uint8_t* pt_data = &p_data[point_offset];
629 
630  colors[pt_idx] = point_field_as<float>(pt_data, field_type);
631 
632  }
633 
634  ++pt_idx;
635  }
636 
637  scalars->SetArray(colors, pt_idx, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
638  return scalars;
639 }
640 
641 } // namespace visualization
642 } // namespace pcl
static std::size_t size()
Get the number of colors in the lookup table.
static RGB at(std::size_t color_id)
Get a color from the lookup table with a given id.
vtkSmartPointer< vtkDataArray > getColor() const override
Obtain the actual color for the input dataset as a VTK data array.
PointCloudColorHandlerGenericField(const PointCloudConstPtr &cloud, const std::string &field_name)
constructor
std::string getFieldName() const override
Get the name of the field used.
vtkSmartPointer< vtkDataArray > getColor() const override
Obtain the actual color for the input dataset as a VTK data array.
void setInputCloud(const PointCloudConstPtr &cloud)
Set the input cloud to be used.
PointCloudColorHandlerHSVField(const PointCloudConstPtr &cloud)
Constructor.
vtkSmartPointer< vtkDataArray > getColor() const override
Obtain the actual color for the input dataset as a VTK data array.
Base Handler class for PointCloud colors.
bool capable_
True if this handler is capable of handling the input data, false otherwise.
virtual void setInputCloud(const PointCloudConstPtr &cloud)
Set the input cloud to be used.
std::vector< pcl::PCLPointField > fields_
The list of fields available for this PointCloud.
int field_idx_
The index of the field holding the data that represents the color.
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.
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.
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.
float distance(const PointT &p1, const PointT &p2)
Definition: geometry.h:60
int getPointStep(const CloudT &)
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.
const std::uint8_t * getCloudData(const CloudT &cloud)
bool isXYZFiniteAt(const CloudT &cloud, int index)
static int getFieldIndex(const std::string &field_name, const std::vector< pcl::PCLPointField > &fields)
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
void getFields(const pcl::PointCloud< PointT > &, std::vector< pcl::PCLPointField > &fields)
Definition: io.hpp:83
constexpr bool isXYZFinite(const PointT &) noexcept
Definition: point_tests.h:125
Defines all the PCL and non-PCL macros used.
#define pcl_lrint(x)
Definition: pcl_macros.h:254
std::vector<::pcl::PCLPointField > fields
std::vector< std::uint8_t > data
A point structure representing Euclidean xyz coordinates.
A point structure representing Euclidean xyz coordinates, and the RGB color.
A structure representing RGB color information.