Skip to content

Commit bb908e9

Browse files
committed
Update plugin to make ZIP archives.
1 parent 87494be commit bb908e9

File tree

9 files changed

+127
-92
lines changed

9 files changed

+127
-92
lines changed

_data/archives.yml

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
cpp-beginners:
22
- "_programs/cpp"
33
- exclude:
4+
- "build"
45
- "cmake-build-debug"
56
- "cmake-build-release"
67
- ".+\\/data\\/.+"

_plugins/archive.rb

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ def wrap_and_flush(zipfile, dest, source)
1717

1818
if not ignoring
1919
writer.write(line)
20+
elsif not line.include?("{{") and not line.include?("}}")
21+
if line.strip.empty? or line.strip.start_with?("//")
22+
writer.write(line)
23+
end
2024
end
2125

2226
if line.strip == ignore_end

_programs/cpp/CMakeLists.txt

+1-6
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,12 @@ option(WITH_OPENMP "Use OpenMP" ON)
1515
# ----------
1616
# C++ compiler setting
1717
# ----------
18-
set(CMAKE_CXX_STANDARD 17)
18+
set(CMAKE_CXX_STANDARD 14)
1919
set(CMAKE_CXX_STANDARD_REQUIRED ON)
2020
if (UNIX)
2121
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
2222
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -Wall")
2323
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g -Wall")
24-
if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
25-
set(CXX_FS_LIBRARY "c++fs")
26-
else()
27-
set(CXX_FS_LIBRARY "stdc++fs")
28-
endif()
2924
endif()
3025

3126
# ----------

_programs/cpp/src/common/io.h

+26-16
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
#include "vec3.h"
1010

