Agrarsense
Static Public Member Functions | List of all members
UPointcloudUtilities Class Reference

#include <PointcloudUtilities.h>

Inheritance diagram for UPointcloudUtilities:
Inheritance graph
[legend]
Collaboration diagram for UPointcloudUtilities:
Collaboration graph
[legend]

Static Public Member Functions

static void SaveTArrayAsPlyAsync (FString FullFileName, const TArray< FVector > points)
 
static void SaveVectorArrayAsPlyAsync (FString FullFileName, const std::vector< FPointData > points)
 

Detailed Description

A class for Point cloud related utilities.

Definition at line 20 of file PointcloudUtilities.h.

Member Function Documentation

◆ SaveTArrayAsPlyAsync()

void UPointcloudUtilities::SaveTArrayAsPlyAsync ( FString  FullFileName,
const TArray< FVector >  points 
)
static

Save TArray of FVectors to disk in .ply format asynchronously

Parameters
FullFileNameFull path with file name and file format (.ply)
pointsTArray of FVectors

Definition at line 19 of file PointcloudUtilities.cpp.

20{
21 if (points.Num() == 0)
22 {
23 return;
24 }
25
26 if (!FullFileName.EndsWith(TEXT(".ply")))
27 {
28 UE_LOG(LogTemp, Warning, TEXT("PointcloudUtilities.cpp: Invalid file format. Expecting filename to end with '.ply'!"));
29 return;
30 }
31
32 FString Directory = FPaths::GetPath(FullFileName);
33 IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
34 if (!PlatformFile.DirectoryExists(*Directory))
35 {
36 if (!PlatformFile.CreateDirectoryTree(*Directory))
37 {
38 return;
39 }
40 }
41
42 AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [FullFileName, points]()
43 {
44 // Create PLY header in binary format
45 std::string header = "ply\nformat binary_little_endian 1.0\n"
46 "element vertex " + std::to_string(points.Num()) + "\n"
47 "property double x\nproperty double y\nproperty double z\n"
48 "end_header\n";
49
50 // Calculate the size of the buffer
51 size_t numPoints = points.Num();
52 size_t bufferSize = numPoints * sizeof(FVector);
53
54 // Open file
55 std::ofstream plyFile(TCHAR_TO_UTF8(*FullFileName), std::ios::out | std::ios::binary);
56 if (!plyFile.is_open())
57 {
58 return;
59 }
60
61 // Write header
62 plyFile.write(header.c_str(), header.size());
63
64 // Write point cloud buffer to the file
65 plyFile.write(reinterpret_cast<const char*>(points.GetData()), bufferSize);
66
67 // Close file
68 plyFile.close();
69 });
70}

◆ SaveVectorArrayAsPlyAsync()

void UPointcloudUtilities::SaveVectorArrayAsPlyAsync ( FString  FullFileName,
const std::vector< FPointData points 
)
static

Save std::vector<FPointData> to disk in .ply format asynchronously. This function not only saves the spatial coordinates of each point in the point cloud but also saves the color information of each point, encoding the RGB color components in the output .ply file.

Parameters
FullFileNameFull path with file name and file extension (.ply), where the point cloud data will be saved.
pointsA vector of FPointData, containing the XYZ coordinates and RGB color data for each point.

Definition at line 72 of file PointcloudUtilities.cpp.

73{
74 if (points.empty())
75 {
76 return;
77 }
78
79 if (!FullFileName.EndsWith(TEXT(".ply")))
80 {
81 UE_LOG(LogTemp, Warning, TEXT("PointcloudUtilities.cpp: Invalid file format. Expecting filename to end with '.ply'!"));
82 return;
83 }
84
85 FString Directory = FPaths::GetPath(FullFileName);
86 IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
87 if (!PlatformFile.DirectoryExists(*Directory))
88 {
89 if (!PlatformFile.CreateDirectoryTree(*Directory))
90 {
91 return;
92 }
93 }
94
95 AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [FullFileName, points]()
96 {
97 // Create PLY header in binary format
98 std::string header = "ply\nformat binary_little_endian 1.0\n"
99 "element vertex " + std::to_string(points.size()) + "\n"
100 "property float x\nproperty float y\nproperty float z\n"
101 "property uchar red\nproperty uchar green\nproperty uchar blue\n"
102 "end_header\n";
103
104 // Prepare the buffer size
105 size_t numPoints = points.size();
106 size_t bufferSize = numPoints * (sizeof(float) * 3 + sizeof(uint8_t) * 3);
107 std::vector<char> buffer;
108 buffer.reserve(bufferSize);
109
110 // Prepare point data
111 for (const auto& point : points)
112 {
113 // Write coordinates (X, Y, Z) as binary floats
114 buffer.insert(buffer.end(), reinterpret_cast<const char*>(&point.X), reinterpret_cast<const char*>(&point.X) + sizeof(float));
115 buffer.insert(buffer.end(), reinterpret_cast<const char*>(&point.Y), reinterpret_cast<const char*>(&point.Y) + sizeof(float));
116 buffer.insert(buffer.end(), reinterpret_cast<const char*>(&point.Z), reinterpret_cast<const char*>(&point.Z) + sizeof(float));
117
118 // Extract RGB components and write them as unsigned chars
119 uint8_t red = (point.RGB >> 16) & 0xFF;
120 uint8_t green = (point.RGB >> 8) & 0xFF;
121 uint8_t blue = point.RGB & 0xFF;
122 buffer.insert(buffer.end(), reinterpret_cast<const char*>(&red), reinterpret_cast<const char*>(&red) + sizeof(uint8_t));
123 buffer.insert(buffer.end(), reinterpret_cast<const char*>(&green), reinterpret_cast<const char*>(&green) + sizeof(uint8_t));
124 buffer.insert(buffer.end(), reinterpret_cast<const char*>(&blue), reinterpret_cast<const char*>(&blue) + sizeof(uint8_t));
125 }
126
127 // Open file
128 std::ofstream plyFile(TCHAR_TO_UTF8(*FullFileName), std::ios::out | std::ios::binary);
129 if (!plyFile.is_open())
130 {
131 UE_LOG(LogTemp, Warning, TEXT("Failed to open file for writing: %s"), *FullFileName);
132 return;
133 }
134
135 // Write header
136 plyFile.write(header.c_str(), header.size());
137
138 // Write point cloud buffer to the file
139 plyFile.write(buffer.data(), buffer.size());
140
141 // Close file
142 plyFile.close();
143 });
144}

Referenced by ALidarManager::SaveCombinedPointcloud(), and ALidar::SaveDataToDisk().


The documentation for this class was generated from the following files: