Browse Source

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
V2-integral
Zhicheng Wang 1 day ago
parent
commit
c7ecb2bb5c
  1. 12
      primitive_process/interface/data/data_center.hpp
  2. 39
      primitive_process/interface/data/data_type.hpp
  3. 43
      primitive_process/interface/subface/simple/cone_face.hpp
  4. 54
      primitive_process/interface/subface/simple/cylinder_face.hpp
  5. 29
      primitive_process/interface/subface/simple/plane.hpp
  6. 27
      primitive_process/interface/subface/simple/sphere_face.hpp
  7. 41
      primitive_process/src/data/data_center.cpp
  8. 10
      primitive_process/src/subface/simple/cone_face.cpp
  9. 9
      primitive_process/src/subface/simple/cylinder_face.cpp
  10. 2
      primitive_process/src/subface/simple/plane.cpp
  11. 9
      primitive_process/src/subface/simple/sphere_face.cpp
  12. 43
      shared_module/container/wrapper/heter_array.hpp

12
primitive_process/interface/data/data_center.hpp

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <macros.h> #include <macros.h>
#include <container/wrapper/heter_array.hpp>
#include "primitive/simple/sphere.hpp" #include "primitive/simple/sphere.hpp"
#include "primitive/simple/cylinder.hpp" #include "primitive/simple/cylinder.hpp"
@ -25,9 +26,8 @@ using polyline_pattern_container_t = flat_object_set<internal::polyline_pattern>
EXTERN_C struct PE_API primitive_data_center_t { EXTERN_C struct PE_API primitive_data_center_t {
// all other data depend on cached transform_blocks // all other data depend on cached transform_blocks
using surface_containers = heter_array<plane_container_t, sphere_container_t, cylinder_container_t, cone_container_t, extrude_side_container_t>
std::variant<plane_container_t, sphere_container_t, cylinder_container_t, cone_container_t, extrude_side_container_t>; surfaces{};
std::array<surface_containers, static_cast<uint8_t>(surface_type::max_count)> surfaces{};
void require_surface(surface_type type, void require_surface(surface_type type,
const internal::paired_model_matrix& matrix, const internal::paired_model_matrix& matrix,
@ -35,13 +35,11 @@ EXTERN_C struct PE_API primitive_data_center_t {
marked_subface_ptr_t<subface>& subface); marked_subface_ptr_t<subface>& subface);
void release_surface(surface_type type, const marked_subface_ptr_t<subface>& subface); void release_surface(surface_type type, const marked_subface_ptr_t<subface>& subface);
using axis_containers = std::variant<polyline_axis_container_t, helixline_axis_container_t>; heter_array<polyline_axis_container_t, helixline_axis_container_t> axes{};
std::array<axis_containers, AXIS_TYPE_MAX_COUNT> axes{};
internal::extrude_axis* require_axis(axis_type type, const internal::extrude_axis& temp_axis_ptr); internal::extrude_axis* require_axis(axis_type type, const internal::extrude_axis& temp_axis_ptr);
void release_axis(axis_type type, const pointer_wrapper<internal::extrude_axis>& axis); void release_axis(axis_type type, const pointer_wrapper<internal::extrude_axis>& axis);
using pattern_containers = std::variant<polyline_pattern_container_t>; heter_array<polyline_pattern_container_t> patterns{};
std::array<pattern_containers, PATTERN_TYPE_MAX_COUNT> patterns{};
internal::pattern* require_pattern(pattern_type type, const internal::pattern& temp_pattern_ptr); internal::pattern* require_pattern(pattern_type type, const internal::pattern& temp_pattern_ptr);
void release_pattern(pattern_type type, const pointer_wrapper<internal::pattern>& pattern); void release_pattern(pattern_type type, const pointer_wrapper<internal::pattern>& pattern);
}; };

39
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 namespace detail
{ {
template <> template <>
struct hasher<internal::transform_block> { inline size_t hasher<internal::transform_block>::operator()(const internal::transform_block& block) const
size_t operator()(const internal::transform_block& block) const { return hash_funcs(block); } {
}; return hash_funcs(block);
}
template <> template <>
struct hasher<internal::paired_model_matrix> { inline size_t hasher<internal::paired_model_matrix>::operator()(const internal::paired_model_matrix& paired_matrix) const
size_t operator()(const internal::paired_model_matrix& paired_matrix) const {
{
return hash_funcs(paired_matrix.local_to_world); return hash_funcs(paired_matrix.local_to_world);
} }
};
template <typename Tag> inline auto get_quadrics_character(Eigen::Vector4d std_diag, const internal::paired_model_matrix& paired_matrix)
struct tagged_hasher<internal::paired_model_matrix_ptr_t, Tag> { {
size_t operator()(const internal::paired_model_matrix& paired_matrix) const Eigen::Matrix4d temp{};
{ temp.leftCols<3>() = paired_matrix.world_to_local.matrix().transpose();
return hash_funcs(paired_matrix.local_to_world); temp(3, 3) = 1.;
} temp = temp * std_diag.asDiagonal() * temp.transpose();
}; temp /= temp.diagonal().head<3>().norm();
return temp;
}
// template <typename Tag>
// struct tagged_hasher<internal::paired_model_matrix_ptr_t, Tag> {
// size_t operator()(const internal::paired_model_matrix& paired_matrix) const
// {
// return hash_funcs(paired_matrix.local_to_world);
// }
// };
} // namespace detail } // namespace detail

43
primitive_process/interface/subface/simple/cone_face.hpp

@ -12,32 +12,25 @@ struct cone_face_t final : subface {
namespace detail 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 <> template <>
struct hasher<internal::cone_face_t> { inline size_t hasher<internal::cone_face_t>::operator()(const internal::cone_face_t& subface) const
// Q' = M^{-T}QM^{-1} {
// Q = { return hash_funcs(get_quadrics_character(cone_std_diag, subface));
// 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());
}
};
template <> template <>
struct eq_compare<internal::cone_face_t> { inline bool eq_compare<internal::cone_face_t>::operator()(const internal::cone_face_t& lhs,
bool operator()(const internal::cone_face_t& lhs, const internal::cone_face_t& rhs) const const internal::cone_face_t& rhs) const
{ {
return eq_funcs(lhs.local_to_world, rhs.local_to_world); return eq_funcs(get_quadrics_character(cone_std_diag, lhs), get_quadrics_character(cone_std_diag, rhs));
} }
};
} // namespace detail } // namespace detail

54
primitive_process/interface/subface/simple/cylinder_face.hpp

@ -13,43 +13,25 @@ struct cylinder_face_t final : subface {
namespace detail namespace detail
{ {
template <> // Q' = M^{-T}QM^{-1}
struct hasher<internal::cylinder_face_t> { // Q = {
// Q' = M^{-T}QM^{-1} // 1, 0, 0, 0
// Q = { // 0, 1, 0, 0
// 1, 0, 0, 0 // 0, 0, 0, 0
// 0, 1, 0, 0 // 0, 0, 0, -1
// 0, 0, 0, 0 // }
// 0, 0, 0, -1 const Eigen::Vector4d cylinder_std_diag{1, 1, 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
// Eigen::Matrix<double, 3, 4> hash_mat = Eigen::Matrix<double, 3, 4>::Zero(); template <>
// hash_mat.topLeftCorner<3, 3>() = R.transpose() * R; inline size_t hasher<internal::cylinder_face_t>::operator()(const internal::cylinder_face_t& subface) const
// hash_mat.topRightCorner<2, 1>() = R * b; {
return hash_funcs(get_quadrics_character(cylinder_std_diag, subface));
// return hash_funcs(hash_mat); }
// }
};
template <> template <>
struct eq_compare<internal::cylinder_face_t> { inline bool eq_compare<internal::cylinder_face_t>::operator()(const internal::cylinder_face_t& lhs,
bool operator()(const internal::cylinder_face_t& lhs, const internal::cylinder_face_t& rhs) const const internal::cylinder_face_t& rhs) const
{ {
return eq_funcs(lhs.local_to_world, rhs.local_to_world); return eq_funcs(get_quadrics_character(cylinder_std_diag, lhs), get_quadrics_character(cylinder_std_diag, rhs));
} }
};
} // namespace detail } // namespace detail

29
primitive_process/interface/subface/simple/plane.hpp

@ -13,27 +13,26 @@ struct plane_t final : subface {
namespace detail namespace detail
{ {
template <> inline auto get_plane_character(const internal::plane_t& subface)
struct hasher<internal::plane_t> { {
size_t operator()(const internal::plane_t& subface) const
{
// CAUTION: we use vec4d to contain translation info here // 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 // 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 // since the later one does not contain translation info
Eigen::Vector4d vec = subface.world_to_local.matrix().row(0); Eigen::Vector4d vec = subface.world_to_local.matrix().row(0);
auto norm = vec.head<3>().norm(); auto norm = vec.head<3>().norm();
vec /= norm; vec /= norm;
// if (vec.z() < 0) vec.head<3>() = -vec.head<3>(); return vec;
return hash_funcs(vec); }
}
};
// only when hash is equal so that eq is called, so we do not have to reverse signs here
template <> template <>
struct eq_compare<internal::plane_t> { inline size_t hasher<internal::plane_t>::operator()(const internal::plane_t& subface) const
bool operator()(const internal::plane_t& lhs, const internal::plane_t& rhs) const {
{ return hash_funcs(get_plane_character(subface));
return eq_funcs(lhs.local_to_world, rhs.local_to_world); }
}
}; template <>
inline bool eq_compare<internal::plane_t>::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 } // namespace detail

27
primitive_process/interface/subface/simple/sphere_face.hpp

@ -14,16 +14,25 @@ struct sphere_face_t final : subface {
namespace detail 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 <> template <>
struct hasher<internal::sphere_face_t> { inline size_t hasher<internal::sphere_face_t>::operator()(const internal::sphere_face_t& subface) const
size_t operator()(const internal::sphere_face_t& subface) const { return hash_funcs(subface.local_to_world); } {
}; return hash_funcs(get_quadrics_character(sphere_std_diag, subface));
}
template <> template <>
struct eq_compare<internal::sphere_face_t> { inline bool eq_compare<internal::sphere_face_t>::operator()(const internal::sphere_face_t& lhs,
bool operator()(const internal::sphere_face_t& lhs, const internal::sphere_face_t& rhs) const const internal::sphere_face_t& rhs) const
{ {
return eq_funcs(lhs.local_to_world, rhs.local_to_world); return eq_funcs(get_quadrics_character(sphere_std_diag, lhs), get_quadrics_character(sphere_std_diag, rhs));
} }
};
} // namespace detail } // namespace detail

41
primitive_process/src/data/data_center.cpp

@ -6,16 +6,17 @@ void surface_construct_helper(flat_object_set<T>& container,
std::array<void*, 2> additional_structure, std::array<void*, 2> additional_structure,
marked_subface_ptr_t<subface>& object) marked_subface_ptr_t<subface>& object)
{ {
static const Eigen::Matrix4d plane_reverse_diag = Eigen::Vector4d{-1, 1, 1, 1}.asDiagonal();
if constexpr (std::is_same_v<T, internal::plane_t>) { if constexpr (std::is_same_v<T, internal::plane_t>) {
auto character_row = matrix.world_to_local.matrix().row(0); Eigen::Vector4d character = 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 cmp = character.cwiseAbs().array() > epsilon;
auto iter = std::find(cmp.begin(), cmp.end(), true); auto iter = std::find(cmp.begin(), cmp.end(), true);
if (auto i = std::distance(cmp.begin(), iter); iter != cmp.end() && character[i] < -epsilon) { if (auto i = std::distance(cmp.begin(), iter); iter != cmp.end() && character[i] < -epsilon) {
matrix.local_to_world = -matrix.local_to_world.matrix(); matrix.local_to_world *= plane_reverse_diag;
matrix.world_to_local = -matrix.world_to_local.matrix(); 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}); object.set_mark(size_t{1});
} }
} }
@ -33,10 +34,10 @@ void primitive_data_center_t::require_surface(surface_type
marked_subface_ptr_t<subface>& subface) marked_subface_ptr_t<subface>& subface)
{ {
auto old_subface = subface; auto old_subface = subface;
std::visit( surfaces.visit(static_cast<uint8_t>(type), [&](auto&& surface_container) {
[&](auto&& surface_container) { surface_construct_helper(surface_container, matrix, additional_structure, subface); }, surface_construct_helper(surface_container, matrix, additional_structure, subface);
surfaces[static_cast<uint8_t>(type)]); });
if (old_subface != nullptr) release_surface(type, old_subface); if (old_subface != nullptr && old_subface.get_ptr() != subface.get_ptr()) release_surface(type, old_subface);
} }
template <typename T> template <typename T>
@ -47,8 +48,8 @@ void surface_release_helper(flat_object_set<T>& container, const marked_subface_
void primitive_data_center_t::release_surface(surface_type type, const marked_subface_ptr_t<subface>& subface) void primitive_data_center_t::release_surface(surface_type type, const marked_subface_ptr_t<subface>& subface)
{ {
std::visit([&](auto&& surface_container) { surface_release_helper(surface_container, subface); }, surfaces.visit(static_cast<uint8_t>(type),
surfaces[static_cast<uint8_t>(type)]); [&](auto&& surface_container) { surface_release_helper(surface_container, subface); });
} }
template <typename T, typename F> template <typename T, typename F>
@ -67,27 +68,27 @@ void direct_release_helper(flat_object_set<T>& container, const pointer_wrapper<
internal::extrude_axis* primitive_data_center_t::require_axis(axis_type type, const internal::extrude_axis& temp_axis_ptr) 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); }, return axes.visit(static_cast<uint8_t>(type),
axes[static_cast<uint8_t>(type)]); [&](auto&& axis_container) { return direct_acquire_helper(axis_container, temp_axis_ptr); });
return nullptr; // return nullptr;
} }
void primitive_data_center_t::release_axis(axis_type type, const pointer_wrapper<internal::extrude_axis>& axis) void primitive_data_center_t::release_axis(axis_type type, const pointer_wrapper<internal::extrude_axis>& axis)
{ {
std::visit([&](auto&& axis_container) { direct_release_helper(axis_container, axis); }, axes[static_cast<uint8_t>(type)]); axes.visit(static_cast<uint8_t>(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) 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); }, return patterns.visit(static_cast<uint8_t>(type),
patterns[static_cast<uint8_t>(type)]); [&](auto&& pattern_container) { return direct_acquire_helper(pattern_container, temp_pattern_ptr); });
return nullptr; // return nullptr;
} }
void primitive_data_center_t::release_pattern(pattern_type type, const pointer_wrapper<internal::pattern>& pattern) void primitive_data_center_t::release_pattern(pattern_type type, const pointer_wrapper<internal::pattern>& pattern)
{ {
std::visit([&](auto&& pattern_container) { direct_release_helper(pattern_container, pattern); }, patterns.visit(static_cast<uint8_t>(type),
patterns[static_cast<uint8_t>(type)]); [&](auto&& pattern_container) { direct_release_helper(pattern_container, pattern); });
} }
namespace internal namespace internal

