Loading include/csg.hpp +7 −2 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ std::shared_ptr<Tree> parse_csg(std::string); class CsgIF : GPUable { public: CsgIF(std::shared_ptr<Tree> a_state); CsgIF(std::shared_ptr<Tree> a_state, bool is_internal_flow = false); CsgIF(const CsgIF &rhs); CsgIF(CsgIF &&rhs) noexcept; CsgIF &operator=(const CsgIF &rhs) = delete; Loading @@ -42,13 +42,18 @@ public: private: std::shared_ptr<Tree> m_state; bool m_is_internal_flow; class Impl; std::unique_ptr<Impl> m_pimpl; }; std::shared_ptr<csg::Tree> get_csgtree_from_filename(std::string); std::unique_ptr<CsgIF> get_csgif_from_filename(std::string geom_file); std::unique_ptr<CsgIF> get_csgif_from_filename(std::string geom_file); // TODO: Deprecate once mfix has // stopped using this call std::unique_ptr<CsgIF> get_csgif(const std::string &geom_file, bool is_internal_flow = false); } // namespace csg Loading src/csg/csg.cpp +23 −4 Original line number Diff line number Diff line Loading @@ -42,16 +42,22 @@ public: }; CsgIF::CsgIF(const CsgIF &rhs) : m_state(rhs.m_state), m_pimpl(std::make_unique<Impl>(*rhs.m_pimpl)) {} : m_state(rhs.m_state), m_is_internal_flow(rhs.m_is_internal_flow), m_pimpl(std::make_unique<Impl>(*rhs.m_pimpl)) {} CsgIF::CsgIF(std::shared_ptr<Tree> a_state) : m_state(a_state), m_pimpl(std::make_unique<Impl>()) {} CsgIF::CsgIF(std::shared_ptr<Tree> a_state, bool is_internal_flow) : m_state(a_state), m_is_internal_flow(is_internal_flow), m_pimpl(std::make_unique<Impl>()) {} CsgIF::CsgIF(CsgIF &&rhs) noexcept = default; CsgIF::~CsgIF() = default; double CsgIF::operator()(double xx, double yy, double zz) const noexcept { return m_pimpl->call_signed_distance(m_state, xx, yy, zz); auto sd = m_pimpl->call_signed_distance(m_state, xx, yy, zz); if (m_is_internal_flow) { return -sd; } return sd; } std::shared_ptr<csg::Tree> get_csgtree_from_filename(std::string geom_file) { Loading @@ -75,4 +81,17 @@ std::unique_ptr<CsgIF> get_csgif_from_filename(std::string geom_file) { return std::make_unique<CsgIF>(csg_if); } std::unique_ptr<CsgIF> get_csgif(const std::string &geom_file, bool is_internal_flow) { auto csg_obj = get_csgtree_from_filename(geom_file); if (!csg_obj) { std::cout << "Failed to parse .csg file: " << geom_file << std::endl; return nullptr; } csg::CsgIF csg_if(csg_obj, is_internal_flow); return std::make_unique<CsgIF>(csg_if); } } // namespace csg src/csg/tests/CMakeLists.txt +1 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ add_executable(unit_tests_csg EXCLUDE_FROM_ALL levelset/extrude.t.cpp levelset/primitives.t.cpp levelset/transform.t.cpp levelset/internal_flow.t.cpp parser/boolean.t.cpp parser/extrude.t.cpp parser/nest.cpp Loading src/csg/tests/levelset/internal_flow.t.cpp 0 → 100644 +71 −0 Original line number Diff line number Diff line #include "catch2/catch.hpp" #include <csg.hpp> #include <csg_types.hpp> #include <memory> namespace { TEST_CASE("union internal flow", "[Levelset Internal Flow]") { // Create a union of a cube of size 12 and a sphere of radius 8 csg::Cube my_cub{.name = std::nullopt, .size = {12, 12, 12}, .center = true}; csg::Sphere my_sph{.name = std::nullopt, .radius = 8}; auto my_union = csg::Union3D(); my_union.objs.push_back(my_cub); my_union.objs.push_back(my_sph); auto my_tree = std::make_shared<csg::Tree>(); my_tree->top.objs.push_back(my_union); csg::CsgIF my_ls(my_tree); csg::CsgIF my_ls_comp(my_tree, true); auto check = [&my_ls, &my_ls_comp](double xx, double yy, double zz) { CHECK(my_ls(xx, yy, zz) == -my_ls_comp(xx, yy, zz)); }; SECTION("Inside") { check(0, 7, 0); check(0, 0, -7.5); } SECTION("Outside") { check(0, -9, 0); check(9, 0, 0); } } TEST_CASE("CsgIF copy constructor", "[Levelset Internal Flow]") { csg::Sphere my_sph{.name = std::nullopt, .radius = 10}; auto my_tree = std::make_shared<csg::Tree>(); my_tree->top.objs.push_back(my_sph); csg::CsgIF my_ls1(my_tree); csg::CsgIF my_ls2(my_ls1); csg::CsgIF my_ls_comp1(my_tree, true); csg::CsgIF my_ls_comp2(my_ls_comp1); auto check = [&my_ls1, &my_ls2, &my_ls_comp1, &my_ls_comp2](double xx, double yy, double zz) { CHECK(my_ls1(xx, yy, zz) == my_ls2(xx, yy, zz)); CHECK(my_ls_comp1(xx, yy, zz) == my_ls_comp2(xx, yy, zz)); CHECK(my_ls1(xx, yy, zz) == -my_ls_comp1(xx, yy, zz)); CHECK(my_ls2(xx, yy, zz) == -my_ls_comp2(xx, yy, zz)); }; SECTION("Outside") { check(0, 8, 8); check(-8, 0, 8); check(0, 8, -8); } SECTION("Inside") { check(0, 0, 0); check(0, 7, 7); check(-7, 0, 7); check(-7, 0, 7); check(0, 7, -7); } } } // namespace src/csg/tests/meson.build +1 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ test_csg = executable( 'levelset/extrude.t.cpp', 'levelset/primitives.t.cpp', 'levelset/transform.t.cpp', 'levelset/internal_flow.t.cpp', 'parser/boolean.t.cpp', 'parser/extrude.t.cpp', 'parser/nest.cpp', Loading Loading
include/csg.hpp +7 −2 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ std::shared_ptr<Tree> parse_csg(std::string); class CsgIF : GPUable { public: CsgIF(std::shared_ptr<Tree> a_state); CsgIF(std::shared_ptr<Tree> a_state, bool is_internal_flow = false); CsgIF(const CsgIF &rhs); CsgIF(CsgIF &&rhs) noexcept; CsgIF &operator=(const CsgIF &rhs) = delete; Loading @@ -42,13 +42,18 @@ public: private: std::shared_ptr<Tree> m_state; bool m_is_internal_flow; class Impl; std::unique_ptr<Impl> m_pimpl; }; std::shared_ptr<csg::Tree> get_csgtree_from_filename(std::string); std::unique_ptr<CsgIF> get_csgif_from_filename(std::string geom_file); std::unique_ptr<CsgIF> get_csgif_from_filename(std::string geom_file); // TODO: Deprecate once mfix has // stopped using this call std::unique_ptr<CsgIF> get_csgif(const std::string &geom_file, bool is_internal_flow = false); } // namespace csg Loading
src/csg/csg.cpp +23 −4 Original line number Diff line number Diff line Loading @@ -42,16 +42,22 @@ public: }; CsgIF::CsgIF(const CsgIF &rhs) : m_state(rhs.m_state), m_pimpl(std::make_unique<Impl>(*rhs.m_pimpl)) {} : m_state(rhs.m_state), m_is_internal_flow(rhs.m_is_internal_flow), m_pimpl(std::make_unique<Impl>(*rhs.m_pimpl)) {} CsgIF::CsgIF(std::shared_ptr<Tree> a_state) : m_state(a_state), m_pimpl(std::make_unique<Impl>()) {} CsgIF::CsgIF(std::shared_ptr<Tree> a_state, bool is_internal_flow) : m_state(a_state), m_is_internal_flow(is_internal_flow), m_pimpl(std::make_unique<Impl>()) {} CsgIF::CsgIF(CsgIF &&rhs) noexcept = default; CsgIF::~CsgIF() = default; double CsgIF::operator()(double xx, double yy, double zz) const noexcept { return m_pimpl->call_signed_distance(m_state, xx, yy, zz); auto sd = m_pimpl->call_signed_distance(m_state, xx, yy, zz); if (m_is_internal_flow) { return -sd; } return sd; } std::shared_ptr<csg::Tree> get_csgtree_from_filename(std::string geom_file) { Loading @@ -75,4 +81,17 @@ std::unique_ptr<CsgIF> get_csgif_from_filename(std::string geom_file) { return std::make_unique<CsgIF>(csg_if); } std::unique_ptr<CsgIF> get_csgif(const std::string &geom_file, bool is_internal_flow) { auto csg_obj = get_csgtree_from_filename(geom_file); if (!csg_obj) { std::cout << "Failed to parse .csg file: " << geom_file << std::endl; return nullptr; } csg::CsgIF csg_if(csg_obj, is_internal_flow); return std::make_unique<CsgIF>(csg_if); } } // namespace csg
src/csg/tests/CMakeLists.txt +1 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ add_executable(unit_tests_csg EXCLUDE_FROM_ALL levelset/extrude.t.cpp levelset/primitives.t.cpp levelset/transform.t.cpp levelset/internal_flow.t.cpp parser/boolean.t.cpp parser/extrude.t.cpp parser/nest.cpp Loading
src/csg/tests/levelset/internal_flow.t.cpp 0 → 100644 +71 −0 Original line number Diff line number Diff line #include "catch2/catch.hpp" #include <csg.hpp> #include <csg_types.hpp> #include <memory> namespace { TEST_CASE("union internal flow", "[Levelset Internal Flow]") { // Create a union of a cube of size 12 and a sphere of radius 8 csg::Cube my_cub{.name = std::nullopt, .size = {12, 12, 12}, .center = true}; csg::Sphere my_sph{.name = std::nullopt, .radius = 8}; auto my_union = csg::Union3D(); my_union.objs.push_back(my_cub); my_union.objs.push_back(my_sph); auto my_tree = std::make_shared<csg::Tree>(); my_tree->top.objs.push_back(my_union); csg::CsgIF my_ls(my_tree); csg::CsgIF my_ls_comp(my_tree, true); auto check = [&my_ls, &my_ls_comp](double xx, double yy, double zz) { CHECK(my_ls(xx, yy, zz) == -my_ls_comp(xx, yy, zz)); }; SECTION("Inside") { check(0, 7, 0); check(0, 0, -7.5); } SECTION("Outside") { check(0, -9, 0); check(9, 0, 0); } } TEST_CASE("CsgIF copy constructor", "[Levelset Internal Flow]") { csg::Sphere my_sph{.name = std::nullopt, .radius = 10}; auto my_tree = std::make_shared<csg::Tree>(); my_tree->top.objs.push_back(my_sph); csg::CsgIF my_ls1(my_tree); csg::CsgIF my_ls2(my_ls1); csg::CsgIF my_ls_comp1(my_tree, true); csg::CsgIF my_ls_comp2(my_ls_comp1); auto check = [&my_ls1, &my_ls2, &my_ls_comp1, &my_ls_comp2](double xx, double yy, double zz) { CHECK(my_ls1(xx, yy, zz) == my_ls2(xx, yy, zz)); CHECK(my_ls_comp1(xx, yy, zz) == my_ls_comp2(xx, yy, zz)); CHECK(my_ls1(xx, yy, zz) == -my_ls_comp1(xx, yy, zz)); CHECK(my_ls2(xx, yy, zz) == -my_ls_comp2(xx, yy, zz)); }; SECTION("Outside") { check(0, 8, 8); check(-8, 0, 8); check(0, 8, -8); } SECTION("Inside") { check(0, 0, 0); check(0, 7, 7); check(-7, 0, 7); check(-7, 0, 7); check(0, 7, -7); } } } // namespace
src/csg/tests/meson.build +1 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ test_csg = executable( 'levelset/extrude.t.cpp', 'levelset/primitives.t.cpp', 'levelset/transform.t.cpp', 'levelset/internal_flow.t.cpp', 'parser/boolean.t.cpp', 'parser/extrude.t.cpp', 'parser/nest.cpp', Loading