Browse Source

fix: modify the implementation of primitive transform

main
linchforever 2 days ago
parent
commit
d6b09e6219
  1. 78
      primitive_process/src/base/primitive.cpp
  2. 106
      primitive_process/src/subface/simple/extrude_helixline_side_face.cpp

78
primitive_process/src/base/primitive.cpp

@ -44,14 +44,6 @@ dynamic_bitset_mp<> primitive::judge_sign_by_subface_sign(const stl_vector_mp<dy
return res;
}
// void primitive::initialize(primitive_data_center_t &data_center)
// {
// this->data_center = make_pointer_wrapper(data_center);
// auto subface_init_model_matrices = get_subface_init_model_matrices();
// initialize(subface_init_model_matrices);
// }
void primitive::initialize(const stl_vector_mp<internal::paired_model_matrix_ptr_t>& matrices,
const stl_vector_mp<bool>& reversed_flags,
const stl_vector_mp<const void*>& geometry,
@ -59,7 +51,7 @@ void primitive::initialize(const stl_vector_mp<internal::paired_model_matrix_ptr
{
auto subfaces = get_subfaces();
auto subface_types = get_subface_types();
// 阶段2: 创建 surface(geometry 所有权转移到 surface)
// 创建 surface(geometry 所有权转移到 surface)
stl_vector_mp<const void*> raw_geometry = geometry.empty() ? get_subface_geometries() : geometry;
stl_vector_mp<const void*> canonical_geometry;
@ -84,7 +76,8 @@ void primitive::initialize(const stl_vector_mp<internal::paired_model_matrix_ptr
break;
}
case surface_type::sphere: {
// TODO: 添加 sphere 的处理
// Sphere 不依赖任何外部 geometry descriptor,
// 其形状完全由 paired_model_matrix 编码,canonical_ptr 保持 nullptr。
break;
}
case surface_type::extrude_polyline_side: {
@ -113,7 +106,6 @@ void primitive::destroy()
auto subface_types = get_subface_types();
assert(subfaces.front().get_ptr() != nullptr);
// for (size_t i = 0; i < subfaces.size(); ++i) data_center->release_surface(subface_types[i], subfaces[i]);
for (size_t i = 0; i < subfaces.size(); ++i) {
auto get_geom_func = internal::get_geometry_accessor_ptr(subface_types[i]);
const void* geometry_ptr = get_geom_func(make_pointer_wrapper(subfaces[i].get_ptr()));
@ -133,6 +125,7 @@ void primitive::destroy()
break;
}
case surface_type::sphere: {
// Sphere 没有 descriptor,geometry_ptr 始终为 nullptr,此分支不会执行。
break;
}
case surface_type::extrude_polyline_side: {
@ -165,7 +158,8 @@ void primitive::apply_transform(internal::transform_type type, Eigen::Vector4d p
geometry_ptrs.reserve(subfaces.size());
for (size_t i = 0; i < subfaces.size(); ++i) {
if (subface_types[i] == surface_type::plane) {
// Plane and sphere both carry no descriptor: geometry pointer is always nullptr.
if (subface_types[i] == surface_type::plane || subface_types[i] == surface_type::sphere) {
geometry_ptrs.push_back(nullptr);
} else {
auto get_geom_func = internal::get_geometry_accessor_ptr(subface_types[i]);
@ -204,8 +198,6 @@ void primitive::apply_transform(internal::transform_type type, Eigen::Vector4d p
} break;
default: throw std::invalid_argument("Invalid transform type");
}
// apply affine transform to aabb
// m_aabb = m_aabb.transformed(affine);
stl_vector_mp<size_t> saved_marks;
saved_marks.reserve(subfaces.size());
@ -219,29 +211,6 @@ void primitive::apply_transform(internal::transform_type type, Eigen::Vector4d p
recompute_aabb();
}
// 后续可能需要删除这个函数
aabb_t compute_local_aabb_from_descriptor(surface_type type, const void* descriptor_ptr)
{
switch (type) {
case surface_type::cylinder: {
auto* desc = static_cast<const cylinder_descriptor_t*>(descriptor_ptr);
double r = desc->radius;
double h = std::sqrt(desc->offset.x * desc->offset.x +
desc->offset.y * desc->offset.y +
desc->offset.z * desc->offset.z);
return aabb_t(Eigen::Vector3d(-r, -r, 0), Eigen::Vector3d(r, r, h));
}
case surface_type::sphere: {
// return aabb_t();
return aabb_t(Eigen::Vector3d(-1, -1, -1), Eigen::Vector3d(2, 2, 2));
}
case surface_type::plane: return aabb_t();
case surface_type::extrude_polyline_side:
case surface_type::extrude_helixline_side:
default: std::cerr << "[WARNING] Unknown surface type: " << static_cast<int>(type) << "\n"; return aabb_t();
}
}
// 重新计算 Primitive 的 AABB
void primitive::recompute_aabb()
{
@ -255,18 +224,36 @@ void primitive::recompute_aabb()
for (size_t i = 0; i < subfaces.size(); ++i) {
aabb_t local_aabb = aabb_t();
if (subface_types[i] == surface_type::extrude_polyline_side) {
// Extrude faces own their own AABB computation.
auto* face = static_cast<internal::extrude_polyline_side_face_t*>(subfaces[i].get_ptr());
local_aabb.extend(face->get_aabb()); // 通过访问器读取
} else if (subface_types[i] == surface_type::extrude_helixline_side) {
auto* face = static_cast<internal::extrude_helixline_side_face_t*>(subfaces[i].get_ptr());
local_aabb.extend(face->get_aabb());
} else {
const void* descriptor_ptr = nullptr;
if (subface_types[i] != surface_type::plane && subfaces[i].get_ptr() != nullptr) {
auto get_desc_func = internal::get_geometry_accessor_ptr(subface_types[i]);
descriptor_ptr = get_desc_func(make_pointer_wrapper(subfaces[i].get_ptr()));
switch (subface_types[i]) {
case surface_type::sphere: {
constexpr double aabb_epsilon = 1e-9;
local_aabb = aabb_t(internal::k_aabb_unit.min().array() - aabb_epsilon,
internal::k_aabb_unit.max().array() + aabb_epsilon);
break;
}
case surface_type::cylinder: {
if (subfaces[i].get_ptr() != nullptr) {
auto get_geom_func = internal::get_geometry_accessor_ptr(surface_type::cylinder);
const void* geom_raw = get_geom_func(make_pointer_wrapper(subfaces[i].get_ptr()));
const auto* desc = static_cast<const cylinder_descriptor_t*>(geom_raw);
if (desc) {
const double r = desc->radius;
const double h = desc->height; // use the explicit height field, not offset magnitude
local_aabb = aabb_t(Eigen::Vector3d(-r, -r, 0.0), Eigen::Vector3d(r, r, h));
}
}
break;
}
case surface_type::plane:
default: continue;
}
local_aabb = compute_local_aabb_from_descriptor(subface_types[i], descriptor_ptr);
if (local_aabb.isEmpty()) { continue; }
if (!local_aabb.min().allFinite() || !local_aabb.max().allFinite()) {
@ -325,19 +312,17 @@ void primitive::update_geometry(const void* new_geometry_ptr, size_t subface_ind
switch (subface_types[i]) {
case surface_type::plane: {
canonical_ptr = data_center->acquire_plane_geometry(new_geometry_ptr);
break;
}
case surface_type::cylinder: {
// auto* desc = static_cast<const cylinder_descriptor_t*>(new_descriptor_ptr);
canonical_ptr = data_center->acquire_cylinder_geometry(new_geometry_ptr);
break;
}
case surface_type::extrude_polyline_side: {
// const auto* raw = static_cast<const extrude_polyline_descriptor_t*>(new_descriptor_ptr);
canonical_ptr = data_center->acquire_extrude_polyline_geometry(new_geometry_ptr);
break;
}
case surface_type::extrude_helixline_side: {
// const auto* raw = static_cast<const extrude_helixline_descriptor_t*>(new_descriptor_ptr);
canonical_ptr = data_center->acquire_extrude_helixline_geometry(new_geometry_ptr);
break;
}
@ -346,7 +331,8 @@ void primitive::update_geometry(const void* new_geometry_ptr, size_t subface_ind
new_geometry.push_back(canonical_ptr);
} else {
// 保持原有 descriptor
if (subface_types[i] == surface_type::plane) {
if (subface_types[i] == surface_type::plane || subface_types[i] == surface_type::sphere) {
// Plane and sphere carry no descriptor.
new_geometry.push_back(nullptr);
} else {
auto get_desc_func = internal::get_geometry_accessor_ptr(subface_types[i]);

106
primitive_process/src/subface/simple/extrude_helixline_side_face.cpp

@ -59,15 +59,6 @@ double extrude_helixline_side_function_impl::eval_sdf(pointer_wrapper<subface> o
const double half_turn = pi / axis_geom.total_theta;
const double world_dist = (p - prev_world_p).norm();
if (prev_t >= 0.0 && world_dist < 0.15 // 空间相邻(约为一个网格步长)
&& std::abs(cur_t - prev_t) > half_turn * 0.8) // axis_t 发生大幅跳变
{
static std::atomic<int> cnt{0};
if (++cnt <= 100) {
std::cout << "[AXIS_JUMP] #" << cnt << " world_dist=" << world_dist << " prev_t=" << prev_t
<< " cur_t=" << cur_t << " delta=" << (cur_t - prev_t) << " half_turn=" << half_turn << "\n";
}
}
prev_t = cur_t;
prev_world_p = p;
}
@ -79,102 +70,9 @@ double extrude_helixline_side_function_impl::eval_sdf(pointer_wrapper<subface> o
profile_local_p.z() = 0.0;
auto [profile_closest_param, dist] = profile_geom.calculate_closest_param(profile_local_p);
// if (axis_closest_param.is_peak_value || axis_geom.isEnd(axis_closest_param.t)) {
// const bool is_outside = profile_geom.pmc(profile_local_p.head<2>(), profile_closest_param);
// dist = is_outside ? std::abs(dist) : -std::abs(dist);
// }
// ===== 调试: 记录 CW 弧区域的 pmc 调用情况 =====
static std::atomic<int> debug_count{0};
bool should_debug = (++debug_count % 5000 == 0);
bool pmc_called = false;
bool pmc_result = false;
if (axis_closest_param.is_peak_value || axis_geom.isEnd(axis_closest_param.t)) {
pmc_called = true;
pmc_result = profile_geom.pmc(profile_local_p.head<2>(), profile_closest_param);
if (should_debug) {
// 输出关键调试信息:最近 profile 点的类型和法向量
double frac_t = profile_closest_param.t - std::floor(profile_closest_param.t);
int seg_n = static_cast<int>(std::floor(profile_closest_param.t));
bool is_arc = (seg_n < (int)profile_geom.thetas.size()) && (profile_geom.thetas[seg_n] > 1e-10);
Eigen::Vector2d profile_normal{0, 0};
if (profile_closest_param.is_peak_value && is_arc) {
profile_normal = profile_geom.calculate_normal(profile_closest_param.t);
}
Eigen::Vector2d p2d = profile_local_p.head<2>();
Eigen::Vector2d closest_2d = profile_closest_param.point.head<2>();
Eigen::Vector2d vec_p_to_closest = closest_2d - p2d;
std::cout << "[SDF_DEBUG] axis_t=" << axis_closest_param.t << " seg=" << seg_n << " frac=" << frac_t
<< " is_arc=" << is_arc << " is_peak=" << profile_closest_param.is_peak_value << " pmc=" << pmc_result
<< " dist=" << dist << " p2d=(" << p2d.x() << "," << p2d.y() << ")"
<< " closest=(" << closest_2d.x() << "," << closest_2d.y() << ")"
<< " normal=(" << profile_normal.x() << "," << profile_normal.y() << ")"
<< " dot=" << vec_p_to_closest.dot(profile_normal) << "\n";
// 验证: 对 CW 弧 (seg=0), 检查法向量是否确实为 R(-frac*theta)*vec_ca
if (is_arc && seg_n == 0) {
const auto iter = profile_geom.vertices.begin() + profile_geom.start_indices[0];
Eigen::Vector2d e = *iter - *(iter + 1); // vec_ca = A - C
double theta = profile_geom.thetas[0];
double phi = frac_t * theta;
Eigen::Vector2d expected_normal(std::cos(phi) * e.x() + std::sin(phi) * e.y(),
-std::sin(phi) * e.x() + std::cos(phi) * e.y());
expected_normal /= e.norm();
std::cout << "[SDF_DEBUG] expected_normal(CW outward)=(" << expected_normal.x() << "," << expected_normal.y()
<< ")"
<< " diff=" << (profile_normal - expected_normal).norm() << "\n";
}
}
dist = pmc_result ? std::abs(dist) : -std::abs(dist);
} else if (should_debug) {
std::cout << "[SDF_DEBUG] pmc NOT called: axis_t=" << axis_closest_param.t
<< " is_peak=" << axis_closest_param.is_peak_value << " isEnd=" << axis_geom.isEnd(axis_closest_param.t)
<< " dist(unsigned)=" << dist << "\n";
}
// [ARC_PMC] 仅记录最近 profile 段为凹弧(seg=0)的调用
// [PMC_FLIP] 检测相邻弧区域点的 pmc 符号翻转
if (pmc_called) {
const int seg_n = static_cast<int>(std::floor(profile_closest_param.t));
const bool is_arc = (seg_n == 0) && !profile_geom.thetas.empty() && (profile_geom.thetas[0] > 1e-10);
if (is_arc) {
// 无条件记录凹弧区域的 pmc 调用(上限 200 条)
{
static std::atomic<int> cnt{0};
if (++cnt <= 200) {
std::cout << "[ARC_PMC] #" << cnt << " axis_t=" << axis_closest_param.t << " p2d=(" << profile_local_p.x()
<< "," << profile_local_p.y() << ")"
<< " pmc=" << pmc_result << " dist=" << dist << "\n";
}
}
// 检测相邻弧区域点的 pmc 翻转
{
thread_local bool prev_arc_pmc = true;
thread_local Eigen::Vector2d prev_arc_p2d{0, 0};
const Eigen::Vector2d cur_p2d = profile_local_p.head<2>();
const double p2d_dist = (cur_p2d - prev_arc_p2d).norm();
if (p2d_dist < 0.3 && pmc_result != prev_arc_pmc) {
static std::atomic<int> cnt{0};
if (++cnt <= 100) {
std::cout << "[PMC_FLIP] #" << cnt << " prev_p2d=(" << prev_arc_p2d.x() << "," << prev_arc_p2d.y()
<< ") pmc=" << prev_arc_pmc << " → cur_p2d=(" << cur_p2d.x() << "," << cur_p2d.y()
<< ") pmc=" << pmc_result << " axis_t=" << axis_closest_param.t << " p2d_jump=" << p2d_dist
<< "\n";
}
}
prev_arc_pmc = pmc_result;
prev_arc_p2d = cur_p2d;
}
}
const bool is_outside = profile_geom.pmc(profile_local_p.head<2>(), profile_closest_param);
dist = is_outside ? std::abs(dist) : -std::abs(dist);
}
return dist;

Loading…
Cancel
Save