-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmyclass.cpp
More file actions
463 lines (417 loc) · 15.2 KB
/
myclass.cpp
File metadata and controls
463 lines (417 loc) · 15.2 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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
#include "myclass.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <PointCloud.h>
#include <Windows.h>
#include <random>
#include <string>
#include <direct.h>
#include <io.h>
#include <cmath>
int ImproveBoundsNum = 0;
int FindBestCandidateNum = 0;
std::chrono::microseconds ImproveBoundsTime(0);
std::chrono::microseconds FindBestCandidateTime(0);
size_t number_of_Candidates = 0;
void readPoints(const std::string& filename, PointCloud& point2pc) {
std::ifstream infile(filename);
if (!infile.is_open()) {
std::cerr << "Failed to open file!" << std::endl;
std::exit(EXIT_FAILURE);
}
// Prepare to read data
std::string dataline;
Point point;
// Start reading the file
while (std::getline(infile, dataline)) {
std::istringstream iss(dataline);
// Read vertex data from obj file
if (dataline[0] == 'v') {
iss.ignore(1);
}
if (!(iss >> point.pos[0] >> point.pos[1] >> point.pos[2])) {
//std::cerr << "Error reading line: " << dataline << std::endl;
continue;
}
point2pc.push_back(point);
}
// Close the file
infile.close();
}
// Read lines from a file
void readLines(const std::string& filename, LineCloud& lc, double m_bitmapEpsilon) {
// Open the file
std::ifstream infile(filename);
// Check if the file is open
if (!infile.is_open()) {
// Failed to open file
std::cerr << "Failed to open file!" << std::endl;
std::exit(EXIT_FAILURE);
}
// Prepare to read data
std::string dataline;
PointCloud pc;
// Initialize point cloud and add a dummy point at index 0
Point point;
pc.push_back(point);
// For the line cloud, add a dummy line at index 0
lc.push_back(Line());
Vec3f startPoint;
Vec3f endPoint;
size_t startPointIdx = 0;
size_t endPointIdx = 0;
// Line segment direction
Vec3f direction;
// Line segment length
float segmentLength = 0;
// Line segment midpoint
double x = 0.0, y = 0.0, z = 0.0;
char v = 'v';
char l = 'l';
// Prepare to read line segments
std::vector<double> values;
double value = 0;
// Start reading the file
while (std::getline(infile, dataline)) {
std::istringstream iss(dataline);
// Read vertex data from obj file
// If the line starts with 'v', it's a vertex
if (dataline[0] == 'v') {
// Read vertex identifier
iss >> v;
while (iss >> value) {
values.push_back(value);
}
point.pos = Vec3f(values[0], values[1], values[2]);
if (values.size() == 6) {
point.color = Vec3f(values[3], values[4], values[5]);
}
pc.push_back(point);
values.clear();
}
// Read line segment data from obj file
// If the line starts with 'l', it's a line segment
if (dataline[0] == 'l') {
if (!(iss >> l >> startPointIdx >> endPointIdx)) {
std::cerr << "Error reading line: " << dataline << std::endl;
continue;
}
// Start point
startPoint = pc[startPointIdx].pos;
// End point
endPoint = pc[endPointIdx].pos;
// Line segment direction
direction = endPoint - startPoint;
// Line segment length
segmentLength = direction.length();
// Normalize direction
direction /= segmentLength;
// Calculate effective number of samples
int numSamples = int(segmentLength / m_bitmapEpsilon) + 2;
Line line(startPoint, endPoint, segmentLength, direction, numSamples);
line.color = pc[startPointIdx].color;
lc.push_back(line);
}
}
// Close the file
infile.close();
}
// Convert line cloud to point cloud
void lc2pc(LineCloud& lc, double m_bitmapEpsilon, PointCloud& line2pc) {
// Sample points along each line segment
for (size_t i = 1; i < lc.size(); i++) {
// Line segment length
float segmentLength = lc[i].segmentLength;
// Line segment direction
Vec3f direction = lc[i].direction;
for (int j = 0; j <= lc[i].num - 2; j++) {
Vec3f samplePoint = lc[i].startPoint + direction * (j * m_bitmapEpsilon);
line2pc.push_back(Point(samplePoint, i));
}
line2pc.push_back(Point(lc[i].endPoint, i));
}
}
// Delete all contents of a directory, including subdirectories
void deleteDirectoryContents(const std::string& dirPath) {
WIN32_FIND_DATA findFileData;
HANDLE hFind = FindFirstFile((dirPath + "\\*").c_str(), &findFileData);
if (hFind == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to open directory: " << dirPath << std::endl;
return;
}
do {
const std::string fileOrDirName = findFileData.cFileName;
if (fileOrDirName == "." || fileOrDirName == "..") {
continue;
}
const std::string fullPath = dirPath + "\\" + fileOrDirName;
if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// Delete contents of subdirectory
deleteDirectoryContents(fullPath);
if (!RemoveDirectory(fullPath.c_str())) { // Remove directory
std::cerr << "Failed to remove directory: " << fullPath << std::endl;
}
}
else {
// Delete file
if (!DeleteFile(fullPath.c_str())) {
std::cerr << "Failed to delete file: " << fullPath << std::endl;
}
}
} while (FindNextFile(hFind, &findFileData) != 0);
FindClose(hFind);
}
// Split a file path into its components
std::vector<std::string> splitPath(const std::string& path) {
std::vector<std::string> parts;
std::string part;
for (char c : path) {
if (c == '\\' || c == '/') {
if (!part.empty()) {
parts.push_back(part);
part.clear();
}
}
else {
part += c;
}
}
if (!part.empty()) {
parts.push_back(part);
}
return parts;
}
// Create a directory and all parent directories if they don't exist
void createDirectoryRecursively(const std::string& path) {
std::vector<std::string> parts = splitPath(path);
std::string currentPath;
for (const auto& part : parts) {
if (!currentPath.empty()) {
currentPath += "\\";
}
currentPath += part;
// Check if the directory exists
if (_access(currentPath.c_str(), 0) != 0) {
// Directory does not exist, create it
if (_mkdir(currentPath.c_str()) != 0) {
std::cerr << "Failed to create directory: " << currentPath << std::endl;
std::cerr << "Error code: " << errno << std::endl; // Print error code
return;
}
}
}
}
// Write point plane, shapes store the corresponding plane, point2pc store the actual point cloud, Lc store the actual line cloud, transacOptions for plane segmentation, filePath for the output directory (default is output)
void writePointPlane(MiscLib::Vector<std::pair<MiscLib::RefCountPtr<PrimitiveShape>, size_t>>& shapes,
PointCloud& point2pc, LineCloud& Lc, float m_epsilon, float m_bitmapEpsilon, const std::string& filePath) {
// Create output directory
createDirectoryRecursively(filePath);
std::string pointPlanesDir = filePath + "/pointPlanes";
std::string linePlanesDir = filePath + "/linePlanes";
createDirectoryRecursively(pointPlanesDir);
createDirectoryRecursively(linePlanesDir);
// Calculate the total number of points
size_t pointNumSum = 0;
// Create a random number generator
std::random_device rd; // Obtain a random number from hardware
std::mt19937 gen(rd()); // Seed the generator
// Create a uniform distribution in the range [0, 1)
std::uniform_real_distribution<> dis(0.0, 1.0);
// Create the all point file
std::string allPointFileName = filePath + "/pointPlanes.obj";
std::ofstream allPointFile(allPointFileName);
// Check if the file was created successfully
if (!allPointFile.is_open()) {
std::cerr << "Failed to create point plane file: " << allPointFileName << std::endl;
std::exit(EXIT_FAILURE);
}
// Create the all point normal file
std::string allPointFileName_normal = filePath + "/pointPlanes_normal.obj";
std::ofstream allPointFile_normal(allPointFileName_normal);
// Create the all line to point normal file
std::string allLine2PointFileName_normal = filePath + "/line2PointPlanes_normal.obj";
std::ofstream allLine2PointFile_normal(allLine2PointFileName_normal);
// Create the all line file
std::string allLineFileName = filePath + "/linePlanes.obj";
std::ofstream allLineFile(allLineFileName);
// Check if the file was created successfully
if (!allLineFile.is_open()) {
std::cerr << "Failed to create line plane file: " << allLineFileName << std::endl;
std::exit(EXIT_FAILURE);
}
// Create the all point normal file
std::string normalFileName = filePath + "/normal.txt";
std::ofstream normalFile(normalFileName);
// Check if the file was created successfully
if (!normalFile.is_open()) {
std::cerr << "Failed to create normal file: " << normalFileName << std::endl;
std::exit(EXIT_FAILURE);
}
// Create the plane tag file
std::string tagFileName = filePath + "/planeTag.txt";
std::ofstream tagFile(tagFileName);
// Check if the file was created successfully
if (!tagFile.is_open()) {
std::cerr << "Failed to create plane tag file: " << tagFileName << std::endl;
std::exit(EXIT_FAILURE);
}
// Create the all line file
size_t allLineNum = 0;
// Create the line planes
for (int i = 0; i < shapes.size(); i++) {
// Get the normal of the current plane
Vec3f normal(0, 0, 0);
shapes[i].first->Normal(Vec3f(0, 0, 0), &normal);
// Create random colors
double r = dis(gen);
double g = dis(gen);
double b = dis(gen);
// Create the point plane file
std::string pointFileName = pointPlanesDir + "/pointPlane" + std::to_string(i + 1) + ".obj";
std::ofstream pointFile(pointFileName);
// Check if the file was created successfully
if (!pointFile.is_open()) {
std::cerr << "Failed to create point plane file: " << pointFileName << std::endl;
std::exit(EXIT_FAILURE);
}
// Create the line plane file
std::string lineFileName = linePlanesDir + "/linePlane" + std::to_string(i + 1) + ".obj";
std::ofstream lineFile(lineFileName);
// Check if the file was created successfully
if (!lineFile.is_open()) {
std::cerr << "Failed to create line plane file: " << lineFileName << std::endl;
std::exit(EXIT_FAILURE);
}
// Get the number of points in the current plane
size_t pointNum = shapes[i].second;
// Get the number of lines in the current plane
size_t lineNum = 0;
auto it = point2pc.end() - pointNumSum - 1;
// Iterate through the points in the current plane
for (int j = 0; j < pointNum; j++) {
// Get the current point
if (it->tag == 0) {
// Create the point normal file
allPointFile_normal << "v" << " " << it->pos[0] << " " << it->pos[1] << " " << it->pos[2] << std::endl;
allPointFile_normal << "vn" << " " << normal[0] << " " << normal[1] << " " << normal[2] << std::endl;
// Create the point plane file
pointFile << "v " << " " << it->pos[0] << " " << it->pos[1] << " " << it->pos[2] << " " << r << " " << g << " " << b << std::endl;
// Create the all point file
allPointFile << "v " << " " << it->pos[0] << " " << it->pos[1] << " " << it->pos[2] << " " << r << " " << g << " " << b << std::endl;
// Create the normal file
normalFile << it->normal[0] << " " << it->normal[1] << " " << it->normal[2] << std::endl;
// Create the plane ID file
tagFile << i + 1 << std::endl;
}
// Create the line file
else {
// Create the line normal file
allLine2PointFile_normal << "v" << " " << it->pos[0] << " " << it->pos[1] << " " << it->pos[2] << std::endl;
allLine2PointFile_normal << "vn" << " " << normal[0] << " " << normal[1] << " " << normal[2] << std::endl;
// Get the current line's tag
size_t tag = it->tag;
// Check if the line has already been processed
if (!Lc[tag].tag) {
Vec3f startPoint = Lc[tag].startPoint;
Vec3f endPoint = Lc[tag].endPoint;
// Check if the line is close to the current plane
if (shapes[i].first->Distance(startPoint) < 3 * m_epsilon && shapes[i].first->Distance(endPoint) < 3 * m_epsilon) {
// Create the line file
lineFile << "v " << " " << startPoint[0] << " " << startPoint[1] << " " << startPoint[2] << " " << r << " " << g << " " << b << std::endl;
lineFile << "v " << " " << endPoint[0] << " " << endPoint[1] << " " << endPoint[2] << " " << r << " " << g << " " << b << std::endl;
// Create the all line file
allLineFile << "v " << " " << startPoint[0] << " " << startPoint[1] << " " << startPoint[2] << " " << r << " " << g << " " << b << std::endl;
allLineFile << "v " << " " << endPoint[0] << " " << endPoint[1] << " " << endPoint[2] << " " << r << " " << g << " " << b << std::endl;
// Create the line number
lineNum++;
allLineNum++;
// Mark the line as processed
Lc[tag].tag = true;
}
}
}
// Create the line connection
--it;
}
// Create the line connection file
for (size_t t = 1; t <= lineNum; t++) {
lineFile << "l" << " " << 2 * t - 1 << " " << 2 * t << std::endl;
}
// Update the point number sum
pointNumSum += pointNum;
// Close the files
pointFile.close();
lineFile.close();
}
// Create the line connection file
for (size_t t = 1; t <= allLineNum; t++) {
allLineFile << "l" << " " << 2 * t - 1 << " " << 2 * t << std::endl;
}
// Close the files
allPointFile.close();
allLineFile.close();
normalFile.close();
tagFile.close();
allPointFile_normal.close();
allLine2PointFile_normal.close();
// Create the line connection file
//visualizationLineCloud(m_bitmapEpsilon, filePath);
// Create the line visualization file
visualizationLineCloud(0.0005, filePath);
}
// Create the line visualization file
void visualizationLineCloud(float m_bitmapEpsilon, const std::string& filePath) {
// Get the original line cloud
LineCloud Lc;
readLines(filePath + "/linePlanes.obj", Lc, m_bitmapEpsilon);
// Create the line cloud file
std::ofstream lineCloudFile(filePath + "/linePlanesWithColor.obj");
// Check if the file was opened successfully
if (!lineCloudFile.is_open()) {
std::cerr << "Failed to open line cloud file: " << filePath + "/linePlanesWithColor.obj" << std::endl;
std::exit(EXIT_FAILURE);
}
// Create the line segments
for (size_t i = 1; i < Lc.size(); i++) {
Vec3f startPoint = Lc[i].startPoint;
Vec3f endPoint = Lc[i].endPoint;
Vec3f color = Lc[i].color;
lineCloudFile << "v" << " " << startPoint[0] << " " << startPoint[1] << " " << startPoint[2] << " " << color[0] << " " << color[1] << " " << color[2] << std::endl;
lineCloudFile << "v" << " " << endPoint[0] << " " << endPoint[1] << " " << endPoint[2] << " " << color[0] << " " << color[1] << " " << color[2] << std::endl;
}
// Create the line samples
for (size_t i = 1; i < Lc.size(); i++) {
Vec3f startPoint = Lc[i].startPoint;
Vec3f endPoint = Lc[i].endPoint;
Vec3f color = Lc[i].color;
for (int j = 1; j < Lc[i].num - 1; j++) {
Vec3f samplePoint = startPoint + Lc[i].direction * (j * m_bitmapEpsilon);
lineCloudFile << "v" << " " << samplePoint[0] << " " << samplePoint[1] << " " << samplePoint[2] << " " << color[0] << " " << color[1] << " " << color[2] << std::endl;
}
}
// Create the line connection file
for (size_t i = 1; i < Lc.size(); i++) {
lineCloudFile << "l" << " " << 2 * i - 1 << " " << 2 * i << std::endl;
}
lineCloudFile.close();
}
// Create the line normals
void estimateLineNormals(PointCloud& pc, LineCloud& lc) {
// Iterate through each point in the point cloud
for (size_t i = 0; i < pc.size(); i++) {
// Get the tag of the current point
size_t tag = pc[i].tag;
// Check if the tag is valid
if (tag) {
// Accumulate the normal vectors for the corresponding line
lc[tag].normals += pc[i].normal;
// Store the normal vectors for the corresponding line
lc[tag].normalsVec.push_back(pc[i].normal);
}
}
// Normalize the normal vectors for each line
for (size_t i = 1; i < lc.size(); i++) {
lc[i].normals.normalize();
}
}