forked from JanuszBedkowski/mandeye_controller
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsave_laz.cpp
More file actions
191 lines (159 loc) · 5.28 KB
/
save_laz.cpp
File metadata and controls
191 lines (159 loc) · 5.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#include "save_laz.h"
#include <iostream>
#include <laszip/laszip_api.h>
nlohmann::json mandeye::LazStats::produceStatus() const {
nlohmann::json status;
status["filename"] = m_filename;
status["points_count"] = m_pointsCount;
status["save_duration_sec1"] = m_saveDurationSec1;
status["save_duration_sec2"] = m_saveDurationSec2;
status["size_mb"] = m_sizeMb;
status["decimation_step"] = m_decimationStep;
return status;
}
std::optional<mandeye::LazStats> mandeye::saveLaz(const std::string& filename, LivoxPointsBufferPtr buffer)
{
mandeye::LazStats stats;
stats.m_filename = filename;
stats.m_pointsCount = buffer->size();
constexpr float scale = 0.0001f; // one tenth of milimeter
// find max
double max_x{std::numeric_limits<double>::lowest()};
double max_y{std::numeric_limits<double>::lowest()};
double max_z{std::numeric_limits<double>::lowest()};
double min_x{std::numeric_limits<double>::max()};
double min_y{std::numeric_limits<double>::max()};
double min_z{std::numeric_limits<double>::max()};
for(auto& p : *buffer)
{
double x = 0.001 * p.point.x;
double y = 0.001 * p.point.y;
double z = 0.001 * p.point.z;
max_x = std::max(max_x, x);
max_y = std::max(max_y, y);
max_z = std::max(max_z, z);
min_x = std::min(min_x, x);
min_y = std::min(min_y, y);
min_z = std::min(min_z, z);
}
std::cout << "processing: " << filename << "points " << buffer->size() << std::endl;
laszip_POINTER laszip_writer;
if(laszip_create(&laszip_writer))
{
fprintf(stderr, "DLL ERROR: creating laszip writer\n");
return nullopt;
}
// get a pointer to the header of the writer so we can populate it
laszip_header* header;
if(laszip_get_header_pointer(laszip_writer, &header))
{
fprintf(stderr, "DLL ERROR: getting header pointer from laszip writer\n");
return nullopt;
}
// populate the header
// heuristically determine the decimation step
int step = 1;
if(buffer->size() > 4000000){
step = ceil((double)buffer->size() / 2000000.0);
}
if(step < 1){
step = 1;
}
int num_points = 0;
for(int i = 0; i < buffer->size(); i += step){
num_points ++;
}
stats.m_decimationStep = step;
header->file_source_ID = 4711;
header->global_encoding = (1 << 0); // see LAS specification for details
header->version_major = 1;
header->version_minor = 2;
// header->file_creation_day = 120;
// header->file_creation_year = 2013;
header->point_data_format = 1;
header->point_data_record_length = 0;
header->number_of_point_records = num_points;//buffer->size();
header->number_of_points_by_return[0] = num_points;//buffer->size();
header->number_of_points_by_return[1] = 0;
header->point_data_record_length = 28;
header->x_scale_factor = scale;
header->y_scale_factor = scale;
header->z_scale_factor = scale;
header->max_x = max_x;
header->min_x = min_x;
header->max_y = max_y;
header->min_y = min_y;
header->max_z = max_z;
header->min_z = min_z;
// optional: use the bounding box and the scale factor to create a "good" offset
// open the writer
laszip_BOOL compress = (strstr(filename.c_str(), ".laz") != 0);
const auto start = std::chrono::high_resolution_clock::now();
if(laszip_open_writer(laszip_writer, filename.c_str(), compress))
{
fprintf(stderr, "DLL ERROR: opening laszip writer for '%s'\n", filename.c_str());
return nullopt;
}
fprintf(stderr, "writing file '%s' %scompressed\n", filename.c_str(), (compress ? "" : "un"));
// get a pointer to the point of the writer that we will populate and write
laszip_point* point;
if(laszip_get_point_pointer(laszip_writer, &point))
{
fprintf(stderr, "DLL ERROR: getting point pointer from laszip writer\n");
return nullopt;
}
laszip_I64 p_count = 0;
laszip_F64 coordinates[3];
//for(int i = 0; i < buffer->size(); i++)
for(int i = 0; i < buffer->size(); i += step)
{
const auto& p = buffer->at(i);
point->intensity = p.point.reflectivity;
point->gps_time = p.timestamp * 1e-9;
point->user_data = p.line_id;
point->classification = p.point.tag;
point->user_data = p.laser_id;
p_count++;
coordinates[0] = 0.001 * p.point.x;
coordinates[1] = 0.001 * p.point.y;
coordinates[2] = 0.001 * p.point.z;
if(laszip_set_coordinates(laszip_writer, coordinates))
{
fprintf(stderr, "DLL ERROR: setting coordinates for point %I64d\n", p_count);
return nullopt;
}
if(laszip_write_point(laszip_writer))
{
fprintf(stderr, "DLL ERROR: writing point %I64d\n", p_count);
return nullopt;
}
}
if(laszip_get_point_count(laszip_writer, &p_count))
{
fprintf(stderr, "DLL ERROR: getting point count\n");
return nullopt;
}
fprintf(stderr, "successfully written %I64d points\n", p_count);
stats.m_pointsCount = p_count;
// close the writer
if(laszip_close_writer(laszip_writer))
{
fprintf(stderr, "DLL ERROR: closing laszip writer\n");
return nullopt;
}
// destroy the writer
if(laszip_destroy(laszip_writer))
{
fprintf(stderr, "DLL ERROR: destroying laszip writer\n");
return nullopt;
}
std::cout << "exportLaz DONE" << std::endl;
const auto end = std::chrono::high_resolution_clock::now();
const std::chrono::duration<float> elapsed_seconds = end - start;
stats.m_saveDurationSec1 = elapsed_seconds.count();
if (std::filesystem::exists(filename)) {
std::uintmax_t size = std::filesystem::file_size(filename);
stats.m_sizeMb = static_cast<float>(size)/(1024*1024);
}
return stats;
}