10
primitive_process/src/subface/simple/cone_face.cpp

@ -12,15 +12,9 @@ double cone_function_impl::eval_sdf(pointer_wrapper<subface> object, Eigen::Vect
const auto t = (q.x() + q.y()) / 2; const auto t = (q.x() + q.y()) / 2;
if (t <= 0) // 最近距离是圆锥顶点 if (t <= 0) // 最近距离是圆锥顶点
{ {
return object->local_to_world_scale().cwiseProduct(local_p.head<3>()).norm(); return q.norm();
} else { // 最近距离在圆锥面上 } else { // 最近距离在圆锥面上
if (len > epsilon) { return (q.x() - q.y()) / 2;
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();
}
} }
} }

9
primitive_process/src/subface/simple/cylinder_face.cpp

@ -6,14 +6,7 @@ namespace internal
double cylinder_function_impl::eval_sdf(pointer_wrapper<subface> object, Eigen::Vector3d p) double cylinder_function_impl::eval_sdf(pointer_wrapper<subface> object, Eigen::Vector3d p)
{ {
Eigen::Vector4d local_p = object->world_to_local * Eigen::Vector4d{p.x(), p.y(), p.z(), 1.0}; 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(); return local_p.head<2>().norm() - 1;
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();
}
} }
Eigen::Vector3d cylinder_function_impl::eval_sdf_grad(pointer_wrapper<subface> object, Eigen::Vector3d p) Eigen::Vector3d cylinder_function_impl::eval_sdf_grad(pointer_wrapper<subface> object, Eigen::Vector3d p)

