14 #include <unordered_map>
21 namespace ply_voxelgrid_reader {
23 struct PLYReaderState {
35 int ReadOriginCallback(p_ply_argument argument) {
36 PLYReaderState *state_ptr;
38 ply_get_argument_user_data(argument,
reinterpret_cast<void **
>(&state_ptr),
41 double value = ply_get_argument_value(argument);
42 state_ptr->origin(index) = value;
46 int ReadOriginRotationCallback(p_ply_argument argument) {
47 PLYReaderState *state_ptr;
49 ply_get_argument_user_data(argument,
reinterpret_cast<void **
>(&state_ptr),
52 double value = ply_get_argument_value(argument);
55 state_ptr->rotation(row, col) = value;
59 int ReadScaleCallback(p_ply_argument argument) {
60 PLYReaderState *state_ptr;
62 ply_get_argument_user_data(argument,
reinterpret_cast<void **
>(&state_ptr),
65 double value = ply_get_argument_value(argument);
66 state_ptr->voxel_size = value;
70 int ReadVoxelCallback(p_ply_argument argument) {
71 PLYReaderState *state_ptr;
73 ply_get_argument_user_data(argument,
reinterpret_cast<void **
>(&state_ptr),
75 if (state_ptr->voxel_index >= state_ptr->voxel_num) {
79 double value = ply_get_argument_value(argument);
80 auto &ptr = *(state_ptr->voxelgrid_ptr);
81 ptr[state_ptr->voxel_index].grid_index_(index) = int(value);
83 state_ptr->voxel_index++;
84 ++(*state_ptr->progress_bar);
89 int ReadColorCallback(p_ply_argument argument) {
90 PLYReaderState *state_ptr;
92 ply_get_argument_user_data(argument,
reinterpret_cast<void **
>(&state_ptr),
94 if (state_ptr->color_index >= state_ptr->color_num) {
98 double value = ply_get_argument_value(argument);
99 auto &ptr = *(state_ptr->voxelgrid_ptr);
100 ptr[state_ptr->color_index].color_(index) = value / 255.0;
102 state_ptr->color_index++;
103 ++(*state_ptr->progress_bar);
110 static const std::unordered_map<
112 std::function<bool(
const std::string &, geometry::VoxelGrid &,
bool)>>
113 file_extension_to_voxelgrid_read_function{
117 static const std::unordered_map<std::string,
118 std::function<bool(
const std::string &,
119 const geometry::VoxelGrid &,
123 file_extension_to_voxelgrid_write_function{
134 const std::string &
format,
135 bool print_progress) {
136 auto voxelgrid = std::make_shared<geometry::VoxelGrid>();
143 const std::string &
format,
144 bool print_progress) {
145 std::string filename_ext;
152 if (filename_ext.empty()) {
154 "Read geometry::VoxelGrid failed: unknown file extension.");
157 auto map_itr = file_extension_to_voxelgrid_read_function.find(filename_ext);
158 if (map_itr == file_extension_to_voxelgrid_read_function.end()) {
160 "Read geometry::VoxelGrid failed: unknown file extension.");
163 bool success = map_itr->second(
filename, voxelgrid, print_progress);
165 (
int)voxelgrid.
voxels_.size());
173 bool print_progress) {
174 std::string filename_ext =
176 if (filename_ext.empty()) {
178 "Write geometry::VoxelGrid failed: unknown file extension.");
182 file_extension_to_voxelgrid_write_function.find(filename_ext);
183 if (map_itr == file_extension_to_voxelgrid_write_function.end()) {
185 "Write geometry::VoxelGrid failed: unknown file extension.");
191 (
int)voxelgrid.
voxels_.size());
197 bool print_progress) {
198 using namespace ply_voxelgrid_reader;
200 p_ply ply_file = ply_open(
filename.c_str(),
nullptr, 0,
nullptr);
206 if (!ply_read_header(ply_file)) {
212 PLYReaderState state;
215 state.voxel_num = ply_set_read_cb(ply_file,
"vertex",
"x",
216 ReadVoxelCallback, &state, 0);
217 ply_set_read_cb(ply_file,
"vertex",
"y", ReadVoxelCallback, &state, 1);
218 ply_set_read_cb(ply_file,
"vertex",
"z", ReadVoxelCallback, &state, 2);
220 if (state.voxel_num <= 0) {
226 state.color_num = ply_set_read_cb(ply_file,
"vertex",
"red",
227 ReadColorCallback, &state, 0);
228 ply_set_read_cb(ply_file,
"vertex",
"green", ReadColorCallback, &state, 1);
229 ply_set_read_cb(ply_file,
"vertex",
"blue", ReadColorCallback, &state, 2);
231 ply_set_read_cb(ply_file,
"origin",
"x", ReadOriginCallback, &state, 0);
232 ply_set_read_cb(ply_file,
"origin",
"y", ReadOriginCallback, &state, 1);
233 ply_set_read_cb(ply_file,
"origin",
"z", ReadOriginCallback, &state, 2);
234 ply_set_read_cb(ply_file,
"rotation",
"r00", ReadOriginRotationCallback,
236 ply_set_read_cb(ply_file,
"rotation",
"r01", ReadOriginRotationCallback,
238 ply_set_read_cb(ply_file,
"rotation",
"r02", ReadOriginRotationCallback,
240 ply_set_read_cb(ply_file,
"rotation",
"r10", ReadOriginRotationCallback,
242 ply_set_read_cb(ply_file,
"rotation",
"r11", ReadOriginRotationCallback,
244 ply_set_read_cb(ply_file,
"rotation",
"r12", ReadOriginRotationCallback,
246 ply_set_read_cb(ply_file,
"rotation",
"r20", ReadOriginRotationCallback,
248 ply_set_read_cb(ply_file,
"rotation",
"r21", ReadOriginRotationCallback,
250 ply_set_read_cb(ply_file,
"rotation",
"r22", ReadOriginRotationCallback,
252 ply_set_read_cb(ply_file,
"voxel_size",
"val", ReadScaleCallback, &state,
255 state.voxel_index = 0;
256 state.color_index = 0;
261 "Reading PLY: ", print_progress);
264 if (!ply_read(ply_file)) {
273 if (state.color_num > 0)
278 voxelgrid.
origin_ = state.origin;
290 bool print_progress) {
296 p_ply ply_file = ply_create(
filename.c_str(),
298 nullptr, 0,
nullptr);
304 ply_add_comment(ply_file,
"Created by cloudViewer");
305 ply_add_element(ply_file,
"origin", 1);
306 ply_add_property(ply_file,
"x", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
307 ply_add_property(ply_file,
"y", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
308 ply_add_property(ply_file,
"z", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
309 ply_add_element(ply_file,
"rotation", 1);
310 ply_add_property(ply_file,
"r00", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
311 ply_add_property(ply_file,
"r01", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
312 ply_add_property(ply_file,
"r02", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
313 ply_add_property(ply_file,
"r10", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
314 ply_add_property(ply_file,
"r11", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
315 ply_add_property(ply_file,
"r12", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
316 ply_add_property(ply_file,
"r20", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
317 ply_add_property(ply_file,
"r21", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
318 ply_add_property(ply_file,
"r22", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
319 ply_add_element(ply_file,
"voxel_size", 1);
320 ply_add_property(ply_file,
"val", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
322 ply_add_element(ply_file,
"vertex",
323 static_cast<long>(voxelgrid.
voxels_.size()));
326 ply_add_property(ply_file,
"x", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
327 ply_add_property(ply_file,
"y", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
328 ply_add_property(ply_file,
"z", PLY_DOUBLE, PLY_DOUBLE, PLY_DOUBLE);
330 ply_add_property(ply_file,
"red", PLY_UCHAR, PLY_UCHAR, PLY_UCHAR);
331 ply_add_property(ply_file,
"green", PLY_UCHAR, PLY_UCHAR, PLY_UCHAR);
332 ply_add_property(ply_file,
"blue", PLY_UCHAR, PLY_UCHAR, PLY_UCHAR);
335 if (!ply_write_header(ply_file)) {
342 static_cast<size_t>(voxelgrid.
voxels_.size()),
343 "Writing PLY: ", print_progress);
346 ply_write(ply_file,
origin(0));
347 ply_write(ply_file,
origin(1));
348 ply_write(ply_file,
origin(2));
351 ply_write(ply_file,
rotation(0, 0));
352 ply_write(ply_file,
rotation(0, 1));
353 ply_write(ply_file,
rotation(0, 2));
354 ply_write(ply_file,
rotation(1, 0));
355 ply_write(ply_file,
rotation(1, 1));
356 ply_write(ply_file,
rotation(1, 2));
357 ply_write(ply_file,
rotation(2, 0));
358 ply_write(ply_file,
rotation(2, 1));
359 ply_write(ply_file,
rotation(2, 2));
363 for (
auto &it : voxelgrid.
voxels_) {
370 ply_write(ply_file,
rgb(0));
371 ply_write(ply_file,
rgb(1));
372 ply_write(ply_file,
rgb(2));
filament::Texture::InternalFormat format
cloudViewer::utility::ConsoleProgressBar * progress_bar
std::vector< geometry::Voxel > * voxelgrid_ptr
VoxelGrid is a collection of voxels which are aligned in grid.
Eigen::Matrix3d rotation_
std::unordered_map< Eigen::Vector3i, Voxel, cloudViewer::utility::hash_eigen< Eigen::Vector3i > > voxels_
Voxels contained in voxel grid.
double voxel_size_
Size of the voxel.
virtual bool IsEmpty() const override
bool HasColors() const
Returns true if the voxel grid contains voxel colors.
Eigen::Vector3d origin_
Coorindate of the origin point.
void AddVoxel(const Voxel &voxel)
Add a voxel with specified grid index and color.
Base Voxel class, containing grid id and color.
Eigen::Vector3i grid_index_
Grid coordinate index of the voxel.
Eigen::Vector3d color_
Color of the voxel.
bool WriteVoxelGridToPLY(const std::string &filename, const geometry::VoxelGrid &voxelgrid, bool write_ascii=false, bool compressed=false, bool print_progress=false)
std::shared_ptr< geometry::VoxelGrid > CreateVoxelGridFromFile(const std::string &filename, const std::string &format="auto", bool print_progress=false)
bool WriteVoxelGrid(const std::string &filename, const geometry::VoxelGrid &voxelgrid, bool write_ascii=false, bool compressed=false, bool print_progress=false)
bool ReadVoxelGridFromPLY(const std::string &filename, geometry::VoxelGrid &voxelgrid, bool print_progress=false)
bool ReadVoxelGrid(const std::string &filename, geometry::VoxelGrid &voxelgrid, const std::string &format="auto", bool print_progress=false)
std::string GetFileExtensionInLowerCase(const std::string &filename)
Eigen::Vector3uint8 ColorToUint8(const Eigen::Vector3d &color)
Generic file read and write utility for python interface.