From d6b09e6219724f6f850ac064897529d533c24ba4 Mon Sep 17 00:00:00 2001 From: linchforever <2766643922@qq.com> Date: Fri, 17 Apr 2026 18:54:56 +0800 Subject: [PATCH] fix: modify the implementation of primitive transform --- primitive_process/src/base/primitive.cpp | 80 ++++++------- .../simple/extrude_helixline_side_face.cpp | 112 +----------------- 2 files changed, 38 insertions(+), 154 deletions(-) diff --git a/primitive_process/src/base/primitive.cpp b/primitive_process/src/base/primitive.cpp index fd9dfe1..8fc89d1 100644 --- a/primitive_process/src/base/primitive.cpp +++ b/primitive_process/src/base/primitive.cpp @@ -44,14 +44,6 @@ dynamic_bitset_mp<> primitive::judge_sign_by_subface_sign(const stl_vector_mpdata_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& matrices, const stl_vector_mp& reversed_flags, const stl_vector_mp& geometry, @@ -59,7 +51,7 @@ void primitive::initialize(const stl_vector_mp raw_geometry = geometry.empty() ? get_subface_geometries() : geometry; stl_vector_mp canonical_geometry; @@ -84,7 +76,8 @@ void primitive::initialize(const stl_vector_mprelease_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 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(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(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(subfaces[i].get_ptr()); local_aabb.extend(face->get_aabb()); // 通过访问器读取 } else if (subface_types[i] == surface_type::extrude_helixline_side) { auto* face = static_cast(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(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(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(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(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]); @@ -385,7 +371,7 @@ void primitive::update_geometry(const void* new_geometry_ptr, size_t subface_ind current_matrices[subface_index], new_geometry[subface_index], subfaces[subface_index]); - subfaces[subface_index].set_mark(saved_mark); + subfaces[subface_index].set_mark(saved_mark); // 重新计算 AABB recompute_aabb(); } \ No newline at end of file diff --git a/primitive_process/src/subface/simple/extrude_helixline_side_face.cpp b/primitive_process/src/subface/simple/extrude_helixline_side_face.cpp index 551d251..d4569c8 100644 --- a/primitive_process/src/subface/simple/extrude_helixline_side_face.cpp +++ b/primitive_process/src/subface/simple/extrude_helixline_side_face.cpp @@ -59,15 +59,6 @@ double extrude_helixline_side_function_impl::eval_sdf(pointer_wrapper 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 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,104 +70,11 @@ double extrude_helixline_side_function_impl::eval_sdf(pointer_wrapper 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 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(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(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 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 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; - } - } - } - + 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); + } + return dist; }