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. 20
      primitive_process/interface/data/data_center.hpp
  2. 41
      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. 39
      primitive_process/interface/subface/simple/plane.hpp
  6. 27
      primitive_process/interface/subface/simple/sphere_face.hpp
  7. 45
      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

20
primitive_process/interface/data/data_center.hpp

@ -1,6 +1,7 @@
#pragma once
#include <macros.h>
#include <container/wrapper/heter_array.hpp>
#include "primitive/simple/sphere.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 {
// all other data depend on cached transform_blocks
using surface_containers =
std::variant<plane_container_t, sphere_container_t, cylinder_container_t, cone_container_t, extrude_side_container_t>;
std::array<surface_containers, static_cast<uint8_t>(surface_type::max_count)> surfaces{};
heter_array<plane_container_t, sphere_container_t, cylinder_container_t, cone_container_t, extrude_side_container_t>
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>& 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>;
std::array<axis_containers, AXIS_TYPE_MAX_COUNT> 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<internal::extrude_axis>& axis);
heter_array<polyline_axis_container_t, helixline_axis_container_t> 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<internal::extrude_axis>& axis);
using pattern_containers = std::variant<polyline_pattern_container_t>;
std::array<pattern_containers, PATTERN_TYPE_MAX_COUNT> patterns{};
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);
heter_array<polyline_pattern_container_t> patterns{};
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);
};
namespace internal

41
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<internal::transform_block> {
size_t operator()(const internal::transform_block& block) const { return hash_funcs(block); }
};
inline size_t hasher<internal::transform_block>::operator()(const internal::transform_block& block) const
{
return hash_funcs(block);
}
template <>
struct hasher<internal::paired_model_matrix> {
size_t operator()(const internal::paired_model_matrix& paired_matrix) const
{
return hash_funcs(paired_matrix.local_to_world);
}
};
inline size_t hasher<internal::paired_model_matrix>::operator()(const internal::paired_model_matrix& paired_matrix) const
{
return hash_funcs(paired_matrix.local_to_world);
}
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);
}
};
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 <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

43
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<internal::cone_face_t> {
// 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<internal::cone_face_t>::operator()(const internal::cone_face_t& subface) const
{
return hash_funcs(get_quadrics_character(cone_std_diag, subface));
}
template <>
struct eq_compare<internal::cone_face_t> {
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<internal::cone_face_t>::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

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

@ -13,43 +13,25 @@ struct cylinder_face_t final : subface {
namespace detail
{
template <>
struct hasher<internal::cylinder_face_t> {
// 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<double, 3, 4> hash_mat = Eigen::Matrix<double, 3, 4>::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<internal::cylinder_face_t>::operator()(const internal::cylinder_face_t& subface) const
{
return hash_funcs(get_quadrics_character(cylinder_std_diag, subface));
}
template <>
struct eq_compare<internal::cylinder_face_t> {
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<internal::cylinder_face_t>::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

39
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<internal::plane_t> {
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<internal::plane_t>::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<internal::plane_t> {
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<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

27
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<internal::sphere_face_t> {
size_t operator()(const internal::sphere_face_t& subface) const { return hash_funcs(subface.local_to_world); }
};
inline size_t hasher<internal::sphere_face_t>::operator()(const internal::sphere_face_t& subface) const
{
return hash_funcs(get_quadrics_character(sphere_std_diag, subface));
}
template <>
struct eq_compare<internal::sphere_face_t> {
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<internal::sphere_face_t>::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

45
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,
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>) {
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>& subface)
{
auto old_subface = subface;
std::visit(
[&](auto&& surface_container) { surface_construct_helper(surface_container, matrix, additional_structure, subface); },
surfaces[static_cast<uint8_t>(type)]);
if (old_subface != nullptr) release_surface(type, old_subface);
surfaces.visit(static_cast<uint8_t>(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 <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)
{
std::visit([&](auto&& surface_container) { surface_release_helper(surface_container, subface); },
surfaces[static_cast<uint8_t>(type)]);
surfaces.visit(static_cast<uint8_t>(type),
[&](auto&& surface_container) { surface_release_helper(surface_container, subface); });
}
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)
{
std::visit([&](auto&& axis_container) { return direct_acquire_helper(axis_container, temp_axis_ptr); },
axes[static_cast<uint8_t>(type)]);
return nullptr;
return axes.visit(static_cast<uint8_t>(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<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)
{
std::visit([&](auto&& pattern_container) { return direct_acquire_helper(pattern_container, temp_pattern_ptr); },
patterns[static_cast<uint8_t>(type)]);
return nullptr;
return patterns.visit(static_cast<uint8_t>(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<internal::pattern>& pattern)
{
std::visit([&](auto&& pattern_container) { direct_release_helper(pattern_container, pattern); },
patterns[static_cast<uint8_t>(type)]);
patterns.visit(static_cast<uint8_t>(type),
[&](auto&& pattern_container) { direct_release_helper(pattern_container, pattern); });
}
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;
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;
}
}

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)
{
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<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)
{
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)

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)
{
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<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();
}
return local_p.head<3>().norm() - 1;
}
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