From e7b917e8dd1b25282f5bee3a4863c4e1ee8b5b78 Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Fri, 15 May 2020 12:47:31 -0400 Subject: [PATCH 1/8] support for non-orthogonal matrix first pass --- src/csg/impl/levelset_3d.cpp | 8 +++++--- src/csg/impl/matrix_functions.cpp | 31 +++++++++++++++++++++++++++++++ src/csg/impl/matrix_functions.hpp | 11 +++++++++++ src/csg/meson.build | 1 + 4 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 src/csg/impl/matrix_functions.cpp create mode 100644 src/csg/impl/matrix_functions.hpp diff --git a/src/csg/impl/levelset_3d.cpp b/src/csg/impl/levelset_3d.cpp index e3498d3..c6310a2 100644 --- a/src/csg/impl/levelset_3d.cpp +++ b/src/csg/impl/levelset_3d.cpp @@ -1,4 +1,5 @@ #include "csg_types.hpp" +#include "matrix_functions.hpp" #include #include @@ -68,11 +69,12 @@ double signed_distance_3d(const Mulmatrix3D &mm, double xx, double yy, auto XX = xx - mm.translation[0]; auto YY = yy - mm.translation[1]; auto ZZ = zz - mm.translation[2]; + auto rot = matrix::inverse(mm.rotation); return signed_distance_3d( mm.group, - mm.rotation[0][0] * XX + mm.rotation[1][0] * YY + mm.rotation[2][0] * ZZ, - mm.rotation[0][1] * XX + mm.rotation[1][1] * YY + mm.rotation[2][1] * ZZ, - mm.rotation[0][2] * XX + mm.rotation[1][2] * YY + mm.rotation[2][2] * ZZ); + rot[0][0] * XX + rot[0][1] * YY + rot[0][2] * ZZ, + rot[1][0] * XX + rot[1][1] * YY + rot[1][2] * ZZ, + rot[2][0] * XX + rot[2][1] * YY + rot[2][2] * ZZ); } double signed_distance_3d(const Cone &cone, double xx, double yy, double zz) { diff --git a/src/csg/impl/matrix_functions.cpp b/src/csg/impl/matrix_functions.cpp new file mode 100644 index 0000000..8cba487 --- /dev/null +++ b/src/csg/impl/matrix_functions.cpp @@ -0,0 +1,31 @@ +#include "matrix_functions.hpp" + +namespace { +double determinant(const std::array, 3> &m) { + return m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) - + m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) + + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); +} +} // namespace + +namespace matrix { + +std::array, 3> +inverse(const std::array, 3> &m) { + std::array, 3> res; + double d = 1 / determinant(m); + + res[0][0] = d * (m[1][1] * m[2][2] - m[2][1] * m[1][2]); + res[0][1] = d * (m[0][2] * m[2][1] - m[0][1] * m[2][2]); + res[0][2] = d * (m[0][1] * m[1][2] - m[0][2] * m[1][1]); + res[1][0] = d * (m[1][2] * m[2][0] - m[1][0] * m[2][2]); + res[1][1] = d * (m[0][0] * m[2][2] - m[0][2] * m[2][0]); + res[1][2] = d * (m[1][0] * m[0][2] - m[0][0] * m[1][2]); + res[2][0] = d * (m[1][0] * m[2][1] - m[2][0] * m[1][1]); + res[2][1] = d * (m[2][0] * m[0][1] - m[0][0] * m[2][1]); + res[2][2] = d * (m[0][0] * m[1][1] - m[1][0] * m[0][1]); + + return res; +} + +} // namespace matrix diff --git a/src/csg/impl/matrix_functions.hpp b/src/csg/impl/matrix_functions.hpp new file mode 100644 index 0000000..167bf60 --- /dev/null +++ b/src/csg/impl/matrix_functions.hpp @@ -0,0 +1,11 @@ +#ifndef MATRIX_FUNCTIONS_H_ +#define MATRIX_FUNCTIONS_H_ + +#include + +namespace matrix { +std::array, 3> +inverse(const std::array, 3> &m); +} + +#endif diff --git a/src/csg/meson.build b/src/csg/meson.build index 228b6e9..f708196 100644 --- a/src/csg/meson.build +++ b/src/csg/meson.build @@ -4,6 +4,7 @@ lib_csg_parser = static_library( 'impl/levelset_3d.cpp', 'impl/levelset_2d.cpp', 'impl/parser.cpp', + 'impl/matrix_functions.cpp', include_directories: tao_inc, install : true) -- GitLab From 8600e0b090d0dc1277e6df53ad5b103e234ec91b Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Fri, 15 May 2020 13:20:45 -0400 Subject: [PATCH 2/8] fix cmake file --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0fa1f06..6bec6ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ target_sources(csg PRIVATE src/csg/impl/levelset_3d.cpp src/csg/impl/levelset_2d.cpp src/csg/impl/csg.cpp + src/csg/impl/matrix_functions.cpp ) target_include_directories(csg PRIVATE -- GitLab From 7863bdc5e30f64882ab6d093b0cfbc9649231516 Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Mon, 18 May 2020 10:24:46 -0400 Subject: [PATCH 3/8] Store rotation inverse & other small tweaks --- src/csg/impl/csg_types.hpp | 2 ++ src/csg/impl/levelset_2d.cpp | 6 +++--- src/csg/impl/levelset_3d.cpp | 10 +++++----- src/csg/impl/matrix_functions.cpp | 24 ++++++++++++++++++++---- src/csg/impl/matrix_functions.hpp | 7 +++++-- src/csg/impl/parser.cpp | 7 +++---- src/csg/tests/levelset/extrude.t.cpp | 3 +++ src/csg/tests/levelset/transform.t.cpp | 4 ++++ 8 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/csg/impl/csg_types.hpp b/src/csg/impl/csg_types.hpp index e804c10..c17b61c 100644 --- a/src/csg/impl/csg_types.hpp +++ b/src/csg/impl/csg_types.hpp @@ -87,12 +87,14 @@ template struct Difference { template <> struct Mulmatrix { std::array, 3> rotation; + std::array, 3> rotation_inv; std::array translation; Union group; }; template <> struct Mulmatrix { std::array, 2> rotation; + std::array, 2> rotation_inv; std::array translation; Union group; }; diff --git a/src/csg/impl/levelset_2d.cpp b/src/csg/impl/levelset_2d.cpp index 32f593c..bb6a6c7 100644 --- a/src/csg/impl/levelset_2d.cpp +++ b/src/csg/impl/levelset_2d.cpp @@ -55,12 +55,12 @@ double signed_distance_2d(const Difference2D &group, double xx, double yy) { } double signed_distance_2d(const Mulmatrix2D &mm, double xx, double yy) { - // TODO: Invert non-orthogonal matrices auto XX = xx - mm.translation[0]; auto YY = yy - mm.translation[1]; + const auto &ri = mm.rotation_inv; return signed_distance_2d(mm.group, - mm.rotation[0][0] * XX + mm.rotation[1][0] * YY, - mm.rotation[0][1] * XX + mm.rotation[1][1] * YY); + ri[0][0] * XX + ri[0][1] * YY, + ri[1][0] * XX + ri[1][1] * YY); } double signed_distance_2d(const Square &sq, double xx, double yy) { diff --git a/src/csg/impl/levelset_3d.cpp b/src/csg/impl/levelset_3d.cpp index c6310a2..8d12a11 100644 --- a/src/csg/impl/levelset_3d.cpp +++ b/src/csg/impl/levelset_3d.cpp @@ -65,16 +65,16 @@ double signed_distance_3d(const Difference3D &group, double xx, double yy, double signed_distance_3d(const Mulmatrix3D &mm, double xx, double yy, double zz) { - // TODO: Invert non-orthogonal matrices auto XX = xx - mm.translation[0]; auto YY = yy - mm.translation[1]; auto ZZ = zz - mm.translation[2]; - auto rot = matrix::inverse(mm.rotation); + const auto &ro = mm.rotation_inv; + auto ri = matrix::inverse(mm.rotation); return signed_distance_3d( mm.group, - rot[0][0] * XX + rot[0][1] * YY + rot[0][2] * ZZ, - rot[1][0] * XX + rot[1][1] * YY + rot[1][2] * ZZ, - rot[2][0] * XX + rot[2][1] * YY + rot[2][2] * ZZ); + ri[0][0] * XX + ri[0][1] * YY + ri[0][2] * ZZ, + ri[1][0] * XX + ri[1][1] * YY + ri[1][2] * ZZ, + ri[2][0] * XX + ri[2][1] * YY + ri[2][2] * ZZ); } double signed_distance_3d(const Cone &cone, double xx, double yy, double zz) { diff --git a/src/csg/impl/matrix_functions.cpp b/src/csg/impl/matrix_functions.cpp index 8cba487..64dc1c1 100644 --- a/src/csg/impl/matrix_functions.cpp +++ b/src/csg/impl/matrix_functions.cpp @@ -1,18 +1,34 @@ #include "matrix_functions.hpp" namespace { -double determinant(const std::array, 3> &m) { +double determinant(const matrix::Mat2d &m) { + return m[0][0] * m[1][1] - m[1][0] * m[1][1]; +} + +double determinant(const matrix::Mat3d &m) { return m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); } + } // namespace namespace matrix { -std::array, 3> -inverse(const std::array, 3> &m) { - std::array, 3> res; +Mat2d inverse(const Mat2d &m) { + Mat2d res; + double d = 1 / determinant(m); + + res[0][0] = d * m[1][1]; + res[0][1] = -1.0 * d * m[0][1]; + res[1][0] = -1.0 * d * m[1][0]; + res[1][1] = d * m[0][0]; + + return res; +} + +Mat3d inverse(const Mat3d &m) { + Mat3d res; double d = 1 / determinant(m); res[0][0] = d * (m[1][1] * m[2][2] - m[2][1] * m[1][2]); diff --git a/src/csg/impl/matrix_functions.hpp b/src/csg/impl/matrix_functions.hpp index 167bf60..783c3fa 100644 --- a/src/csg/impl/matrix_functions.hpp +++ b/src/csg/impl/matrix_functions.hpp @@ -4,8 +4,11 @@ #include namespace matrix { -std::array, 3> -inverse(const std::array, 3> &m); +using Mat2d = std::array, 2>; +using Mat3d = std::array, 3>; + +Mat2d inverse(const Mat2d &m); +Mat3d inverse(const Mat3d &m); } #endif diff --git a/src/csg/impl/parser.cpp b/src/csg/impl/parser.cpp index d2454de..8dccc6c 100644 --- a/src/csg/impl/parser.cpp +++ b/src/csg/impl/parser.cpp @@ -8,6 +8,7 @@ // includes #include "csg_types.hpp" +#include "matrix_functions.hpp" using namespace tao::pegtl; @@ -385,10 +386,9 @@ template <> struct action> { std::stringstream ss(in.string()); auto mulmat = csg::Mulmatrix2D(); auto mat = st.current_matrices.back(); - // clang-format off mulmat.rotation[0] = {mat[0][0], mat[0][1]}; mulmat.rotation[1] = {mat[1][0], mat[1][1]}; - // clang-format on + mulmat.rotation_inv = ::matrix::inverse(mulmat.rotation); mulmat.translation = { mat[0][3], @@ -409,11 +409,10 @@ template <> struct action> { std::stringstream ss(in.string()); auto mulmat = csg::Mulmatrix3D(); auto mat = st.current_matrices.back(); - // clang-format off mulmat.rotation[0] = {mat[0][0], mat[0][1], mat[0][2]}; mulmat.rotation[1] = {mat[1][0], mat[1][1], mat[1][2]}; mulmat.rotation[2] = {mat[2][0], mat[2][1], mat[2][2]}; - // clang-format on + mulmat.rotation_inv = ::matrix::inverse(mulmat.rotation); mulmat.translation = { mat[0][3], diff --git a/src/csg/tests/levelset/extrude.t.cpp b/src/csg/tests/levelset/extrude.t.cpp index 11769ce..eb59dd0 100644 --- a/src/csg/tests/levelset/extrude.t.cpp +++ b/src/csg/tests/levelset/extrude.t.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace { @@ -14,6 +15,7 @@ TEST_CASE("two shape linear", "[Levelset Extrude]") { auto my_mat = csg::Mulmatrix2D(); my_mat.rotation[0] = std::array{{1, 0}}; my_mat.rotation[1] = std::array{{0, 1}}; + my_mat.rotation_inv = matrix::inverse(my_mat.rotation); my_mat.translation = {4, 0}; my_mat.group.objs.push_back(my_cir); my_lin_ext.group.objs.push_back(my_mat); @@ -44,6 +46,7 @@ TEST_CASE("simple torus", "[Levelset Extrude]") { auto my_mat = csg::Mulmatrix2D(); my_mat.rotation[0] = std::array{{1, 0}}; my_mat.rotation[1] = std::array{{0, 1}}; + my_mat.rotation_inv = matrix::inverse(my_mat.rotation); my_mat.translation = {2, 0}; my_mat.group.objs.push_back(my_cir); my_rot_ext.group.objs.push_back(my_mat); diff --git a/src/csg/tests/levelset/transform.t.cpp b/src/csg/tests/levelset/transform.t.cpp index af6c818..d29453f 100644 --- a/src/csg/tests/levelset/transform.t.cpp +++ b/src/csg/tests/levelset/transform.t.cpp @@ -4,6 +4,7 @@ #include #include +#include namespace { @@ -16,6 +17,7 @@ TEST_CASE("Translation", "[Levelset Transform]") { my_mat.rotation[0] = std::array{{1, 0, 0}}; my_mat.rotation[1] = std::array{{0, 1, 0}}; my_mat.rotation[2] = std::array{{0, 0, 1}}; + my_mat.rotation_inv = matrix::inverse(my_mat.rotation); my_mat.translation = {100, 200, 300}; my_mat.group.objs.push_back(my_cyl); @@ -52,6 +54,7 @@ TEST_CASE("90° Rotation around y-axis, rotating z-axis into x-axis", my_mat.rotation[0] = std::array{{0, 0, 1}}; my_mat.rotation[1] = std::array{{0, 1, 0}}; my_mat.rotation[2] = std::array{{-1, 0, 0}}; + my_mat.rotation_inv = matrix::inverse(my_mat.rotation); my_mat.translation = {0, 0, 0}; my_mat.group.objs.push_back(my_cyl); @@ -100,6 +103,7 @@ TEST_CASE("Orthogonal rotation + translation of cylinder", my_mat.rotation[0] = std::array{{0, 0, 1}}; my_mat.rotation[1] = std::array{{0, 1, 0}}; my_mat.rotation[2] = std::array{{-1, 0, 0}}; + my_mat.rotation_inv = matrix::inverse(my_mat.rotation); my_mat.translation = {Cx, Cy, Cz}; my_mat.group.objs.push_back(my_cyl); -- GitLab From 30a53f32897c19d07799928c020b530b8d633a04 Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Mon, 18 May 2020 10:26:06 -0400 Subject: [PATCH 4/8] fix typo bug --- src/csg/impl/levelset_3d.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/csg/impl/levelset_3d.cpp b/src/csg/impl/levelset_3d.cpp index 8d12a11..1f8c098 100644 --- a/src/csg/impl/levelset_3d.cpp +++ b/src/csg/impl/levelset_3d.cpp @@ -68,8 +68,7 @@ double signed_distance_3d(const Mulmatrix3D &mm, double xx, double yy, auto XX = xx - mm.translation[0]; auto YY = yy - mm.translation[1]; auto ZZ = zz - mm.translation[2]; - const auto &ro = mm.rotation_inv; - auto ri = matrix::inverse(mm.rotation); + const auto &ri = mm.rotation_inv; return signed_distance_3d( mm.group, ri[0][0] * XX + ri[0][1] * YY + ri[0][2] * ZZ, -- GitLab From 8320629b179509a6f1e93a442366e745244eb601 Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Mon, 18 May 2020 12:32:28 -0400 Subject: [PATCH 5/8] more tests --- src/csg/tests/levelset/transform.t.cpp | 116 ++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/src/csg/tests/levelset/transform.t.cpp b/src/csg/tests/levelset/transform.t.cpp index d29453f..30f778b 100644 --- a/src/csg/tests/levelset/transform.t.cpp +++ b/src/csg/tests/levelset/transform.t.cpp @@ -91,7 +91,7 @@ TEST_CASE("90° Rotation around y-axis, rotating z-axis into x-axis", } } -TEST_CASE("Orthogonal rotation + translation of cylinder", +TEST_CASE("90° rotation + translation of cylinder", "[Levelset Transform]") { double radius = 4.5, height = 10; @@ -144,4 +144,118 @@ TEST_CASE("Orthogonal rotation + translation of cylinder", } } +TEST_CASE("45° Rotation around y-axis", "[Levelset Transform]") { + + double side = 20; + csg::Cube my_cub{ + .name = std::nullopt, .size = {side, side, side}, .center = true}; + + auto my_mat = csg::Mulmatrix3D(); + my_mat.rotation[0] = std::array{{0.707107, 0, 0.707107}}; + my_mat.rotation[1] = std::array{{0, 1, 0}}; + my_mat.rotation[2] = std::array{{-0.707107, 0, 0.707107}}; + my_mat.rotation_inv = matrix::inverse(my_mat.rotation); + my_mat.translation = {0, 0, 0}; + my_mat.group.objs.push_back(my_cub); + + auto my_tree = std::make_shared(); + my_tree->top.objs.push_back(my_mat); + csg::CsgIF my_levelset(my_tree); + + SECTION("along x axis") { + CHECK_FALSE(0 < my_levelset(-14.15, 0, 0)); + CHECK(0 < my_levelset(-14.13, 0, 0)); + + CHECK_FALSE(0 < my_levelset(14.15, 0, 0)); + CHECK(0 < my_levelset(14.13, 0, 0)); + + CHECK_FALSE(0 < my_levelset(14.13, 0, 1)); + CHECK(0 < my_levelset(12, 0, 1)); + + CHECK_FALSE(0 < my_levelset(-14.13, 0, 1)); + CHECK(0 < my_levelset(-12, 0, 1)); + + CHECK_FALSE(0 < my_levelset(-14.13, 0, -1)); + CHECK(0 < my_levelset(-12, 0, -1)); + + CHECK_FALSE(0 < my_levelset(14.15, 1, 0)); + CHECK(0 < my_levelset(14.13, 1, 0)); + } + SECTION("along y axis") { + CHECK_FALSE(0 < my_levelset(0, -10.01, 0)); + CHECK(0 < my_levelset(0, -9.99, 0)); + + CHECK_FALSE(0 < my_levelset(0, 10.01, 0)); + CHECK(0 < my_levelset(0, 9.99, 0)); + + CHECK_FALSE(0 < my_levelset(0, 10.01, 1)); + CHECK(0 < my_levelset(0, 9.99, 1)); + + CHECK_FALSE(0 < my_levelset(0, -10.01, -1)); + CHECK(0 < my_levelset(0, -9.99, -1)); + + CHECK_FALSE(0 < my_levelset(1, 10.01, 0)); + CHECK(0 < my_levelset(1, 9.99, 0)); + } + SECTION("along z axis") { + CHECK_FALSE(0 < my_levelset(0, 0, -14.15)); + CHECK(0 < my_levelset(0, 0, -14.13)); + + CHECK_FALSE(0 < my_levelset(0, 0, 14.15)); + CHECK(0 < my_levelset(0, 0, 14.13)); + + CHECK_FALSE(0 < my_levelset(0, 1, 14.15)); + CHECK(0 < my_levelset(0, 1, 14.13)); + + CHECK_FALSE(0 < my_levelset(0, -1, -14.15)); + CHECK(0 < my_levelset(0, -1, -14.13)); + + CHECK_FALSE(0 < my_levelset(1, 0, 14.13)); + CHECK(0 < my_levelset(1, 0, 12)); + } +} + +TEST_CASE("Skewed with shear y along z", "[Levelset Transform]") { + double radius = 10, height = 10; + double skew_yz = 0.7; + + csg::Cylinder my_cyl{.name = std::nullopt, .radius = radius, .height = height, .center = false}; + + auto my_mat = csg::Mulmatrix3D(); + my_mat.rotation[0] = std::array{{1, 0, 0}}; + my_mat.rotation[1] = std::array{{0, 1, 0.7}}; + my_mat.rotation[2] = std::array{{0, 0, 1}}; + my_mat.rotation_inv = matrix::inverse(my_mat.rotation); + my_mat.translation = {0, 0, 0}; + my_mat.group.objs.push_back(my_cyl); + + auto my_tree = std::make_shared(); + my_tree->top.objs.push_back(my_mat); + csg::CsgIF my_levelset(my_tree); + + auto check = [radius, &my_levelset](double Cx, double Cy, double Cz) { + CHECK_FALSE(0 < my_levelset(Cx + radius * 1.01, Cy, Cz)); + CHECK(0 < my_levelset(Cx + radius * 0.99, Cy, Cz)); + + CHECK_FALSE(0 < my_levelset(Cx, Cy + 1.01 * radius, Cz)); + CHECK(0 < my_levelset(Cx, Cy + radius * 0.99, Cz)); + + CHECK_FALSE(0 < my_levelset(Cx, Cy + 1.01 * radius, Cz)); + CHECK(0 < my_levelset(Cx, Cy + radius * 0.99, Cz)); + + CHECK_FALSE(0 < my_levelset(Cx, Cy - 1.01 * radius, Cz)); + CHECK(0 < my_levelset(Cx, Cy - radius * 0.99, Cz)); + }; + + SECTION("near lower end") { + check(0, 0, 0.01); + } + SECTION("near middle") { + check(0, skew_yz * 4.99, 4.99); + } + SECTION("near upper end") { + check(0, skew_yz * 9.99, 9.99); + } +} + } // namespace -- GitLab From 370e9cd45587b067a9b62b2b172eb8393ed728c0 Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Mon, 18 May 2020 12:34:25 -0400 Subject: [PATCH 6/8] formatting --- src/csg/impl/levelset_2d.cpp | 3 +-- src/csg/impl/levelset_3d.cpp | 11 +++++------ src/csg/tests/levelset/transform.t.cpp | 22 +++++++++------------- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/csg/impl/levelset_2d.cpp b/src/csg/impl/levelset_2d.cpp index bb6a6c7..aeb0b52 100644 --- a/src/csg/impl/levelset_2d.cpp +++ b/src/csg/impl/levelset_2d.cpp @@ -58,8 +58,7 @@ double signed_distance_2d(const Mulmatrix2D &mm, double xx, double yy) { auto XX = xx - mm.translation[0]; auto YY = yy - mm.translation[1]; const auto &ri = mm.rotation_inv; - return signed_distance_2d(mm.group, - ri[0][0] * XX + ri[0][1] * YY, + return signed_distance_2d(mm.group, ri[0][0] * XX + ri[0][1] * YY, ri[1][0] * XX + ri[1][1] * YY); } diff --git a/src/csg/impl/levelset_3d.cpp b/src/csg/impl/levelset_3d.cpp index 1f8c098..7ec4e71 100644 --- a/src/csg/impl/levelset_3d.cpp +++ b/src/csg/impl/levelset_3d.cpp @@ -68,12 +68,11 @@ double signed_distance_3d(const Mulmatrix3D &mm, double xx, double yy, auto XX = xx - mm.translation[0]; auto YY = yy - mm.translation[1]; auto ZZ = zz - mm.translation[2]; - const auto &ri = mm.rotation_inv; - return signed_distance_3d( - mm.group, - ri[0][0] * XX + ri[0][1] * YY + ri[0][2] * ZZ, - ri[1][0] * XX + ri[1][1] * YY + ri[1][2] * ZZ, - ri[2][0] * XX + ri[2][1] * YY + ri[2][2] * ZZ); + const auto &ri = mm.rotation_inv; + return signed_distance_3d(mm.group, + ri[0][0] * XX + ri[0][1] * YY + ri[0][2] * ZZ, + ri[1][0] * XX + ri[1][1] * YY + ri[1][2] * ZZ, + ri[2][0] * XX + ri[2][1] * YY + ri[2][2] * ZZ); } double signed_distance_3d(const Cone &cone, double xx, double yy, double zz) { diff --git a/src/csg/tests/levelset/transform.t.cpp b/src/csg/tests/levelset/transform.t.cpp index 30f778b..f80af0e 100644 --- a/src/csg/tests/levelset/transform.t.cpp +++ b/src/csg/tests/levelset/transform.t.cpp @@ -91,8 +91,7 @@ TEST_CASE("90° Rotation around y-axis, rotating z-axis into x-axis", } } -TEST_CASE("90° rotation + translation of cylinder", - "[Levelset Transform]") { +TEST_CASE("90° rotation + translation of cylinder", "[Levelset Transform]") { double radius = 4.5, height = 10; double Cx = 10, Cy = 5, Cz = 5; @@ -219,7 +218,10 @@ TEST_CASE("Skewed with shear y along z", "[Levelset Transform]") { double radius = 10, height = 10; double skew_yz = 0.7; - csg::Cylinder my_cyl{.name = std::nullopt, .radius = radius, .height = height, .center = false}; + csg::Cylinder my_cyl{.name = std::nullopt, + .radius = radius, + .height = height, + .center = false}; auto my_mat = csg::Mulmatrix3D(); my_mat.rotation[0] = std::array{{1, 0, 0}}; @@ -244,18 +246,12 @@ TEST_CASE("Skewed with shear y along z", "[Levelset Transform]") { CHECK(0 < my_levelset(Cx, Cy + radius * 0.99, Cz)); CHECK_FALSE(0 < my_levelset(Cx, Cy - 1.01 * radius, Cz)); - CHECK(0 < my_levelset(Cx, Cy - radius * 0.99, Cz)); + CHECK(0 < my_levelset(Cx, Cy - radius * 0.99, Cz)); }; - SECTION("near lower end") { - check(0, 0, 0.01); - } - SECTION("near middle") { - check(0, skew_yz * 4.99, 4.99); - } - SECTION("near upper end") { - check(0, skew_yz * 9.99, 9.99); - } + SECTION("near lower end") { check(0, 0, 0.01); } + SECTION("near middle") { check(0, skew_yz * 4.99, 4.99); } + SECTION("near upper end") { check(0, skew_yz * 9.99, 9.99); } } } // namespace -- GitLab From 0471538dd0e3cb6e638f21ba1dab706a56117a21 Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Mon, 18 May 2020 12:44:26 -0400 Subject: [PATCH 7/8] remove include not needed --- src/csg/impl/levelset_3d.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/csg/impl/levelset_3d.cpp b/src/csg/impl/levelset_3d.cpp index 7ec4e71..9c60790 100644 --- a/src/csg/impl/levelset_3d.cpp +++ b/src/csg/impl/levelset_3d.cpp @@ -1,5 +1,4 @@ #include "csg_types.hpp" -#include "matrix_functions.hpp" #include #include -- GitLab From a617ae2290c749730a8f419e2e1add2dea5ffb00 Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Mon, 18 May 2020 17:09:31 -0400 Subject: [PATCH 8/8] review changes --- src/csg/impl/csg_types.hpp | 40 +++++++++++++++++++++++--- src/csg/impl/levelset_2d.cpp | 2 +- src/csg/impl/levelset_3d.cpp | 2 +- src/csg/impl/matrix_functions.cpp | 6 ++-- src/csg/impl/matrix_functions.hpp | 2 +- src/csg/impl/parser.cpp | 15 ++++------ src/csg/tests/levelset/extrude.t.cpp | 10 ++----- src/csg/tests/levelset/transform.t.cpp | 31 ++++---------------- 8 files changed, 55 insertions(+), 53 deletions(-) diff --git a/src/csg/impl/csg_types.hpp b/src/csg/impl/csg_types.hpp index c17b61c..c1725fe 100644 --- a/src/csg/impl/csg_types.hpp +++ b/src/csg/impl/csg_types.hpp @@ -1,6 +1,8 @@ #ifndef CSG_TYPES_H_ #define CSG_TYPES_H_ +#include "matrix_functions.hpp" + #include #include #include @@ -86,17 +88,47 @@ template struct Difference { }; template <> struct Mulmatrix { - std::array, 3> rotation; - std::array, 3> rotation_inv; +private: + matrix::Mat3d m_rotation; + matrix::Mat3d m_rotation_inv; + +public: std::array translation; Union group; + + Mulmatrix(const std::array &rot_row0, + const std::array &rot_row1, + const std::array &rot_row2) { + m_rotation[0] = rot_row0; + m_rotation[1] = rot_row1; + m_rotation[2] = rot_row2; + m_rotation_inv = matrix::inverse(m_rotation); + } + + const matrix::Mat3d &rotation() const { return m_rotation; } + + const matrix::Mat3d &rotation_inv() const { return m_rotation_inv; } }; template <> struct Mulmatrix { - std::array, 2> rotation; - std::array, 2> rotation_inv; +private: + matrix::Mat2d m_rotation; + matrix::Mat2d m_rotation_inv; + +public: std::array translation; Union group; + + Mulmatrix(const std::array &rot_row0, + const std::array &rot_row1) { + m_rotation[0] = rot_row0; + m_rotation[1] = rot_row1; + m_rotation_inv = matrix::inverse(m_rotation); + } + + const matrix::Mat2d &rotation() const { return m_rotation; } + + const matrix::Mat2d &rotation_inv() const { return m_rotation_inv; } }; struct LinearExtrude { diff --git a/src/csg/impl/levelset_2d.cpp b/src/csg/impl/levelset_2d.cpp index aeb0b52..3eff418 100644 --- a/src/csg/impl/levelset_2d.cpp +++ b/src/csg/impl/levelset_2d.cpp @@ -57,7 +57,7 @@ double signed_distance_2d(const Difference2D &group, double xx, double yy) { double signed_distance_2d(const Mulmatrix2D &mm, double xx, double yy) { auto XX = xx - mm.translation[0]; auto YY = yy - mm.translation[1]; - const auto &ri = mm.rotation_inv; + auto ri = mm.rotation_inv(); return signed_distance_2d(mm.group, ri[0][0] * XX + ri[0][1] * YY, ri[1][0] * XX + ri[1][1] * YY); } diff --git a/src/csg/impl/levelset_3d.cpp b/src/csg/impl/levelset_3d.cpp index 9c60790..3216138 100644 --- a/src/csg/impl/levelset_3d.cpp +++ b/src/csg/impl/levelset_3d.cpp @@ -67,7 +67,7 @@ double signed_distance_3d(const Mulmatrix3D &mm, double xx, double yy, auto XX = xx - mm.translation[0]; auto YY = yy - mm.translation[1]; auto ZZ = zz - mm.translation[2]; - const auto &ri = mm.rotation_inv; + auto ri = mm.rotation_inv(); return signed_distance_3d(mm.group, ri[0][0] * XX + ri[0][1] * YY + ri[0][2] * ZZ, ri[1][0] * XX + ri[1][1] * YY + ri[1][2] * ZZ, diff --git a/src/csg/impl/matrix_functions.cpp b/src/csg/impl/matrix_functions.cpp index 64dc1c1..4c0159d 100644 --- a/src/csg/impl/matrix_functions.cpp +++ b/src/csg/impl/matrix_functions.cpp @@ -6,9 +6,9 @@ double determinant(const matrix::Mat2d &m) { } double determinant(const matrix::Mat3d &m) { - return m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) - - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) + - m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); + return m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + + m[0][1] * (m[1][2] * m[2][0] - m[2][2] * m[1][0]) + + m[0][2] * (m[1][0] * m[2][1] - m[2][0] * m[1][1]); } } // namespace diff --git a/src/csg/impl/matrix_functions.hpp b/src/csg/impl/matrix_functions.hpp index 783c3fa..b500cd4 100644 --- a/src/csg/impl/matrix_functions.hpp +++ b/src/csg/impl/matrix_functions.hpp @@ -9,6 +9,6 @@ using Mat3d = std::array, 3>; Mat2d inverse(const Mat2d &m); Mat3d inverse(const Mat3d &m); -} +} // namespace matrix #endif diff --git a/src/csg/impl/parser.cpp b/src/csg/impl/parser.cpp index 8dccc6c..22417da 100644 --- a/src/csg/impl/parser.cpp +++ b/src/csg/impl/parser.cpp @@ -8,7 +8,6 @@ // includes #include "csg_types.hpp" -#include "matrix_functions.hpp" using namespace tao::pegtl; @@ -384,11 +383,9 @@ template <> struct action> { template static void apply(const Input &in, parser_state &st) { std::stringstream ss(in.string()); - auto mulmat = csg::Mulmatrix2D(); auto mat = st.current_matrices.back(); - mulmat.rotation[0] = {mat[0][0], mat[0][1]}; - mulmat.rotation[1] = {mat[1][0], mat[1][1]}; - mulmat.rotation_inv = ::matrix::inverse(mulmat.rotation); + auto mulmat = + csg::Mulmatrix2D({{mat[0][0], mat[0][1]}}, {{mat[1][0], mat[1][1]}}); mulmat.translation = { mat[0][3], @@ -407,12 +404,10 @@ template <> struct action> { template static void apply(const Input &in, parser_state &st) { std::stringstream ss(in.string()); - auto mulmat = csg::Mulmatrix3D(); auto mat = st.current_matrices.back(); - mulmat.rotation[0] = {mat[0][0], mat[0][1], mat[0][2]}; - mulmat.rotation[1] = {mat[1][0], mat[1][1], mat[1][2]}; - mulmat.rotation[2] = {mat[2][0], mat[2][1], mat[2][2]}; - mulmat.rotation_inv = ::matrix::inverse(mulmat.rotation); + auto mulmat = csg::Mulmatrix3D({{mat[0][0], mat[0][1], mat[0][2]}}, + {{mat[1][0], mat[1][1], mat[1][2]}}, + {{mat[2][0], mat[2][1], mat[2][2]}}); mulmat.translation = { mat[0][3], diff --git a/src/csg/tests/levelset/extrude.t.cpp b/src/csg/tests/levelset/extrude.t.cpp index eb59dd0..5938db2 100644 --- a/src/csg/tests/levelset/extrude.t.cpp +++ b/src/csg/tests/levelset/extrude.t.cpp @@ -12,10 +12,7 @@ TEST_CASE("two shape linear", "[Levelset Extrude]") { csg::Circle my_cir{.name = std::nullopt, .radius = 1}; my_lin_ext.group.objs.push_back(my_cir); - auto my_mat = csg::Mulmatrix2D(); - my_mat.rotation[0] = std::array{{1, 0}}; - my_mat.rotation[1] = std::array{{0, 1}}; - my_mat.rotation_inv = matrix::inverse(my_mat.rotation); + auto my_mat = csg::Mulmatrix2D({{1, 0}}, {{0, 1}}); my_mat.translation = {4, 0}; my_mat.group.objs.push_back(my_cir); my_lin_ext.group.objs.push_back(my_mat); @@ -43,10 +40,7 @@ TEST_CASE("simple torus", "[Levelset Extrude]") { auto my_rot_ext = csg::RotateExtrude(); csg::Circle my_cir{.name = std::nullopt, .radius = 1}; - auto my_mat = csg::Mulmatrix2D(); - my_mat.rotation[0] = std::array{{1, 0}}; - my_mat.rotation[1] = std::array{{0, 1}}; - my_mat.rotation_inv = matrix::inverse(my_mat.rotation); + auto my_mat = csg::Mulmatrix2D({{1, 0}}, {{0, 1}}); my_mat.translation = {2, 0}; my_mat.group.objs.push_back(my_cir); my_rot_ext.group.objs.push_back(my_mat); diff --git a/src/csg/tests/levelset/transform.t.cpp b/src/csg/tests/levelset/transform.t.cpp index f80af0e..0123c6c 100644 --- a/src/csg/tests/levelset/transform.t.cpp +++ b/src/csg/tests/levelset/transform.t.cpp @@ -13,11 +13,7 @@ TEST_CASE("Translation", "[Levelset Transform]") { csg::Cylinder my_cyl{ .name = std::nullopt, .radius = 2, .height = 20, .center = true}; - auto my_mat = csg::Mulmatrix3D(); - my_mat.rotation[0] = std::array{{1, 0, 0}}; - my_mat.rotation[1] = std::array{{0, 1, 0}}; - my_mat.rotation[2] = std::array{{0, 0, 1}}; - my_mat.rotation_inv = matrix::inverse(my_mat.rotation); + auto my_mat = csg::Mulmatrix3D({{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}); my_mat.translation = {100, 200, 300}; my_mat.group.objs.push_back(my_cyl); @@ -50,11 +46,7 @@ TEST_CASE("90° Rotation around y-axis, rotating z-axis into x-axis", csg::Cylinder my_cyl{ .name = std::nullopt, .radius = 2, .height = 20, .center = false}; - auto my_mat = csg::Mulmatrix3D(); - my_mat.rotation[0] = std::array{{0, 0, 1}}; - my_mat.rotation[1] = std::array{{0, 1, 0}}; - my_mat.rotation[2] = std::array{{-1, 0, 0}}; - my_mat.rotation_inv = matrix::inverse(my_mat.rotation); + auto my_mat = csg::Mulmatrix3D({{0, 0, 1}}, {{0, 1, 0}}, {{-1, 0, 0}}); my_mat.translation = {0, 0, 0}; my_mat.group.objs.push_back(my_cyl); @@ -98,11 +90,7 @@ TEST_CASE("90° rotation + translation of cylinder", "[Levelset Transform]") { csg::Cylinder my_cyl{ .name = std::nullopt, .radius = radius, .height = height, .center = true}; - auto my_mat = csg::Mulmatrix3D(); - my_mat.rotation[0] = std::array{{0, 0, 1}}; - my_mat.rotation[1] = std::array{{0, 1, 0}}; - my_mat.rotation[2] = std::array{{-1, 0, 0}}; - my_mat.rotation_inv = matrix::inverse(my_mat.rotation); + auto my_mat = csg::Mulmatrix3D({{0, 0, 1}}, {{0, 1, 0}}, {{-1, 0, 0}}); my_mat.translation = {Cx, Cy, Cz}; my_mat.group.objs.push_back(my_cyl); @@ -149,11 +137,8 @@ TEST_CASE("45° Rotation around y-axis", "[Levelset Transform]") { csg::Cube my_cub{ .name = std::nullopt, .size = {side, side, side}, .center = true}; - auto my_mat = csg::Mulmatrix3D(); - my_mat.rotation[0] = std::array{{0.707107, 0, 0.707107}}; - my_mat.rotation[1] = std::array{{0, 1, 0}}; - my_mat.rotation[2] = std::array{{-0.707107, 0, 0.707107}}; - my_mat.rotation_inv = matrix::inverse(my_mat.rotation); + auto my_mat = csg::Mulmatrix3D({{0.707107, 0, 0.707107}}, {{0, 1, 0}}, + {{-0.707107, 0, 0.707107}}); my_mat.translation = {0, 0, 0}; my_mat.group.objs.push_back(my_cub); @@ -223,11 +208,7 @@ TEST_CASE("Skewed with shear y along z", "[Levelset Transform]") { .height = height, .center = false}; - auto my_mat = csg::Mulmatrix3D(); - my_mat.rotation[0] = std::array{{1, 0, 0}}; - my_mat.rotation[1] = std::array{{0, 1, 0.7}}; - my_mat.rotation[2] = std::array{{0, 0, 1}}; - my_mat.rotation_inv = matrix::inverse(my_mat.rotation); + auto my_mat = csg::Mulmatrix3D({{1, 0, 0}}, {{0, 1, 0.7}}, {{0, 0, 1}}); my_mat.translation = {0, 0, 0}; my_mat.group.objs.push_back(my_cyl); -- GitLab