Skip to content

Commit 7039f3c

Browse files
committed
Eigen PCA example
1 parent 72cd733 commit 7039f3c

File tree

4 files changed

+131
-4
lines changed

4 files changed

+131
-4
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "3rdparty/eigen"]
2+
path = 3rdparty/eigen
3+
url = https://gitlab.com/libeigen/eigen

3rdparty/eigen

Submodule eigen added at 0fd6b4f

CMakeLists.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,11 @@ if(UNIX)
140140
string(REGEX REPLACE "([^;]+)" "${ICU_LIBRARY_DIR}/lib\\1.a" ICU_LIBRARIES "${ICU_LIBRARY_NAMES}")
141141
endif()
142142
else()
143-
set(BOOST_ROOT ${IFCOPENSHELL_ROOT}/_deps/boost_1_74_0)
144-
set(BOOST_LIBRARYDIR ${IFCOPENSHELL_ROOT}/_deps/boost_1_74_0/stage/vs${MSVC_YEAR}-${WIN_ARCH}/lib)
143+
set(BOOST_ROOT ${IFCOPENSHELL_ROOT}/deps/boost_1_67_0)
144+
set(BOOST_LIBRARYDIR ${IFCOPENSHELL_ROOT}/deps/boost_1_67_0/stage/vs${MSVC_YEAR}-${WIN_ARCH}/lib)
145145

146146
set(IFC_INCLUDE_DIR ${IFCOPENSHELL_ROOT}/src)
147-
set(IFC_LIBRARY_DIR ${IFCOPENSHELL_ROOT}/_build-vs${MSVC_YEAR}-Win32/${CMAKE_BUILD_TYPE})
147+
set(IFC_LIBRARY_DIR ${IFCOPENSHELL_ROOT}/build-vs${MSVC_YEAR}-x86/${CMAKE_BUILD_TYPE})
148148

149149
string(REGEX REPLACE "([^;]+)" "${IFC_LIBRARY_DIR}/\\1.lib" IFC_LIBRARIES "${IFC_LIBRARY_NAMES}")
150150

@@ -162,7 +162,7 @@ find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
162162
message(STATUS "Boost include files found in ${Boost_INCLUDE_DIRS}")
163163
message(STATUS "Boost libraries found in ${Boost_LIBRARY_DIRS}")
164164

165-
include_directories(${IFC_INCLUDE_DIR} ${OCC_INCLUDE_DIR} ${Boost_INCLUDE_DIRS})
165+
include_directories(${IFC_INCLUDE_DIR} ${OCC_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/eigen)
166166
link_directories(${Boost_LIBRARY_DIRS})
167167

168168
include_directories(${INCLUDE_DIRECTORIES} ${OCC_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ${IFC_INCLUDE_DIR})

tests/test_pca.cpp

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#include "../voxelizer.h"
2+
#include "../volume.h"
3+
#include "../traversal.h"
4+
5+
6+
#include <gp_Pln.hxx>
7+
#include <Bnd_Box.hxx>
8+
#include <BRepBndLib.hxx>
9+
#include <BRepBuilderAPI_MakeFace.hxx>
10+
#include <BRepMesh_IncrementalMesh.hxx>
11+
12+
#include <Eigen/Dense>
13+
14+
#include <gtest/gtest.h>
15+
16+
TEST(NormalEstimation, EigenPCA) {
17+
static Eigen::Vector3f Z(0, 0, 1);
18+
Eigen::MatrixXf points(10, 3);
19+
points.setRandom();
20+
points.col(2).setZero();
21+
22+
Eigen::MatrixXf centered = points.rowwise() - points.colwise().mean();
23+
Eigen::MatrixXf cov = centered.adjoint() * centered;
24+
Eigen::SelfAdjointEigenSolver<Eigen::MatrixXf> eig(cov);
25+
26+
ASSERT_FLOAT_EQ(std::abs(eig.eigenvectors().col(0).dot(Z)), 1.);
27+
}
28+
29+
30+
TEST(NormalEstimation, OCC) {
31+
gp_Pln p(1, 2, 3, 4);
32+
auto face = BRepBuilderAPI_MakeFace(p, -1, 1, -1, 1).Face();
33+
BRepMesh_IncrementalMesh(face, 0.1);
34+
35+
auto surf = BRep_Tool::Surface(face);
36+
auto dir = Handle_Geom_Plane::DownCast(surf)->Position().Direction();
37+
38+
Eigen::Vector3f norm(dir.X(), dir.Y(), dir.Z());
39+
std::cout << "Face normal " << norm << std::endl;
40+
41+
Bnd_Box B;
42+
BRepBndLib::AddClose(face, B);
43+
44+
double d = 0.05;
45+
double x0, y0, z0, x1, y1, z1;
46+
B.Get(x0, y0, z0, x1, y1, z1);
47+
48+
auto storage = new chunked_voxel_storage<bit_t>(
49+
x0 - d,
50+
y0 - d,
51+
z0 - d, d,
52+
(x1 - x0) / d + 2,
53+
(y1 - y0) / d + 2,
54+
(z1 - z0) / d + 2,
55+
64);
56+
auto vox = voxelizer(face, storage);
57+
vox.Convert();
58+
59+
std::cout << "count " << storage->count() << std::endl;
60+
61+
auto it = storage->begin();
62+
std::advance(it, storage->count() / 2);
63+
64+
std::cout << "center " << (*it).format() << std::endl;
65+
66+
for (int i = 1; i <= 10; i += 2) {
67+
68+
visitor<26> vis;
69+
vis.max_depth = 0.1 * i / d;
70+
71+
std::cout << "md " << (0.1 * i) << std::endl;
72+
73+
std::vector<float> coords;
74+
75+
auto selection = storage->empty_copy();
76+
77+
vis([&coords, &selection](const tagged_index& pos) {
78+
if (pos.which == tagged_index::VOXEL) {
79+
coords.push_back(pos.pos.get(0));
80+
coords.push_back(pos.pos.get(1));
81+
coords.push_back(pos.pos.get(2));
82+
selection->Set(pos.pos);
83+
}
84+
else {
85+
throw std::runtime_error("Unexpected");
86+
}
87+
}, storage, *it);
88+
89+
/*{
90+
std::ofstream ofs("m2.obj");
91+
((chunked_voxel_storage<bit_t>*)selection)->obj_export(ofs);
92+
}
93+
94+
storage->boolean_subtraction_inplace(selection);
95+
96+
{
97+
std::ofstream ofs("m1.obj");
98+
storage->obj_export(ofs);
99+
}*/
100+
101+
std::cout << "neighbours " << (coords.size() / 3) << std::endl;
102+
103+
Eigen::MatrixXf points = Eigen::Map<Eigen::MatrixXf>(coords.data(), 3, coords.size() / 3).transpose();
104+
105+
Eigen::MatrixXf centered = points.rowwise() - points.colwise().mean();
106+
Eigen::MatrixXf cov = centered.adjoint() * centered;
107+
Eigen::SelfAdjointEigenSolver<Eigen::MatrixXf> eig(cov);
108+
109+
auto estimated = eig.eigenvectors().col(0);
110+
111+
std::cout << estimated << std::endl;
112+
113+
auto angle = std::acos(estimated.dot(norm));
114+
if (angle > M_PI / 2) {
115+
angle = M_PI - angle;
116+
}
117+
auto angle_degrees = angle / M_PI * 180.;
118+
119+
std::cout << "angle " << angle_degrees << "d" << std::endl;
120+
121+
ASSERT_LT(angle_degrees, 90.);
122+
}
123+
}

0 commit comments

Comments
 (0)