2
primitive_process/src/subface/simple/plane.cpp

@ -5,7 +5,7 @@ namespace internal
double plane_function_impl::eval_sdf(pointer_wrapper<subface> object, Eigen::Vector3d p) double plane_function_impl::eval_sdf(pointer_wrapper<subface> object, Eigen::Vector3d p)
{ {
Eigen::Vector4d local_p = object->world_to_local * Eigen::Vector4d{p.x(), p.y(), p.z(), 1.0}; 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<subface> object, Eigen::Vector3d p) Eigen::Vector3d plane_function_impl::eval_sdf_grad(pointer_wrapper<subface> object, Eigen::Vector3d p)

9
primitive_process/src/subface/simple/sphere_face.cpp

@ -6,14 +6,7 @@ namespace internal
double sphere_function_impl::eval_sdf(pointer_wrapper<subface> object, Eigen::Vector3d p) double sphere_function_impl::eval_sdf(pointer_wrapper<subface> object, Eigen::Vector3d p)
{ {
Eigen::Vector4d local_p = object->world_to_local * Eigen::Vector4d{p.x(), p.y(), p.z(), 1.0}; 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(); return local_p.head<3>().norm() - 1;
if (len > std::numeric_limits<double>::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();
}
} }
Eigen::Vector3d sphere_function_impl::eval_sdf_grad(pointer_wrapper<subface> object, Eigen::Vector3d p) Eigen::Vector3d sphere_function_impl::eval_sdf_grad(pointer_wrapper<subface> object, Eigen::Vector3d p)

43
shared_module/container/wrapper/heter_array.hpp

@ -0,0 +1,43 @@
#pragma once
#include <array>
#include <variant>
template <typename... Ts>
struct heter_array {
heter_array() : data(this->default_ctor_impl(std::make_index_sequence<N>{})) {}
~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 <typename F>
decltype(auto) visit(size_t i, F&& f)
{
return std::visit(std::forward<F>(f), data[i]);
}
template <typename F>
decltype(auto) visit(size_t i, F&& f) const
{
return std::visit(std::forward<F>(f), data[i]);
}
protected:
template <size_t... Is>
static auto default_ctor_impl(std::index_sequence<Is...>)
{
return std::array<heter_type, N>{heter_type{std::in_place_index<Is>}...};
}
using heter_type = std::variant<Ts...>;
static constexpr size_t N = sizeof...(Ts);
std::array<heter_type, N> data{};
};
Loading…
Cancel
Save