The most common way to do this is by subscript in the [] operand[1]
pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud;
for(int nIndex = 0; nIndex < pointCloud->points.size (); nIndex++)
{
pointCloud->points[nIndex].x;
pointCloud->points[nIndex].y;
pointCloud->points[nIndex].z;
}
The more efficient way is to use an iterator [2] [3]
The example in Euclidean Cluster Extraction of pcl tutorials is well known [2].
Extract the indices cluster_indices
then use it to iterate each pointcloud from cluster_indices.begin ()
to cluster_indices.end ()
. Next step is to iterate every point in the pointcloud from it->indices.begin ();
to it->indices.end ()
. The code snippet is:
std::vector<pcl::PointIndices> cluster_indices;
pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
ec.setClusterTolerance (0.02); // 2cm
ec.setMinClusterSize (100);
ec.setMaxClusterSize (25000);
ec.setSearchMethod (tree);
ec.setInputCloud (cloud_filtered);
ec.extract (cluster_indices);
int j = 0;
for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); ++pit)
cloud_cluster->points.push_back (cloud_filtered->points[*pit]); //*
cloud_cluster->width = cloud_cluster->points.size ();
cloud_cluster->height = 1;
cloud_cluster->is_dense = true;
std::cout << "PointCloud representing the Cluster: " << cloud_cluster->points.size () << " data points." << std::endl;
std::stringstream ss;
ss << "cloud_cluster_" << j << ".pcd";
writer.write<pcl::PointXYZ> (ss.str (), *cloud_cluster, false); //*
j++;
}
Last way do iteration but only Eigen::Vector3f
values of points can be extract instead of a PCL point. [3]
If having trouble to save memory consumption, try this! Note: Only if the second way didn't work out!
The advantage of using this iterator is that no indices should be extracted before.
for (std::vector<pcl::PointXYZ, Eigen::aligned_allocator<pcl::PointXYZ> >::iterator it = pointCloud.bigin(); it != cropedCloud.end(); it++)
{
// Return an Eigen::Vector3f of points coordinate.
it->getVector3fMap(); // if double wanted, just say it->getVector3fMap().cast<double>
}
Note:
- The snippet should be modified to YOUR version before using it
pcl::PointXYZ
can be replaced by any type ofPointT
pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud
can be replaced bypcl::PointCloud<pcl::PointXYZ> pointCloud
, so by the mean time replacepointCloud->points.size()
instead ofpointCloud.points.size()
*/
What matters to me but it might not be helpful to you
Let's talk about how to find a way to use data of unknown type
pcl::CropBox< PointT >
does gives an access to achieve indices.- There is an
iterator begin ()
on the PCL namespace website. I guess can use it to iterate all around in the pointcloud. - Look for definition at line 442 of point_cloud.h, which returns
points.begin ()
Click the functionbegin ()
in theconst_iterator begin () const
. - In the tutorial of iterating pointcloud[2],
pointcloud->begin()
is neither indices nor points. The data structure type it use isstd::vector<pcl::PointXYZ, Eigen::aligned_allocator<pcl::PointXYZ> >::iterator
, which I got from the error building. Note: Sometimes you don't know what the type it is, but you can got it from the error. What a amazing thing. - The most important thing is: how to get the data? So I go through the pcl directory, and search for function
points.begin()
. $ cd ~/Downloads/nozuonodie/pcl-pcl-1.7.2
,grep -rn -ie "points.begin ()"
. Look for those lines of matched completely function "points.begin ()" in hpp or cpp files.- After several attemps, I got it by
common/include/pcl/range_image/impl/range_image.hpp:1225: for (typename PointCloudType::const_iterator it = far_ranges.points.begin (); it != far_ranges.points.end (); ++it)
. Go to line 1225, seeVector3fMapConst current_point = it->getVector3fMap ();
, then look for variablecurrent_point
- In line 1231,
this->getImagePoint (current_point, x_real, y_real, range_of_current_point);
just go to the definition ofgetImagePoint
. - In line 352, function
void RangeImage::getImagePoint (const Eigen::Vector3f& point, float& image_x, float& image_y, float& range) const
totally matches. - In conclusion, member function getVector3fMap() can get Eigen::Vector3f from the point by iterator. And also can be proved by referece [3].
References:
[1] Filtering a PointCloud using a PassThrough filter
[2] Euclidean Cluster Extraction
[3] Creating a PCL point cloud using a container of Eigen Vector3d