I used libLAS library to read the cloud points of a .las file. Then I stored the points in a PCL point cloud variable in order to process and display the point cloud using the Point Cloud Library.
This is the code that I used:
class PointCloud
{
public:
//PointCloud(const std::string& path);
uint32_t getVertsCount();
float4* getVertsData();
template<typename PointT>
typename pcl::PointCloud<PointT>::Ptr read(const std::string& path);//void read(const std::string &path);
}
template<typename PointT>
typename pcl::PointCloud<PointT>::Ptr PointCloud::read(const string& path)
{
typename pcl::PointCloud<PointT>::Ptr lasCloud(new pcl::PointCloud<PointT>);
std::ifstream ifs;
ifs.open(path, std::ios::in | std::ios::binary);
//std::ifstream inf(path, std::ios::in | std::ios::binary);
liblas::ReaderFactory f;
liblas::Reader reader = f.CreateWithStream(ifs);
liblas::Header const& header = reader.GetHeader();
std::cout << "Compressed: " << (header.Compressed() == true) ? "true" : "false";
std::cout << "Signature: " << header.GetFileSignature() << '\n';
std::cout << "Points count: " << header.GetPointRecordsCount() << '\n';
while (reader.ReadNextPoint())
{
liblas::Point const& p = reader.GetPoint();
PointT cloudPoint;
cloudPoint.x = float(p.GetX()) * 0.001 + 590284.000; // (double)(x * scaleX) + offsetX;
cloudPoint.y = float(p.GetY()) * 0.001 + 4339456.000; // (double)(y * scaleY) + offsetY;
cloudPoint.z = float(p.GetZ()) * 0.001 + 157.000; // (double)(z * scaleZ) + offsetZ;
std::cout << p.GetX() << ", " << p.GetY() << ", " << p.GetZ() << "\n";
//cloudPoint.intensity = p.GetIntensity(); // (double)(intensity) / 65536.0;
lasCloud->points.push_back(cloudPoint);
}
if (!ifs.good())
throw runtime_error("Reading went wrong!");
lasCloud->width = lasCloud->points.size();
lasCloud->height = 1;
lasCloud->is_dense = true;
std::cout << "Cloud size = " << lasCloud->points.size() << endl;
return lasCloud;
}
int main (int argc, char** argv)
{
std::cout << "starting enviroment" << std::endl;
pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
CameraAngle setAngle = FPS; //XY, FPS, Side, TopDown
initCamera(setAngle, viewer);
pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloudI; //
inputCloudI = pcd.read<pcl::PointXYZ>("C:/Users/hedey/OneDrive/Documents/Research_papers/STDF/10_4231_MFQF-Q141/I-65/LiDAR/RoadSurface/NB/20180524_I65_NB_RoadSurface_1_50.5.las");
std::cout << "Cloud size = " << inputCloudI->points.size() << endl;
renderPointCloud(viewer, inputCloudI, "lasCloud");
while (!viewer->wasStopped())
{
viewer->spinOnce();
}
}
However, the displayed cloud using the PCL viewer looks like one point. What I noticed is that when I printed out the coordinates that I read using libLAS, the x & y coordinates don't have decimal values, which is inaccurate compared to the actual coordinates stored in the las file. I got the actual point coordinates using las2txt from the command prompt. This is the txt file containing the actual coordinates. And here is an image showing the cout results:
Also, this is how the point cloud looks like when I opened it using CloudCompare. I look forward to geting the same displayed when I read it into a PCL Point Cloud variable and display the results using the PCL viewer, because I'll need to do further processing in order to make sensor fusion (Camera and Lidar).
The default precision of
std::cout
is 6 decimal digits. Please add something likebefore the
while
loop.Also, casting
p.GetX()
etc. tofloat
is pointless: if you multiply it by0.001
, the left hand side of the argument of operator* will naturally by promoted to at leastdouble
. However,float
has only about 7 digits of precision, so for 9-digit integers stored inside doubles (yes!) such truncation is catastrophic.Also there's another (minor) error, the correct line reads
Please notice the () braces surrounding the conditional expression (and
\n
). Please use standard compiler options that will warn against such simple issues.Please read also https://stackoverflow.com/help/minimal-reproducible-example