1111
//! Write OBJ file
12-
void write_obj(const std::string &filename, const std::vector<Vec3> &positions, const std::vector<uint32_t> &indices) {
12+
inline void write_obj(const std::string &filename, const std::vector<Vec3> &positions,
13+
const std::vector<uint32_t> &indices) {
1314
std::ofstream writer(filename.c_str(), std::ios::out);
1415
if (writer.fail()) {
1516
throw std::runtime_error("Failed to open file: " + filename);
@@ -31,47 +32,55 @@ void write_obj(const std::string &filename, const std::vector<Vec3> &positions,
3132
}
3233

3334
//! Write PLY file
34-
void write_ply(const std::string &filename, const std::vector<Vec3> &positions, const std::vector<uint32_t> &indices) {
35+
inline void write_ply(const std::string &filename, const std::vector<Vec3> &positions,
36+
const std::vector<uint32_t> &indices) {
3537
std::ofstream writer(filename.c_str(), std::ios::out | std::ios::binary);
3638
if (writer.fail()) {
3739
throw std::runtime_error("Failed to open file: " + filename);
3840
}
3941

40-
writer << "ply" << "\n";
41-
writer << "format binary_little_endian 1.0" << "\n";
42+
writer << "ply"
43+
<< "\n";
44+
writer << "format binary_little_endian 1.0"
45+
<< "\n";
4246

4347
const size_t nVerts = positions.size();
4448
writer << "element vertex " << nVerts << "\n";
45-
writer << "property float x" << "\n";
46-
writer << "property float y" << "\n";
47-
writer << "property float z" << "\n";
49+
writer << "property float x"
50+
<< "\n";
51+
writer << "property float y"
52+
<< "\n";
53+
writer << "property float z"
54+
<< "\n";
4855

4956
const int nFaces = (int)indices.size() / 3;
5057
writer << "element face " << nFaces << "\n";
51-
writer << "property list uchar int vertex_indices" << "\n";
52-
writer << "end_header" << "\n";
58+
writer << "property list uchar int vertex_indices"
59+
<< "\n";
60+
writer << "end_header"
61+
<< "\n";
5362

5463
for (const auto &p : positions) {
55-
float buf[3] = {(float)p.x, (float)p.y, (float)p.z};
56-
writer.write((char*)buf, sizeof(float) * 3);
64+
float buf[3] = { (float)p.x, (float)p.y, (float)p.z };
65+
writer.write((char *)buf, sizeof(float) * 3);
5766
}
5867

5968
for (int i = 0; i < nFaces; i++) {
6069
const uint8_t k = 3;
61-
writer.write((char*)&k, sizeof(uint8_t));
70+
writer.write((char *)&k, sizeof(uint8_t));
6271

6372
const uint32_t a = indices[i * 3 + 0];
6473
const uint32_t b = indices[i * 3 + 1];
6574
const uint32_t c = indices[i * 3 + 2];
66-
uint32_t buf[3] = {a, b, c};
67-
writer.write((char*)buf, sizeof(uint32_t) * 3);
75+
uint32_t buf[3] = { a, b, c };
76+
writer.write((char *)buf, sizeof(uint32_t) * 3);
6877
}
6978

7079
writer.close();
7180
}
7281

7382
// Load OFF mesh file (in this program, the file stores only point cloud)
74-
void read_off(const std::string &filename, std::vector<Vec3> *positions, std::vector<Vec3> *normals = nullptr) {
83+
inline void read_off(const std::string &filename, std::vector<Vec3> *positions, std::vector<Vec3> *normals = nullptr) {
7584
std::ifstream reader(filename.c_str(), std::ios::in);
7685
if (reader.fail()) {
7786
throw std::runtime_error("Failed to open file: " + filename);
@@ -109,7 +118,8 @@ void read_off(const std::string &filename, std::vector<Vec3> *positions, std::ve
109118
}
110119

111120
// Write OFF mesh file (only point cloud will be written)
112-
void write_off(const std::string &filename, const std::vector<Vec3> &positions, const std::vector<Vec3> &normals = std::vector<Vec3>()) {
121+
inline void write_off(const std::string &filename, const std::vector<Vec3> &positions,
122+
const std::vector<Vec3> &normals = std::vector<Vec3>()) {
113123
std::ofstream writer(filename.c_str(), std::ios::out);
114124
if (writer.fail()) {
115125
throw std::runtime_error("Failed to open file: " + filename);

_programs/cpp/src/icp/CMakeLists.txt

+11-8
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,22 @@ set(BUILD_TARGET "icp_exe")
22
add_executable(${BUILD_TARGET})
33

44
target_include_directories(${BUILD_TARGET} PUBLIC ${EIGEN3_INCLUDE_DIRS})
5-
target_sources(
6-
${BUILD_TARGET}
7-
PRIVATE
8-
${COMMON_HEADERS}
5+
6+
set(SOURCE_FILES
97
main.cpp
108
icp.h
119
icp.cpp
1210
svd.h
13-
svd.cpp
14-
)
11+
svd.cpp)
12+
13+
target_sources(
14+
${BUILD_TARGET}
15+
PRIVATE
16+
${SOURCE_FILES}
17+
${COMMON_HEADERS})
1518

16-
get_target_property(SOURCE_LIST ${BUILD_TARGET} SOURCES)
17-
source_group("Source Files" FILES ${SOURCE_LIST})
19+
source_group("Source Files" FILES ${SOURCE_FILES})
20+
source_group("Common Headers" FILES ${COMMON_HEADERS})
1821

1922
if (MSVC)
2023
target_compile_options(${BUILD_TARGET} PRIVATE "/Zi")

_programs/cpp/src/icp/icp.cpp

+46-28
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ using IndexType = int64_t;
99
using EigenMatrix = Eigen::MatrixXd;
1010
using EigenVector = Eigen::VectorXd;
1111

12+
#include "common/io.h"
1213
#include "common/kdtree.h"
1314
#include "common/debug.h"
1415
#include "svd.h"
@@ -29,18 +30,14 @@ EigenMatrix rodrigues(const EigenVector &w, const double theta) {
2930
const double wy = w(1);
3031
const double wz = w(2);
3132
EigenMatrix K(3, 3);
32-
K << 0.0, -wz, wy,
33-
wz, 0.0, -wx,
34-
-wy, wx, 0.0;
33+
K << 0.0, -wz, wy, wz, 0.0, -wx, -wy, wx, 0.0;
3534

3635
EigenMatrix I = EigenMatrix::Identity(3, 3);
3736
return I + K * s + (K * K) * (1.0 - c);
3837
}
3938

4039
//! single point to point ICP step
41-
void point2pointICP_step(const std::vector<Vec3> &target,
42-
const std::vector<Vec3> &source,
43-
EigenMatrix *rotMat,
40+
void point2pointICP_step(const std::vector<Vec3> &target, const std::vector<Vec3> &source, EigenMatrix *rotMat,
4441
EigenVector *trans) {
4542
// Construct Kd-tree to find closest points
4643
KDTree<Vec3> tree;
@@ -49,6 +46,10 @@ void point2pointICP_step(const std::vector<Vec3> &target,
4946
// {{ NOT_IMPL_ERROR();
5047

5148
// Match closest point pairs
49+
// Hint:
50+
// Construct here that two matrices X and P,
51+
// whose elements are positions of source vertices (X),
52+
// and those for closest points of the sources (P)
5253
const int nPoints = (int)source.size();
5354
EigenMatrix X(nPoints, 3);
5455
EigenMatrix P(nPoints, 3);
@@ -60,12 +61,18 @@ void point2pointICP_step(const std::vector<Vec3> &target,
6061
}
6162

6263
// Subtract xMean, pMean from X, P
64+
// Hint:
65+
// Row-wise or column-wise mean (also sum, max, min etc.) of Eigen matrices
66+
// can be easily calculate using "rowwise()" or "colwise()".
6367
const EigenVector xMean = X.colwise().mean();
6468
const EigenVector pMean = P.colwise().mean();
6569
X.rowwise() -= xMean.transpose();
6670
P.rowwise() -= pMean.transpose();
6771

6872
// Solve with SVD to obtain R
73+
// Hint:
74+
// An SVD method "eigenSVD" is already given in "svd.h".
75+
// See its arguments carefully when using it.
6976
const EigenMatrix M = P.transpose() * X;
7077
EigenMatrix U, V;
7178
EigenVector sigma;
@@ -77,18 +84,19 @@ void point2pointICP_step(const std::vector<Vec3> &target,
7784
diagH << 1.0, 1.0, detVU;
7885

7986
// Output
87+
// Hint:
88+
// Be careful that arguments for output matrices and vectors
89+
// are represented as "pointers". Therefore, you should insert
90+
// values for them with "asterisk" like "*lhs = rhs".
8091
*rotMat = U * diagH.asDiagonal() * V.transpose();
8192
*trans = pMean - (*rotMat) * xMean;
8293

8394
// }}
8495
}
8596

8697
//! single point to plane ICP step
87-
void point2planeICP_step(const std::vector<Vec3> &target,
88-
const std::vector<Vec3> &targetNorm,
89-
const std::vector<Vec3> &source,
90-
Eigen::MatrixXd *rotMat,
91-
Eigen::VectorXd *trans) {
98+
void point2planeICP_step(const std::vector<Vec3> &target, const std::vector<Vec3> &targetNorm,
99+
const std::vector<Vec3> &source, Eigen::MatrixXd *rotMat, Eigen::VectorXd *trans) {
92100
// Construct Kd-tree to find closest points
93101
std::vector<Point> points;
94102
for (int i = 0; i < (int)target.size(); i++) {
@@ -101,7 +109,10 @@ void point2planeICP_step(const std::vector<Vec3> &target,
101109
// {{ NOT_IMPL_ERROR();
102110

103111
// Construct linear system
104-
const int nPoints = (int) source.size();
112+
// Hint:
113+
// prepare matrix A and vector b
114+
// A is 6x6 matrix, and b is 6-D vector
115+
const int nPoints = (int)source.size();
105116
EigenMatrix A(6, 6);
106117
EigenVector b(6);
107118
A.setZero();
@@ -119,16 +130,25 @@ void point2planeICP_step(const std::vector<Vec3> &target,
119130
}
120131

121132
// Solve
133+
// Hint:
134+
// Use "Eigen::PartialPivLU" to solve the system
122135
Eigen::PartialPivLU<EigenMatrix> lu(A);
123136
EigenVector u = lu.solve(b);
124137

125138
// Substitute to instances a, t
139+
// Hint:
140+
// Eigen matrices and vectors can be initialized
141+
// with its elements by "<<" operator.
126142
EigenVector a(3);
127143
a << u(0), u(1), u(2);
128144
EigenVector t(3);
129145
t << u(3), u(4), u(5);
130146

131147
// Reproduce rotation matrix
148+
// Hint:
149+
// Remember that vector "a" is the multiple of
150+
// the direction of rotation axis and
151+
// the degree of rotation angle.
132152
const double theta = a.norm();
133153
const EigenVector w = a / theta;
134154
*rotMat = rodrigues(w, theta);
@@ -137,29 +157,23 @@ void point2planeICP_step(const std::vector<Vec3> &target,
137157
// }}
138158
}
139159

140-
void rigidICP(const std::vector<Vec3> &target,
141-
const std::vector<Vec3> &targetNorm,
142-
std::vector<Vec3> &source,
143-
std::vector<Vec3> &sourceNorm,
144-
ICPMetric metric,
145-
int maxIters,
146-
double tolerance,
147-
bool verbose) {
160+
void rigidICP(const std::vector<Vec3> &target, const std::vector<Vec3> &targetNorm, std::vector<Vec3> &source,
161+
std::vector<Vec3> &sourceNorm, ICPMetric metric, int maxIters, double tolerance, bool verbose) {
148162
// Point-to-point ICP
149163
for (int it = 0; it < maxIters; it++) {
150164
Eigen::MatrixXd R(3, 3);
151165
Eigen::VectorXd t(3);
152166
switch (metric) {
153-
case ICPMetric::Point2Point:
154-
point2pointICP_step(target, source, &R, &t);
155-
break;
167+
case ICPMetric::Point2Point:
168+
point2pointICP_step(target, source, &R, &t);
169+
break;
156170

157-
case ICPMetric::Point2Plane:
158-
point2planeICP_step(target, targetNorm, source, &R, &t);
159-
break;
171+
case ICPMetric::Point2Plane:
172+
point2planeICP_step(target, targetNorm, source, &R, &t);
173+
break;
160174

161-
default:
162-
throw std::runtime_error("Unknown ICP metric type!");
175+
default:
176+
throw std::runtime_error("Unknown ICP metric type!");
163177
}
164178

165179
// Apply rigid transformation
@@ -189,6 +203,10 @@ void rigidICP(const std::vector<Vec3> &target,
189203
printf("\n");
190204
}
191205

206+
char outfile[256];
207+
sprintf(outfile, "intermediate_%03d.off", it);
208+
write_off(std::string(outfile), source, sourceNorm);
209+
192210
if (error < tolerance) {
193211
break;
194212
}

_programs/cpp/src/icp/main.cpp

+21-18
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,27 @@ int main(int argc, char **argv) {
1515
const int nIterations = argc > 3 ? atoi(argv[3]) : 100;
1616
const double tolerance = argc > 4 ? atof(argv[4]) : 1.0e-4;
1717

18-
// Load point cloud data
19-
std::vector<Vec3> pos0;
20-
std::vector<Vec3> norm0;
21-
std::vector<Vec3> pos1;
22-
std::vector<Vec3> norm1;
23-
read_off(argv[1], &pos0, &norm0);
24-
read_off(argv[2], &pos1, &norm1);
25-
printf("PCL #0: %ld points\n", pos0.size());
26-
printf("PCL #1: %ld points\n", pos1.size());
18+
try {
19+
// Load point cloud data
20+
std::vector<Vec3> pos0;
21+
std::vector<Vec3> norm0;
22+
std::vector<Vec3> pos1;
23+
std::vector<Vec3> norm1;
24+
read_off(argv[1], &pos0, &norm0);
25+
read_off(argv[2], &pos1, &norm1);
26+
printf("PCL #0: %ld points\n", pos0.size());
27+
printf("PCL #1: %ld points\n", pos1.size());
2728

28-
// Rigid ICP
29-
rigidICP(pos0, norm0, pos1, norm1, ICPMetric::Point2Plane,
30-
nIterations, tolerance, true);
29+
// Rigid ICP
30+
rigidICP(pos0, norm0, pos1, norm1, ICPMetric::Point2Plane, nIterations, tolerance, true);
3131

32-
// Write as *.off
33-
filepath path(argv[2]);
34-
const filepath dirname = path.dirname();
35-
const filepath basename = path.stem();
36-
const std::string outfile = (dirname / basename + "_output.off").string();
37-
write_off(outfile, pos1, norm1);
32+
// Write as *.off
33+
filepath path(argv[2]);
34+
const filepath dirname = path.dirname();
35+
const filepath basename = path.stem();
36+
const std::string outfile = (dirname / basename + "_output.off").string();
37+
write_off(outfile, pos1, norm1);
38+
} catch (std::runtime_error &e) {
39+
std::cerr << e.what() << std::endl;
40+
}
3841
}

0 commit comments

Comments
 (0)