diff --git a/primitive_process/interface/subface/geometry/polyline_fillet.hpp b/primitive_process/interface/subface/geometry/polyline_fillet.hpp index 12a28a2..3fd2c99 100644 --- a/primitive_process/interface/subface/geometry/polyline_fillet.hpp +++ b/primitive_process/interface/subface/geometry/polyline_fillet.hpp @@ -22,7 +22,7 @@ struct fillet_config_t { // @param out_points 输出点列表 // @param out_bulges 输出 bulge 列表(与 out_points 等长) // @param cfg 圆角参数 -void insert_profile_corner_fillets(const polyline_descriptor_t& profile, +void insert_polyline_corner_fillets(const polyline_descriptor_t& profile, std::vector& out_points, std::vector& out_bulges, const fillet_config_t& cfg = {}); diff --git a/primitive_process/src/subface/geometry/extrude_helixline_geometry.cpp b/primitive_process/src/subface/geometry/extrude_helixline_geometry.cpp index d4d8de5..9ed08f6 100644 --- a/primitive_process/src/subface/geometry/extrude_helixline_geometry.cpp +++ b/primitive_process/src/subface/geometry/extrude_helixline_geometry.cpp @@ -12,19 +12,12 @@ void extrude_helixline_geometry_t::build() // 构建 axis 几何数据 axis_geom.build_from_descriptor(axis_desc, axis_to_world, helixline_aabb); - const auto& matrix_handle = this->axis_to_world.matrix(); - const Eigen::Vector3d N = -matrix_handle.col(0); - const Eigen::Vector3d T = (matrix_handle.col(2) * this->axis_geom.height - + this->axis_geom.radius * this->axis_geom.total_theta * matrix_handle.col(1)) - .normalized(); - const Eigen::Vector3d B = N.cross(T); - // 对 profile 各衔接顶点插入微小圆角弧 std::vector filleted_pts; std::vector filleted_bgs; - const fillet_config_t fillet_cfg{/*segment_ratio=*/0.02, + const fillet_config_t fillet_cfg{/*segment_ratio=*/3.0, /*min_turn_angle_deg=*/0.5}; - insert_profile_corner_fillets(profile_desc, filleted_pts, filleted_bgs, fillet_cfg); + insert_polyline_corner_fillets(profile_desc, filleted_pts, filleted_bgs, fillet_cfg); polyline_descriptor_t filleted_desc{}; filleted_desc.point_number = static_cast(filleted_pts.size()); @@ -38,6 +31,14 @@ void extrude_helixline_geometry_t::build() << "original profile points: " << profile_desc.point_number << ", after fillet: " << filleted_desc.point_number << "\n"; + + const auto& matrix_handle = this->axis_to_world.matrix(); + const Eigen::Vector3d N = -matrix_handle.col(0); + const Eigen::Vector3d T = (matrix_handle.col(2) * this->axis_geom.height + + this->axis_geom.radius * this->axis_geom.total_theta * matrix_handle.col(1)) + .normalized(); + const Eigen::Vector3d B = N.cross(T); + // 构建 profile 几何数据(使用插入圆角后的 descriptor) aabb_t_dim<2> profile_aabb; profile_geom.build_as_profile(filleted_desc, B, N, matrix_handle.col(3).head<3>(), profile_aabb); diff --git a/primitive_process/src/subface/geometry/extrude_polyline_geometry.cpp b/primitive_process/src/subface/geometry/extrude_polyline_geometry.cpp index 81b3d02..b8edcd3 100644 --- a/primitive_process/src/subface/geometry/extrude_polyline_geometry.cpp +++ b/primitive_process/src/subface/geometry/extrude_polyline_geometry.cpp @@ -9,40 +9,63 @@ void extrude_polyline_geometry_t::build() const auto& profile_desc = this->descriptor.profiles[0]; const auto& axis_desc = this->descriptor.axis; - // 构建 axis 几何数据,同时得到 axis_to_world 坐标系 - axis_geom.build_as_axis(axis_desc, profile_desc.reference_normal, axis_to_world, polyline_aabb); + // 对 axis 折线插入微小圆角弧 + std::cout << "[extrude_polyline_geometry_t::build]: inserting tiny curve for axis" + << " segment_ratio=" << 0.1 << ", min_turn_angle_deg=" << 0.0 << "\n"; + std::vector filleted_axis_pts; + std::vector filleted_axis_bgs; + const fillet_config_t axis_fillet_cfg{/*segment_ratio=*/0.1, + /*min_turn_angle_deg=*/0.0}; + insert_polyline_corner_fillets(axis_desc, filleted_axis_pts, filleted_axis_bgs, axis_fillet_cfg); - // 从 axis_to_world 中提取投影方向 - const Eigen::Vector3d proj_x = axis_to_world.matrix().col(0).head<3>(); // Binormal - const Eigen::Vector3d proj_y = axis_to_world.matrix().col(1).head<3>(); // Normal - const Eigen::Vector3d origin = axis_to_world.matrix().col(3).head<3>(); + // 构建圆角后的 axis 临时描述符 + polyline_descriptor_t filleted_axis_desc{}; + filleted_axis_desc.point_number = static_cast(filleted_axis_pts.size()); + filleted_axis_desc.points = filleted_axis_pts.data(); + filleted_axis_desc.bulge_number = static_cast(filleted_axis_bgs.size()); + filleted_axis_desc.bulges = filleted_axis_bgs.data(); + filleted_axis_desc.reference_normal = axis_desc.reference_normal; + filleted_axis_desc.is_close = axis_desc.is_close; + + std::cout << "[extrude_polyline_geometry_t::build] " + << "original axis points: " << axis_desc.point_number << ", after fillet: " << filleted_axis_desc.point_number + << "\n"; - // 对 profile 各衔接顶点插入微小圆角弧 - // segment_ratio=0.05 意味着每段损失约 5%,棱角感仍然明显。 - // 如需更锋利,将 segment_ratio 调至 0.01-0.02; - // 如需更平滑,调至 0.1-0.2。 - std::vector filleted_pts; - std::vector filleted_bgs; - const fillet_config_t fillet_cfg{/*segment_ratio=*/0.05, - /*min_turn_angle_deg=*/0.5}; - insert_profile_corner_fillets(profile_desc, filleted_pts, filleted_bgs, fillet_cfg); - - // 构建临时 descriptor 指向圆角后的数据(不修改原始 descriptor) - polyline_descriptor_t filleted_desc{}; - filleted_desc.point_number = static_cast(filleted_pts.size()); - filleted_desc.points = filleted_pts.data(); - filleted_desc.bulge_number = static_cast(filleted_bgs.size()); - filleted_desc.bulges = filleted_bgs.data(); - filleted_desc.reference_normal = profile_desc.reference_normal; - filleted_desc.is_close = profile_desc.is_close; + axis_geom.build_as_axis(filleted_axis_desc, // 改为 filleted_axis_desc + profile_desc.reference_normal, + axis_to_world, + polyline_aabb); + + std::cout << "[extrude_polyline_geometry_t::build]: inserting tiny curve for profile" + << " segment_ratio=" << 0.05 << ", min_turn_angle_deg=" << 0.0 << "\n"; + std::vector filleted_profile_pts; + std::vector filleted_profile_bgs; + const fillet_config_t profile_fillet_cfg{/*segment_ratio=*/0.1, + /*min_turn_angle_deg=*/0.0}; + insert_polyline_corner_fillets(profile_desc, filleted_profile_pts, filleted_profile_bgs, profile_fillet_cfg); + + polyline_descriptor_t filleted_profile_desc{}; + filleted_profile_desc.point_number = static_cast(filleted_profile_pts.size()); + filleted_profile_desc.points = filleted_profile_pts.data(); + filleted_profile_desc.bulge_number = static_cast(filleted_profile_bgs.size()); + filleted_profile_desc.bulges = filleted_profile_bgs.data(); + filleted_profile_desc.reference_normal = profile_desc.reference_normal; + filleted_profile_desc.is_close = profile_desc.is_close; std::cout << "[extrude_polyline_geometry_t::build] " - << "original profile points: " << profile_desc.point_number << ", after fillet: " << filleted_desc.point_number + << "original profile points: " << profile_desc.point_number + << ", after fillet: " << filleted_profile_desc.point_number << "\n"; + + // 从 axis_to_world 中提取投影方向 + const Eigen::Vector3d proj_x = axis_to_world.matrix().col(0).head<3>(); // Binormal + const Eigen::Vector3d proj_y = axis_to_world.matrix().col(1).head<3>(); // Normal + const Eigen::Vector3d origin = axis_to_world.matrix().col(3).head<3>(); + // 构建 profile 几何数据(使用插入圆角后的 descriptor) aabb_t_dim<2> profile_aabb; - profile_geom.build_as_profile(filleted_desc, proj_x, proj_y, origin, profile_aabb); + profile_geom.build_as_profile(filleted_profile_desc, proj_x, proj_y, origin, profile_aabb); // 将 profile 的最大范围扩展到 polyline_aabb const auto profile_max_extent = profile_aabb.max().cwiseMax(profile_aabb.min().cwiseAbs()).maxCoeff(); diff --git a/primitive_process/src/subface/geometry/polyline_fillet.cpp b/primitive_process/src/subface/geometry/polyline_fillet.cpp index 0646d27..3428e60 100644 --- a/primitive_process/src/subface/geometry/polyline_fillet.cpp +++ b/primitive_process/src/subface/geometry/polyline_fillet.cpp @@ -85,7 +85,7 @@ Corner compute_corner(const std::vector& pts, // bulge 符号:cross>0 → 左转(CCW多边形凸角) → CW弧 → 负 bulge double fillet_bulge = std::tan(turn_angle / 4.0); const double cross = T_in.x() * T_out.y() - T_in.y() * T_out.x(); - if (cross > 0.0) fillet_bulge = -fillet_bulge; + if (cross < 0.0) fillet_bulge = -fillet_bulge; c.active = true; c.fillet_bulge = fillet_bulge; @@ -105,7 +105,7 @@ inline void push_point(std::vector& out_points, } // anonymous namespace -void insert_profile_corner_fillets(const polyline_descriptor_t& profile, +void insert_polyline_corner_fillets(const polyline_descriptor_t& profile, std::vector& out_points, std::vector& out_bulges, const fillet_config_t& cfg) @@ -122,7 +122,8 @@ void insert_profile_corner_fillets(const polyline_descriptor_t& profile, if (n < 3) { for (uint32_t i = 0; i < n; ++i) { out_points.push_back(profile.points[i]); - out_bulges.push_back(profile.bulges ? profile.bulges[i] : 0.0); + // 只有前n-1个顶点需要凸度(开放折线) + if (i < n - 1) { out_bulges.push_back(profile.bulges ? profile.bulges[i] : 0.0); } } return; } @@ -204,12 +205,15 @@ void insert_profile_corner_fillets(const polyline_descriptor_t& profile, } // 末点:始终为 pts[n-1](端点,没有圆角) - // bulge 对最后一点无意义(无后续段),填 0.0 out_points.push_back(profile.points[n - 1]); - out_bulges.push_back(0.0); + //out_bulges.push_back(0.0); } - assert(out_points.size() == out_bulges.size()); + if (closed) { + assert(out_points.size() == out_bulges.size()); + } else { + assert(out_bulges.size() + 1 == out_points.size()); // 开放折线:凸度数量 = 点数 - 1 + } } } // namespace internal \ No newline at end of file