From 6065f7860d975c52545fdc57f304bb17c95bfbfb Mon Sep 17 00:00:00 2001 From: linchforever <2766643922@qq.com> Date: Sun, 19 Apr 2026 10:24:27 +0800 Subject: [PATCH] fix: 'compute_polyline_bottom/top_cap_matrix' and 'update_geometry' --- .../interface/base/primitive.hpp | 13 +++--- .../interface/primitive/simple/extrude.hpp | 34 ++++++++------- .../interface/primitive/simple/sphere.hpp | 7 ++++ primitive_process/src/base/primitive.cpp | 2 +- .../src/primitive/simple/extrude.cpp | 41 ++++++++++++++----- 5 files changed, 64 insertions(+), 33 deletions(-) diff --git a/primitive_process/interface/base/primitive.hpp b/primitive_process/interface/base/primitive.hpp index d0fc7e5..d194b50 100644 --- a/primitive_process/interface/base/primitive.hpp +++ b/primitive_process/interface/base/primitive.hpp @@ -25,13 +25,12 @@ EXTERN_C struct PE_API primitive { virtual span> get_subfaces() const = 0; virtual stl_vector_mp get_subface_types() const = 0; virtual stl_vector_mp get_subface_geometries() const = 0; - - void update_geometry(const void *geometry_ptr, size_t subface_index = 0); + virtual void update_geometry(const void *geometry_ptr, size_t subface_index = 0); dynamic_bitset_mp<> judge_sign_by_subface_sign(const stl_vector_mp> &) const; dynamic_bitset_mp<> judge_sign_by_subface_sign(const stl_vector_mp> &, - const stl_vector_mp &, - const stl_vector_mp &) const; + const stl_vector_mp &, + const stl_vector_mp &) const; aabb_t fetch_aabb() const { return m_aabb; } @@ -40,9 +39,9 @@ EXTERN_C struct PE_API primitive { protected: void initialize( const stl_vector_mp &, - const stl_vector_mp &, - const stl_vector_mp &, - const aabb_t &); + const stl_vector_mp &, + const stl_vector_mp &, + const aabb_t &); void recompute_aabb(); aabb_t m_aabb{}; diff --git a/primitive_process/interface/primitive/simple/extrude.hpp b/primitive_process/interface/primitive/simple/extrude.hpp index e3c2580..5df1b75 100644 --- a/primitive_process/interface/primitive/simple/extrude.hpp +++ b/primitive_process/interface/primitive/simple/extrude.hpp @@ -163,15 +163,16 @@ inline vector2d compute_profile_aabb_max(const polyline_descriptor_t* profile) * @param desc polyline descriptor * @return 底盖的 paired_model_matrix */ -inline paired_model_matrix compute_polyline_bottom_cap_matrix(const polyline_descriptor_t& desc) +inline paired_model_matrix compute_polyline_bottom_cap_matrix(const extrude_polyline_geometry_t& geom) { - Eigen::Vector3d origin = Eigen::Map(&desc.points[0].x); - Eigen::Vector3d p1 = Eigen::Map(&desc.points[1].x); - Eigen::Vector3d tangent = (p1 - origin).normalized(); - Eigen::Vector3d axis_normal = Eigen::Map(&desc.reference_normal.x); + const Eigen::Vector2d tangent_2d = geom.axis_geom.calculate_tangent(0.0); + const Eigen::Vector3d tangent_3d = + (geom.axis_to_world.linear() * Eigen::Vector3d(tangent_2d.y(), 0.0, tangent_2d.x())).normalized(); + const Eigen::Vector3d origin = Eigen::Map(&geom.descriptor.axis.points[0].x); + Eigen::Vector3d axis_normal = Eigen::Map(&geom.descriptor.axis.reference_normal.x); axis_normal.normalize(); - return build_polyline_cap_matrix(origin, tangent, axis_normal, false); + return build_polyline_cap_matrix(origin, tangent_3d, axis_normal, false); } /** @@ -179,16 +180,18 @@ inline paired_model_matrix compute_polyline_bottom_cap_matrix(const polyline_des * @param desc polyline descriptor * @return 顶盖的 paired_model_matrix */ -inline paired_model_matrix compute_polyline_top_cap_matrix(const polyline_descriptor_t& desc) +inline paired_model_matrix compute_polyline_top_cap_matrix(const extrude_polyline_geometry_t& geom) { - uint32_t last_idx = desc.point_number - 1; - Eigen::Vector3d origin = Eigen::Map(&desc.points[last_idx].x); - Eigen::Vector3d p_prev = Eigen::Map(&desc.points[last_idx - 1].x); - Eigen::Vector3d tangent = (origin - p_prev).normalized(); - Eigen::Vector3d axis_normal = Eigen::Map(&desc.reference_normal.x); + const double segment_count = static_cast(geom.axis_geom.start_indices.size()); + const Eigen::Vector2d tangent_2d = geom.axis_geom.calculate_tangent(segment_count); + const Eigen::Vector3d tangent_3d = + (geom.axis_to_world.linear() * Eigen::Vector3d(tangent_2d.y(), 0.0, tangent_2d.x())).normalized(); + const uint32_t last_idx = geom.descriptor.axis.point_number - 1; + const Eigen::Vector3d origin = Eigen::Map(&geom.descriptor.axis.points[last_idx].x); + Eigen::Vector3d axis_normal = Eigen::Map(&geom.descriptor.axis.reference_normal.x); axis_normal.normalize(); - return build_polyline_cap_matrix(origin, tangent, axis_normal, true); + return build_polyline_cap_matrix(origin, tangent_3d, axis_normal, true); } /** @@ -223,7 +226,6 @@ inline paired_model_matrix make_helixline_cap_matrix(const helixline_geometry_da return m; } - inline paired_model_matrix compute_helixline_bottom_cap_matrix(const helixline_geometry_data& ag) { return make_helixline_cap_matrix(ag, 0.0); @@ -274,6 +276,8 @@ struct extrude_polyline_t final : primitive { }; } + void update_geometry(const void* new_geometry_ptr, size_t subface_index = 0) override; + /** * @brief 从 descriptor 初始化(内部方法,类似 cylinder 的 initialize) * @details 先准备好所有参数,然后一次性调用基类的 initialize @@ -334,6 +338,8 @@ struct extrude_helixline_t final : primitive { return {surface_type::extrude_helixline_side, surface_type::plane, surface_type::plane}; } + void update_geometry(const void* new_geometry_ptr, size_t subface_index = 0) override; + PE_API void initialize_from_descriptor(primitive_data_center_t* dc, const extrude_helixline_descriptor_t& desc); PE_API void initialize_with_components(primitive_data_center_t* dc, const extrude_helixline_descriptor_t& desc) diff --git a/primitive_process/interface/primitive/simple/sphere.hpp b/primitive_process/interface/primitive/simple/sphere.hpp index 1cece0a..71b51d8 100644 --- a/primitive_process/interface/primitive/simple/sphere.hpp +++ b/primitive_process/interface/primitive/simple/sphere.hpp @@ -26,6 +26,13 @@ struct sphere_t final : primitive { stl_vector_mp get_subface_types() const override { return {surface_type::sphere}; } + // sphere_t does not support geometry descriptor updates. + void update_geometry(const void * new_geometry_ptr, size_t subface_index = 0) override + { + throw std::invalid_argument("sphere_t::update_geometry: sphere geometry is fully encoded in the model matrix " + "and has no separate descriptor. Use apply_transform() to modify the sphere."); + } + marked_subface_ptr_t sphere_face{}; }; } // namespace internal \ No newline at end of file diff --git a/primitive_process/src/base/primitive.cpp b/primitive_process/src/base/primitive.cpp index 8fc89d1..4b72286 100644 --- a/primitive_process/src/base/primitive.cpp +++ b/primitive_process/src/base/primitive.cpp @@ -306,7 +306,7 @@ void primitive::update_geometry(const void* new_geometry_ptr, size_t subface_ind new_geometry.reserve(subfaces.size()); for (size_t i = 0; i < subfaces.size(); ++i) { if (i == subface_index) { - // 规范化新 descriptor + // 规范化新 geometry const void* canonical_ptr = nullptr; switch (subface_types[i]) { diff --git a/primitive_process/src/primitive/simple/extrude.cpp b/primitive_process/src/primitive/simple/extrude.cpp index 3341dfd..a390272 100644 --- a/primitive_process/src/primitive/simple/extrude.cpp +++ b/primitive_process/src/primitive/simple/extrude.cpp @@ -31,8 +31,8 @@ void extrude_polyline_t::initialize_from_descriptor(primitive_data_center_t* dc, axis_matrix.local_to_world = geom->axis_to_world; axis_matrix.world_to_local = geom->axis_to_world.inverse(); - paired_model_matrix bottom_matrix = compute_polyline_bottom_cap_matrix(desc.axis); - paired_model_matrix top_matrix = compute_polyline_top_cap_matrix(desc.axis); + paired_model_matrix bottom_matrix = compute_polyline_bottom_cap_matrix(*geom); + paired_model_matrix top_matrix = compute_polyline_top_cap_matrix(*geom); std::array matrix_storage = {axis_matrix, bottom_matrix, top_matrix}; paired_model_matrix_ptr_t axis_matrix_ptr = make_pointer_wrapper(matrix_storage[0]); @@ -53,14 +53,10 @@ void extrude_polyline_t::initialize_from_descriptor(primitive_data_center_t* dc, bottom_cap_desc = descriptor_defaults::unit_plane; top_cap_desc = descriptor_defaults::unit_plane; } - std::cout << "[EXTRUDE_POLYLINE_INIT] Bottom cap AABB min: (" << bottom_cap_desc.local_aabb_min.x << ", " - << bottom_cap_desc.local_aabb_min.y << ")\n"; - std::cout << "[EXTRUDE_POLYLINE_INIT] Bottom cap AABB max: (" << bottom_cap_desc.local_aabb_max.x << ", " - << bottom_cap_desc.local_aabb_max.y << ")\n"; // 修改initialize调用,传递plane descriptor initialize({axis_matrix_ptr, bottom_matrix_ptr, top_matrix_ptr}, - {false, true, false}, // polyline侧面的法向指向内部,因此需要翻转 + {false, true, false}, {static_cast(geom), nullptr, nullptr}, @@ -69,6 +65,19 @@ void extrude_polyline_t::initialize_from_descriptor(primitive_data_center_t* dc, recompute_aabb(); } +void extrude_polyline_t::update_geometry(const void* new_geometry_ptr, size_t subface_index) +{ + if (subface_index != 0) { + throw std::invalid_argument("extrude_polyline_t::update_geometry: cap planes (index 1 and 2) cannot be " + "updated independently. Their matrices are derived from the axis path. " + "Use replace_profile(), replace_axis(), or initialize_from_descriptor() " + "to rebuild the primitive as a whole."); + } + if (!data_center) { throw std::runtime_error("Primitive not initialized"); } + auto* desc = static_cast(new_geometry_ptr); + initialize_from_descriptor(data_center.raw(), *desc); +} + void extrude_polyline_t::replace_profile(const profile_descriptor_t& new_profile) { if (!data_center) { throw std::runtime_error("Primitive not initialized"); } @@ -125,9 +134,6 @@ void extrude_helixline_t::initialize_from_descriptor(primitive_data_center_t* dc paired_model_matrix bottom_matrix = compute_helixline_bottom_cap_matrix(geom->axis_geom); paired_model_matrix top_matrix = compute_helixline_top_cap_matrix(geom->axis_geom); - std::cout << "[EXTRUDE_HELIXLINE_INIT] Bottom cap matrix(BNTP):\n" << bottom_matrix.local_to_world.matrix() << "\n"; - std::cout << "[EXTRUDE_HELIXLINE_INIT] Top cap matrix(BNTP):\n" << top_matrix.local_to_world.matrix() << "\n"; - std::array matrix_storage = {axis_matrix, bottom_matrix, top_matrix}; paired_model_matrix_ptr_t axis_matrix_ptr = make_pointer_wrapper(matrix_storage[0]); paired_model_matrix_ptr_t bottom_matrix_ptr = make_pointer_wrapper(matrix_storage[1]); @@ -148,13 +154,26 @@ void extrude_helixline_t::initialize_from_descriptor(primitive_data_center_t* dc } initialize({axis_matrix_ptr, bottom_matrix_ptr, top_matrix_ptr}, - {false, true, false}, // helixline侧面的法向指向内部,因此需要翻转 + {false, true, false}, {static_cast(geom), nullptr, nullptr}, aabb_t{}); recompute_aabb(); } +void extrude_helixline_t::update_geometry(const void* new_geometry_ptr, size_t subface_index) +{ + if (subface_index != 0) { + throw std::invalid_argument("extrude_helixline_t::update_geometry: cap planes (index 1 and 2) cannot be " + "updated independently. Their matrices are derived from the helix path. " + "Use replace_profile(), replace_axis(), or initialize_from_descriptor() " + "to rebuild the primitive as a whole."); + } + if (!data_center) { throw std::runtime_error("Primitive not initialized"); } + auto* desc = static_cast(new_geometry_ptr); + initialize_from_descriptor(data_center.raw(), *desc); +} + void extrude_helixline_t::replace_profile(const profile_descriptor_t& new_profile) { if (!data_center) { throw std::runtime_error("Primitive not initialized"); }