From c7ecb2bb5cd46c783ed2a45caf1780b1483ece06 Mon Sep 17 00:00:00 2001 From: Zhicheng Wang <1627343141@qq.com> Date: Tue, 16 Jun 2026 18:40:36 +0800 Subject: [PATCH] refactor: subface hashing with quadrics character and heter_array - Replace struct-based hasher/eq_compare with inline method definitions - Introduce get_quadrics_character() for unified quadric surface identity - Add get_plane_character() for plane surface identity - Replace std::variant pair arrays with heter_array in data_center - Add heter_array utility container --- .../interface/data/data_center.hpp | 20 ++++--- .../interface/data/data_type.hpp | 41 ++++++++------ .../interface/subface/simple/cone_face.hpp | 43 +++++++-------- .../subface/simple/cylinder_face.hpp | 54 +++++++------------ .../interface/subface/simple/plane.hpp | 39 +++++++------- .../interface/subface/simple/sphere_face.hpp | 27 ++++++---- primitive_process/src/data/data_center.cpp | 45 ++++++++-------- .../src/subface/simple/cone_face.cpp | 10 +--- .../src/subface/simple/cylinder_face.cpp | 9 +--- .../src/subface/simple/plane.cpp | 2 +- .../src/subface/simple/sphere_face.cpp | 9 +--- .../container/wrapper/heter_array.hpp | 43 +++++++++++++++ 12 files changed, 178 insertions(+), 164 deletions(-) create mode 100644 shared_module/container/wrapper/heter_array.hpp diff --git a/primitive_process/interface/data/data_center.hpp b/primitive_process/interface/data/data_center.hpp index 3b326a9..f83b398 100644 --- a/primitive_process/interface/data/data_center.hpp +++ b/primitive_process/interface/data/data_center.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "primitive/simple/sphere.hpp" #include "primitive/simple/cylinder.hpp" @@ -25,9 +26,8 @@ using polyline_pattern_container_t = flat_object_set EXTERN_C struct PE_API primitive_data_center_t { // all other data depend on cached transform_blocks - using surface_containers = - std::variant; - std::array(surface_type::max_count)> surfaces{}; + heter_array + surfaces{}; void require_surface(surface_type type, const internal::paired_model_matrix& matrix, @@ -35,15 +35,13 @@ EXTERN_C struct PE_API primitive_data_center_t { marked_subface_ptr_t& subface); void release_surface(surface_type type, const marked_subface_ptr_t& subface); - using axis_containers = std::variant; - std::array axes{}; - internal::extrude_axis* require_axis(axis_type type, const internal::extrude_axis& temp_axis_ptr); - void release_axis(axis_type type, const pointer_wrapper& axis); + heter_array axes{}; + internal::extrude_axis* require_axis(axis_type type, const internal::extrude_axis& temp_axis_ptr); + void release_axis(axis_type type, const pointer_wrapper& axis); - using pattern_containers = std::variant; - std::array patterns{}; - internal::pattern* require_pattern(pattern_type type, const internal::pattern& temp_pattern_ptr); - void release_pattern(pattern_type type, const pointer_wrapper& pattern); + heter_array patterns{}; + internal::pattern* require_pattern(pattern_type type, const internal::pattern& temp_pattern_ptr); + void release_pattern(pattern_type type, const pointer_wrapper& pattern); }; namespace internal diff --git a/primitive_process/interface/data/data_type.hpp b/primitive_process/interface/data/data_type.hpp index 13a8796..f1cab99 100644 --- a/primitive_process/interface/data/data_type.hpp +++ b/primitive_process/interface/data/data_type.hpp @@ -40,23 +40,32 @@ enum class surface_type : uint8_t { plane, sphere, cylinder, cone, extrude_side, namespace detail { template <> -struct hasher { - size_t operator()(const internal::transform_block& block) const { return hash_funcs(block); } -}; +inline size_t hasher::operator()(const internal::transform_block& block) const +{ + return hash_funcs(block); +} template <> -struct hasher { - size_t operator()(const internal::paired_model_matrix& paired_matrix) const - { - return hash_funcs(paired_matrix.local_to_world); - } -}; +inline size_t hasher::operator()(const internal::paired_model_matrix& paired_matrix) const +{ + return hash_funcs(paired_matrix.local_to_world); +} -template -struct tagged_hasher { - size_t operator()(const internal::paired_model_matrix& paired_matrix) const - { - return hash_funcs(paired_matrix.local_to_world); - } -}; +inline auto get_quadrics_character(Eigen::Vector4d std_diag, const internal::paired_model_matrix& paired_matrix) +{ + Eigen::Matrix4d temp{}; + temp.leftCols<3>() = paired_matrix.world_to_local.matrix().transpose(); + temp(3, 3) = 1.; + temp = temp * std_diag.asDiagonal() * temp.transpose(); + temp /= temp.diagonal().head<3>().norm(); + return temp; +} + +// template +// struct tagged_hasher { +// size_t operator()(const internal::paired_model_matrix& paired_matrix) const +// { +// return hash_funcs(paired_matrix.local_to_world); +// } +// }; } // namespace detail \ No newline at end of file diff --git a/primitive_process/interface/subface/simple/cone_face.hpp b/primitive_process/interface/subface/simple/cone_face.hpp index 61c9fd7..9319414 100644 --- a/primitive_process/interface/subface/simple/cone_face.hpp +++ b/primitive_process/interface/subface/simple/cone_face.hpp @@ -12,32 +12,25 @@ struct cone_face_t final : subface { namespace detail { +// Q' = M^{-T}QM^{-1} +// Q = { +// 1, 0, 0, 0 +// 0, 1, 0, 0 +// 0, 0, -1, 0 +// 0, 0, 0, 0 +// } +const Eigen::Vector4d cone_std_diag{1, 1, -1, 0}; + template <> -struct hasher { - // Q' = M^{-T}QM^{-1} - // Q = { - // 1, 0, 0, 0 - // 0, 1, 0, 0 - // 0, 0, -1, 0 - // 0, 0, 0, 0 - // } - size_t operator()(const internal::cone_face_t& subface) const - { - // build M^{-T}Q directly - Eigen::Matrix4d mat = internal::empty_affine_matrix; - const auto& M_inv_T = subface.world_to_local.matrix(); - mat.leftCols<2>() = M_inv_T.topRows<2>().transpose(); - mat.col(2) = -M_inv_T.row(2).transpose(); - auto res = mat * subface.world_to_local; - return hash_funcs(res.matrix()); - } -}; +inline size_t hasher::operator()(const internal::cone_face_t& subface) const +{ + return hash_funcs(get_quadrics_character(cone_std_diag, subface)); +} template <> -struct eq_compare { - bool operator()(const internal::cone_face_t& lhs, const internal::cone_face_t& rhs) const - { - return eq_funcs(lhs.local_to_world, rhs.local_to_world); - } -}; +inline bool eq_compare::operator()(const internal::cone_face_t& lhs, + const internal::cone_face_t& rhs) const +{ + return eq_funcs(get_quadrics_character(cone_std_diag, lhs), get_quadrics_character(cone_std_diag, rhs)); +} } // namespace detail \ No newline at end of file diff --git a/primitive_process/interface/subface/simple/cylinder_face.hpp b/primitive_process/interface/subface/simple/cylinder_face.hpp index e5be2f1..1454a14 100644 --- a/primitive_process/interface/subface/simple/cylinder_face.hpp +++ b/primitive_process/interface/subface/simple/cylinder_face.hpp @@ -13,43 +13,25 @@ struct cylinder_face_t final : subface { namespace detail { -template <> -struct hasher { - // Q' = M^{-T}QM^{-1} - // Q = { - // 1, 0, 0, 0 - // 0, 1, 0, 0 - // 0, 0, 0, 0 - // 0, 0, 0, -1 - // } - size_t operator()(const internal::cylinder_face_t& subface) const - { - // build M^{-T}Q directly - Eigen::Matrix4d mat = internal::empty_affine_matrix; - mat.leftCols<2>() = subface.world_to_local.matrix().topRows<2>().transpose(); - mat(1, 3) = -1.; - auto res = mat * subface.world_to_local; - return hash_funcs(res.matrix()); - } - - // size_t operator()(const internal::cylinder_face_t& subface) const - // { - // auto R = subface.world_to_local.linear().topLeftCorner<2, 3>(); // 2x3 - // auto b = subface.local_to_world.translation(); // 3x1 +// Q' = M^{-T}QM^{-1} +// Q = { +// 1, 0, 0, 0 +// 0, 1, 0, 0 +// 0, 0, 0, 0 +// 0, 0, 0, -1 +// } +const Eigen::Vector4d cylinder_std_diag{1, 1, 0, -1}; - // Eigen::Matrix hash_mat = Eigen::Matrix::Zero(); - // hash_mat.topLeftCorner<3, 3>() = R.transpose() * R; - // hash_mat.topRightCorner<2, 1>() = R * b; - - // return hash_funcs(hash_mat); - // } -}; +template <> +inline size_t hasher::operator()(const internal::cylinder_face_t& subface) const +{ + return hash_funcs(get_quadrics_character(cylinder_std_diag, subface)); +} template <> -struct eq_compare { - bool operator()(const internal::cylinder_face_t& lhs, const internal::cylinder_face_t& rhs) const - { - return eq_funcs(lhs.local_to_world, rhs.local_to_world); - } -}; +inline bool eq_compare::operator()(const internal::cylinder_face_t& lhs, + const internal::cylinder_face_t& rhs) const +{ + return eq_funcs(get_quadrics_character(cylinder_std_diag, lhs), get_quadrics_character(cylinder_std_diag, rhs)); +} } // namespace detail \ No newline at end of file diff --git a/primitive_process/interface/subface/simple/plane.hpp b/primitive_process/interface/subface/simple/plane.hpp index 73da01a..c40e8c4 100644 --- a/primitive_process/interface/subface/simple/plane.hpp +++ b/primitive_process/interface/subface/simple/plane.hpp @@ -13,27 +13,26 @@ struct plane_t final : subface { namespace detail { +inline auto get_plane_character(const internal::plane_t& subface) +{ + // CAUTION: we use vec4d to contain translation info here + // to do this, we have to use the first row of world_to_local instead of the first column of local_to_world + // since the later one does not contain translation info + Eigen::Vector4d vec = subface.world_to_local.matrix().row(0); + auto norm = vec.head<3>().norm(); + vec /= norm; + return vec; +} + template <> -struct hasher { - size_t operator()(const internal::plane_t& subface) const - { - // CAUTION: we use vec4d to contain translation info here - // to do this, we have to use the first row of world_to_local instead of the first column of local_to_world - // since the later one does not contain translation info - Eigen::Vector4d vec = subface.world_to_local.matrix().row(0); - auto norm = vec.head<3>().norm(); - vec /= norm; - // if (vec.z() < 0) vec.head<3>() = -vec.head<3>(); - return hash_funcs(vec); - } -}; +inline size_t hasher::operator()(const internal::plane_t& subface) const +{ + return hash_funcs(get_plane_character(subface)); +} -// only when hash is equal so that eq is called, so we do not have to reverse signs here template <> -struct eq_compare { - bool operator()(const internal::plane_t& lhs, const internal::plane_t& rhs) const - { - return eq_funcs(lhs.local_to_world, rhs.local_to_world); - } -}; +inline bool eq_compare::operator()(const internal::plane_t& lhs, const internal::plane_t& rhs) const +{ + return eq_funcs(get_plane_character(lhs), get_plane_character(rhs)); +} } // namespace detail \ No newline at end of file diff --git a/primitive_process/interface/subface/simple/sphere_face.hpp b/primitive_process/interface/subface/simple/sphere_face.hpp index a0df3b4..5a06bd7 100644 --- a/primitive_process/interface/subface/simple/sphere_face.hpp +++ b/primitive_process/interface/subface/simple/sphere_face.hpp @@ -14,16 +14,25 @@ struct sphere_face_t final : subface { namespace detail { +// Q' = M^{-T}QM^{-1} +// Q = { +// 1, 0, 0, 0 +// 0, 1, 0, 0 +// 0, 0, 1, 0 +// 0, 0, 0, -1 +// } +const Eigen::Vector4d sphere_std_diag{1, 1, 1, -1}; + template <> -struct hasher { - size_t operator()(const internal::sphere_face_t& subface) const { return hash_funcs(subface.local_to_world); } -}; +inline size_t hasher::operator()(const internal::sphere_face_t& subface) const +{ + return hash_funcs(get_quadrics_character(sphere_std_diag, subface)); +} template <> -struct eq_compare { - bool operator()(const internal::sphere_face_t& lhs, const internal::sphere_face_t& rhs) const - { - return eq_funcs(lhs.local_to_world, rhs.local_to_world); - } -}; +inline bool eq_compare::operator()(const internal::sphere_face_t& lhs, + const internal::sphere_face_t& rhs) const +{ + return eq_funcs(get_quadrics_character(sphere_std_diag, lhs), get_quadrics_character(sphere_std_diag, rhs)); +} } // namespace detail \ No newline at end of file diff --git a/primitive_process/src/data/data_center.cpp b/primitive_process/src/data/data_center.cpp index 3266f12..6d3b44f 100644 --- a/primitive_process/src/data/data_center.cpp +++ b/primitive_process/src/data/data_center.cpp @@ -6,16 +6,17 @@ void surface_construct_helper(flat_object_set& container, std::array additional_structure, marked_subface_ptr_t& object) { + static const Eigen::Matrix4d plane_reverse_diag = Eigen::Vector4d{-1, 1, 1, 1}.asDiagonal(); + if constexpr (std::is_same_v) { - auto character_row = matrix.world_to_local.matrix().row(0); - Eigen::Vector4d character = character_row.reverse(); - character[0] = -character[0]; // 反转d项以取得一致的符号表现 - auto cmp = character.cwiseAbs().array() > epsilon; - auto iter = std::find(cmp.begin(), cmp.end(), true); + Eigen::Vector4d character = matrix.world_to_local.matrix().row(0); + auto cmp = character.cwiseAbs().array() > epsilon; + auto iter = std::find(cmp.begin(), cmp.end(), true); if (auto i = std::distance(cmp.begin(), iter); iter != cmp.end() && character[i] < -epsilon) { - matrix.local_to_world = -matrix.local_to_world.matrix(); - matrix.world_to_local = -matrix.world_to_local.matrix(); + matrix.local_to_world *= plane_reverse_diag; + matrix.world_to_local = matrix.local_to_world.inverse(); + // matrix.world_to_local = plane_reverse_diag * matrix.world_to_local.matrix(); object.set_mark(size_t{1}); } } @@ -33,10 +34,10 @@ void primitive_data_center_t::require_surface(surface_type marked_subface_ptr_t& subface) { auto old_subface = subface; - std::visit( - [&](auto&& surface_container) { surface_construct_helper(surface_container, matrix, additional_structure, subface); }, - surfaces[static_cast(type)]); - if (old_subface != nullptr) release_surface(type, old_subface); + surfaces.visit(static_cast(type), [&](auto&& surface_container) { + surface_construct_helper(surface_container, matrix, additional_structure, subface); + }); + if (old_subface != nullptr && old_subface.get_ptr() != subface.get_ptr()) release_surface(type, old_subface); } template @@ -47,8 +48,8 @@ void surface_release_helper(flat_object_set& container, const marked_subface_ void primitive_data_center_t::release_surface(surface_type type, const marked_subface_ptr_t& subface) { - std::visit([&](auto&& surface_container) { surface_release_helper(surface_container, subface); }, - surfaces[static_cast(type)]); + surfaces.visit(static_cast(type), + [&](auto&& surface_container) { surface_release_helper(surface_container, subface); }); } template @@ -67,27 +68,27 @@ void direct_release_helper(flat_object_set& container, const pointer_wrapper< internal::extrude_axis* primitive_data_center_t::require_axis(axis_type type, const internal::extrude_axis& temp_axis_ptr) { - std::visit([&](auto&& axis_container) { return direct_acquire_helper(axis_container, temp_axis_ptr); }, - axes[static_cast(type)]); - return nullptr; + return axes.visit(static_cast(type), + [&](auto&& axis_container) { return direct_acquire_helper(axis_container, temp_axis_ptr); }); + // return nullptr; } void primitive_data_center_t::release_axis(axis_type type, const pointer_wrapper& axis) { - std::visit([&](auto&& axis_container) { direct_release_helper(axis_container, axis); }, axes[static_cast(type)]); + axes.visit(static_cast(type), [&](auto&& axis_container) { direct_release_helper(axis_container, axis); }); } internal::pattern* primitive_data_center_t::require_pattern(pattern_type type, const internal::pattern& temp_pattern_ptr) { - std::visit([&](auto&& pattern_container) { return direct_acquire_helper(pattern_container, temp_pattern_ptr); }, - patterns[static_cast(type)]); - return nullptr; + return patterns.visit(static_cast(type), + [&](auto&& pattern_container) { return direct_acquire_helper(pattern_container, temp_pattern_ptr); }); + // return nullptr; } void primitive_data_center_t::release_pattern(pattern_type type, const pointer_wrapper& pattern) { - std::visit([&](auto&& pattern_container) { direct_release_helper(pattern_container, pattern); }, - patterns[static_cast(type)]); + patterns.visit(static_cast(type), + [&](auto&& pattern_container) { direct_release_helper(pattern_container, pattern); }); } namespace internal diff --git a/primitive_process/src/subface/simple/cone_face.cpp b/primitive_process/src/subface/simple/cone_face.cpp index eac08f7..8c48fd0 100644 --- a/primitive_process/src/subface/simple/cone_face.cpp +++ b/primitive_process/src/subface/simple/cone_face.cpp @@ -12,15 +12,9 @@ double cone_function_impl::eval_sdf(pointer_wrapper object, Eigen::Vect const auto t = (q.x() + q.y()) / 2; if (t <= 0) // 最近距离是圆锥顶点 { - return object->local_to_world_scale().cwiseProduct(local_p.head<3>()).norm(); + return q.norm(); } else { // 最近距离在圆锥面上 - if (len > epsilon) { - const auto vec = local_p.head<3>() - Eigen::Vector3d{local_p.x() * t / len, local_p.y() * t / len, -t}; - return object->local_to_world_scale().cwiseProduct(vec).norm(); - } else { - const Eigen::Vector2d q_ = {object->local_to_world_scale().minCoeff(), -t}; - return -q_.norm(); - } + return (q.x() - q.y()) / 2; } } diff --git a/primitive_process/src/subface/simple/cylinder_face.cpp b/primitive_process/src/subface/simple/cylinder_face.cpp index 30c4340..5baf061 100644 --- a/primitive_process/src/subface/simple/cylinder_face.cpp +++ b/primitive_process/src/subface/simple/cylinder_face.cpp @@ -6,14 +6,7 @@ namespace internal double cylinder_function_impl::eval_sdf(pointer_wrapper object, Eigen::Vector3d p) { Eigen::Vector4d local_p = object->world_to_local * Eigen::Vector4d{p.x(), p.y(), p.z(), 1.0}; - const double len = local_p.head<2>().norm(); - - if (len > epsilon) { - Eigen::Vector2d normal = local_p.head<2>() / len; - return object->local_to_world_scale().head<2>().cwiseProduct(normal).norm() * (len * len - 1); - } else { - return -object->local_to_world_scale().minCoeff(); - } + return local_p.head<2>().norm() - 1; } Eigen::Vector3d cylinder_function_impl::eval_sdf_grad(pointer_wrapper object, Eigen::Vector3d p) diff --git a/primitive_process/src/subface/simple/plane.cpp b/primitive_process/src/subface/simple/plane.cpp index 88bde95..7fe3f39 100644 --- a/primitive_process/src/subface/simple/plane.cpp +++ b/primitive_process/src/subface/simple/plane.cpp @@ -5,7 +5,7 @@ namespace internal double plane_function_impl::eval_sdf(pointer_wrapper object, Eigen::Vector3d p) { Eigen::Vector4d local_p = object->world_to_local * Eigen::Vector4d{p.x(), p.y(), p.z(), 1.0}; - return object->local_to_world_scale().x() * local_p.x(); + return local_p.x(); } Eigen::Vector3d plane_function_impl::eval_sdf_grad(pointer_wrapper object, Eigen::Vector3d p) diff --git a/primitive_process/src/subface/simple/sphere_face.cpp b/primitive_process/src/subface/simple/sphere_face.cpp index 25c0f1e..68ee293 100644 --- a/primitive_process/src/subface/simple/sphere_face.cpp +++ b/primitive_process/src/subface/simple/sphere_face.cpp @@ -6,14 +6,7 @@ namespace internal double sphere_function_impl::eval_sdf(pointer_wrapper object, Eigen::Vector3d p) { Eigen::Vector4d local_p = object->world_to_local * Eigen::Vector4d{p.x(), p.y(), p.z(), 1.0}; - const double len = local_p.head<3>().norm(); - - if (len > std::numeric_limits::epsilon()) { - Eigen::Vector3d normal = local_p.head<3>() / len; - return object->local_to_world_scale().cwiseProduct(normal).norm() * (len * len - 1); - } else { - return -object->local_to_world_scale().minCoeff(); - } + return local_p.head<3>().norm() - 1; } Eigen::Vector3d sphere_function_impl::eval_sdf_grad(pointer_wrapper object, Eigen::Vector3d p) diff --git a/shared_module/container/wrapper/heter_array.hpp b/shared_module/container/wrapper/heter_array.hpp new file mode 100644 index 0000000..23c7cc2 --- /dev/null +++ b/shared_module/container/wrapper/heter_array.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include +#include + +template +struct heter_array { + heter_array() : data(this->default_ctor_impl(std::make_index_sequence{})) {} + + ~heter_array() = default; + + heter_array(const heter_array&) = default; + heter_array(heter_array&&) = default; + heter_array& operator=(const heter_array&) = default; + heter_array& operator=(heter_array&&) = default; + + auto& operator[](size_t i) { return data[i]; } + + const auto& operator[](size_t i) const { return data[i]; } + + template + decltype(auto) visit(size_t i, F&& f) + { + return std::visit(std::forward(f), data[i]); + } + + template + decltype(auto) visit(size_t i, F&& f) const + { + return std::visit(std::forward(f), data[i]); + } + +protected: + template + static auto default_ctor_impl(std::index_sequence) + { + return std::array{heter_type{std::in_place_index}...}; + } + + using heter_type = std::variant; + static constexpr size_t N = sizeof...(Ts); + std::array data{}; +}; \ No newline at end of file