Skip to content

Commit 7e7f343

Browse files
Cover both PointCloud and PCLPointCloud2 with one PointCloudColorHandlerGenericField class
1 parent 2556e89 commit 7e7f343

File tree

2 files changed

+65
-45
lines changed

2 files changed

+65
-45
lines changed

visualization/include/pcl/visualization/impl/point_cloud_color_handlers.hpp

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939

4040
#include <set>
4141
#include <map>
42+
#include <stdexcept>
4243

4344
#include <pcl/pcl_macros.h>
4445
#include <pcl/common/colors.h>
@@ -491,29 +492,40 @@ PointCloudColorHandlerLabelField<PointT>::getColor () const
491492

492493
// Get point fields from cloud. Could not get it to work with existing
493494
// pcl::getFields
494-
inline template <typename CloudT> std::vector<pcl::PCLPointField>
495+
template <typename CloudT> inline std::vector<pcl::PCLPointField>
495496
getFields(const CloudT& cloud)
496497
{
497498
return pcl::getFields<typename CloudT::PointType>();
498499
}
499500

501+
template <> inline std::vector<pcl::PCLPointField>
502+
getFields<pcl::PCLPointCloud2>(const pcl::PCLPointCloud2& cloud) {
503+
return cloud.fields;
504+
}
505+
506+
500507
// 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&)
502509
{
503510
return sizeof(typename CloudT::PointType);
504511
}
505512

513+
template <> inline int
514+
getPointStep<pcl::PCLPointCloud2>(const pcl::PCLPointCloud2& cloud) {
515+
return cloud.point_step;
516+
}
517+
506518
// 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)
508520
{
509521
return reinterpret_cast<const std::uint8_t*>(cloud.points.data());
510522
}
511523

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) {
514525
return reinterpret_cast<const std::uint8_t*>(cloud.data.data());
515526
}
516527

528+
517529
// copy of pcl::getFieldIndex() from impl/io.hpp, without the unused template
518530
// parameter
519531
static int getFieldIndex(const std::string& field_name,
@@ -529,6 +541,46 @@ static int getFieldIndex(const std::string& field_name,
529541
return std::distance(fields.begin(), result);
530542
}
531543

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+
532584
template <typename DType, typename RType> RType reinterpret_and_cast(const std::uint8_t* p)
533585
{
534586
return static_cast<RType>(*reinterpret_cast<const DType*>(p));
@@ -587,14 +639,18 @@ PointCloudColorHandlerGenericField<PointT>::PointCloudColorHandlerGenericField(
587639
const PointCloudConstPtr& cloud, const std::string& field_name)
588640
: PointCloudColorHandler<PointT>(cloud), field_name_(field_name)
589641
{
590-
this->fields_ = getFields(*cloud);
591642
this->setInputCloud(cloud);
592643
}
593644

645+
template <typename PointT>
646+
PointCloudColorHandlerGenericField<PointT>::PointCloudColorHandlerGenericField(const std::string& field_name)
647+
: PointCloudColorHandler<PointT>(), field_name_(field_name) {}
648+
594649
template <typename PointT> void PointCloudColorHandlerGenericField<PointT>::setInputCloud(
595650
const PointCloudConstPtr& cloud)
596651
{
597652
PointCloudColorHandler<PointT>::setInputCloud(cloud);
653+
this->fields_ = getFields(*cloud);
598654
this->field_idx_ = getFieldIndex(field_name_, this->fields_);
599655
this->capable_ = this->field_idx_ != -1;
600656
}
@@ -638,7 +694,7 @@ template <typename PointT> vtkSmartPointer<vtkDataArray> PointCloudColorHandlerG
638694
// Color every point
639695
for (vtkIdType cp = 0; cp < nr_points; ++cp, point_offset += point_step) {
640696

641-
if (x_channel_idx != -1 && !pcl::isXYZFinite((*this->cloud_)[cp])) {
697+
if (x_channel_idx != -1 && !isXYZFiniteAt(*this->cloud_, cp)) {
642698
// no x channel in the cloud, or point is infinite
643699
continue;
644700
} else {

visualization/include/pcl/visualization/point_cloud_color_handlers.h

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ namespace pcl
353353
PointCloudColorHandlerGenericField(const PointCloudConstPtr& cloud,
354354
const std::string& field_name);
355355

356+
PointCloudColorHandlerGenericField(const std::string& field_name);
357+
356358
/** \brief Set the input cloud to be used.
357359
* \param[in] cloud the input cloud to be used by the handler
358360
*/
@@ -711,44 +713,6 @@ namespace pcl
711713
int v_field_idx_;
712714
};
713715

714-
//////////////////////////////////////////////////////////////////////////////////////
715-
/** \brief Generic field handler class for colors. Uses an user given field to extract
716-
* 1D data and display the color at each point using a min-max lookup table.
717-
* \author Radu B. Rusu
718-
* \ingroup visualization
719-
*/
720-
template <>
721-
class PCL_EXPORTS PointCloudColorHandlerGenericField<pcl::PCLPointCloud2> : public PointCloudColorHandler<pcl::PCLPointCloud2>
722-
{
723-
using PointCloud = PointCloudColorHandler<pcl::PCLPointCloud2>::PointCloud;
724-
using PointCloudPtr = PointCloud::Ptr;
725-
using PointCloudConstPtr = PointCloud::ConstPtr;
726-
727-
public:
728-
using Ptr = shared_ptr<PointCloudColorHandlerGenericField<PointCloud> >;
729-
using ConstPtr = shared_ptr<const PointCloudColorHandlerGenericField<PointCloud> >;
730-
731-
/** \brief Constructor. */
732-
PointCloudColorHandlerGenericField (const PointCloudConstPtr &cloud,
733-
const std::string &field_name);
734-
735-
vtkSmartPointer<vtkDataArray>
736-
getColor () const override;
737-
738-
protected:
739-
/** \brief Get the name of the class. */
740-
virtual std::string
741-
getName () const { return ("PointCloudColorHandlerGenericField"); }
742-
743-
/** \brief Get the name of the field used. */
744-
virtual std::string
745-
getFieldName () const { return (field_name_); }
746-
747-
private:
748-
/** \brief Name of the field used to create the color handler. */
749-
std::string field_name_;
750-
};
751-
752716
//////////////////////////////////////////////////////////////////////////////////////
753717
/** \brief RGBA handler class for colors. Uses the data present in the "rgba" field as
754718
* the color at each point. Transparency is handled.

0 commit comments

Comments
 (0)