39
39
40
40
#include < set>
41
41
#include < map>
42
+ #include < stdexcept>
42
43
43
44
#include < pcl/pcl_macros.h>
44
45
#include < pcl/common/colors.h>
@@ -491,29 +492,40 @@ PointCloudColorHandlerLabelField<PointT>::getColor () const
491
492
492
493
// Get point fields from cloud. Could not get it to work with existing
493
494
// pcl::getFields
494
- inline template <typename CloudT> std::vector<pcl::PCLPointField>
495
+ template <typename CloudT> inline std::vector<pcl::PCLPointField>
495
496
getFields (const CloudT& cloud)
496
497
{
497
498
return pcl::getFields<typename CloudT::PointType>();
498
499
}
499
500
501
+ template <> inline std::vector<pcl::PCLPointField>
502
+ getFields<pcl::PCLPointCloud2>(const pcl::PCLPointCloud2& cloud) {
503
+ return cloud.fields ;
504
+ }
505
+
506
+
500
507
// Get point step. Does not directly exist in pcl::PointCloud
501
- inline template <typename CloudT> int getPointStep (const CloudT&)
508
+ template <typename CloudT> inline int getPointStep (const CloudT&)
502
509
{
503
510
return sizeof (typename CloudT::PointType);
504
511
}
505
512
513
+ template <> inline int
514
+ getPointStep<pcl::PCLPointCloud2>(const pcl::PCLPointCloud2& cloud) {
515
+ return cloud.point_step ;
516
+ }
517
+
506
518
// Get cloud data blob
507
- inline template <typename CloudT> const std::uint8_t * getCloudData (const CloudT& cloud)
519
+ template <typename CloudT> inline const std::uint8_t * getCloudData (const CloudT& cloud)
508
520
{
509
521
return reinterpret_cast <const std::uint8_t *>(cloud.points .data ());
510
522
}
511
523
512
- inline const std::uint8_t * getCloudData (const typename pcl::PCLPointCloud2& cloud)
513
- {
524
+ template <> inline const std::uint8_t * getCloudData<pcl::PCLPointCloud2>(const typename pcl::PCLPointCloud2& cloud) {
514
525
return reinterpret_cast <const std::uint8_t *>(cloud.data .data ());
515
526
}
516
527
528
+
517
529
// copy of pcl::getFieldIndex() from impl/io.hpp, without the unused template
518
530
// parameter
519
531
static int getFieldIndex (const std::string& field_name,
@@ -529,6 +541,46 @@ static int getFieldIndex(const std::string& field_name,
529
541
return std::distance (fields.begin (), result);
530
542
}
531
543
544
+ // Cloud type agnostic isXYZFinite wrappers to check if pointcloud or PCLPointCloud2 at
545
+ // given index is finite
546
+ template <typename CloudT> inline bool isXYZFiniteAt (const CloudT& cloud, int index)
547
+ {
548
+ return pcl::isXYZFinite (cloud.at (index));
549
+ }
550
+
551
+ template <> inline bool isXYZFiniteAt (const PCLPointCloud2& cloud, int index)
552
+ {
553
+ // get x,y,z field indices
554
+ const auto x_field_idx = getFieldIndex (" x" , cloud.fields );
555
+ const auto y_field_idx = getFieldIndex (" y" , cloud.fields );
556
+ const auto z_field_idx = getFieldIndex (" z" , cloud.fields );
557
+
558
+ // if any missing, error
559
+ if (x_field_idx == -1 || y_field_idx == -1 || z_field_idx == -1 ) {
560
+ throw std::out_of_range (" getXData(): input cloud missing at least one of x, y, z fields" );
561
+ }
562
+ // get x,y,z field values
563
+ const auto position_x = index * cloud.point_step + cloud.fields [x_field_idx].offset ;
564
+ const auto position_y = index * cloud.point_step + cloud.fields [y_field_idx].offset ;
565
+ const auto position_z = index * cloud.point_step + cloud.fields [z_field_idx].offset ;
566
+ if (cloud.data .size () >= (position_x + sizeof (float )) &&
567
+ cloud.data .size () >= (position_y + sizeof (float )) &&
568
+ cloud.data .size () >= (position_z + sizeof (float ))) {
569
+ const float x = *reinterpret_cast <const float *>(cloud.data [position_x]);
570
+ const float y = *reinterpret_cast <const float *>(cloud.data [position_y]);
571
+ const float z = *reinterpret_cast <const float *>(cloud.data [position_z]);
572
+ return isXYZFinite (PointXYZ (x, y, z));
573
+ } else {
574
+ // the last of the three is out of range
575
+ throw std::out_of_range (" getXData(): requested for index larger than number of points" );
576
+ }
577
+ }
578
+
579
+ inline const std::uint8_t * getCloudData (const typename pcl::PCLPointCloud2& cloud)
580
+ {
581
+ return reinterpret_cast <const std::uint8_t *>(cloud.data .data ());
582
+ }
583
+
532
584
template <typename DType, typename RType> RType reinterpret_and_cast (const std::uint8_t * p)
533
585
{
534
586
return static_cast <RType>(*reinterpret_cast <const DType*>(p));
@@ -587,14 +639,18 @@ PointCloudColorHandlerGenericField<PointT>::PointCloudColorHandlerGenericField(
587
639
const PointCloudConstPtr& cloud, const std::string& field_name)
588
640
: PointCloudColorHandler<PointT>(cloud), field_name_(field_name)
589
641
{
590
- this ->fields_ = getFields (*cloud);
591
642
this ->setInputCloud (cloud);
592
643
}
593
644
645
+ template <typename PointT>
646
+ PointCloudColorHandlerGenericField<PointT>::PointCloudColorHandlerGenericField(const std::string& field_name)
647
+ : PointCloudColorHandler<PointT>(), field_name_(field_name) {}
648
+
594
649
template <typename PointT> void PointCloudColorHandlerGenericField<PointT>::setInputCloud(
595
650
const PointCloudConstPtr& cloud)
596
651
{
597
652
PointCloudColorHandler<PointT>::setInputCloud (cloud);
653
+ this ->fields_ = getFields (*cloud);
598
654
this ->field_idx_ = getFieldIndex (field_name_, this ->fields_ );
599
655
this ->capable_ = this ->field_idx_ != -1 ;
600
656
}
@@ -638,7 +694,7 @@ template <typename PointT> vtkSmartPointer<vtkDataArray> PointCloudColorHandlerG
638
694
// Color every point
639
695
for (vtkIdType cp = 0 ; cp < nr_points; ++cp, point_offset += point_step) {
640
696
641
- if (x_channel_idx != -1 && !pcl::isXYZFinite (( *this ->cloud_ )[cp] )) {
697
+ if (x_channel_idx != -1 && !isXYZFiniteAt ( *this ->cloud_ , cp )) {
642
698
// no x channel in the cloud, or point is infinite
643
699
continue ;
644
700
} else {
0 commit comments