|
|
|
@ -4,54 +4,16 @@ |
|
|
|
|
|
|
|
namespace internal |
|
|
|
{ |
|
|
|
|
|
|
|
/// 计算 profile 截面的最大半径(原点到各顶点的最大距离)。
|
|
|
|
/// 用于确保 axis 圆角半径 > profile 半径,防止挤出体内侧自相交。
|
|
|
|
static double compute_profile_max_radius(const polyline_descriptor_t& profile_desc) |
|
|
|
{ |
|
|
|
if (profile_desc.point_number == 0 || profile_desc.points == nullptr) return 0.0; |
|
|
|
|
|
|
|
double max_r2 = 0.0; |
|
|
|
for (uint32_t i = 0; i < profile_desc.point_number; ++i) { |
|
|
|
const double x = profile_desc.points[i].x; |
|
|
|
const double y = profile_desc.points[i].y; |
|
|
|
max_r2 = std::max(max_r2, x * x + y * y); |
|
|
|
} |
|
|
|
|
|
|
|
// 如果有 bulge 圆弧,圆弧中点可能更远,粗略扩大 10%
|
|
|
|
if (profile_desc.bulges != nullptr) { |
|
|
|
double arc_extra = 0.0; |
|
|
|
for (uint32_t i = 0; i < profile_desc.point_number; ++i) { |
|
|
|
const double b = profile_desc.bulges[i]; |
|
|
|
if (std::abs(b) < 1e-12) continue; |
|
|
|
// 圆弧中点偏离弦的距离 = chord/2 * |b|
|
|
|
|
const uint32_t j = (i + 1) % profile_desc.point_number; |
|
|
|
const double dx = profile_desc.points[j].x - profile_desc.points[i].x; |
|
|
|
const double dy = profile_desc.points[j].y - profile_desc.points[i].y; |
|
|
|
arc_extra = std::max(arc_extra, 0.5 * std::sqrt(dx * dx + dy * dy) * std::abs(b)); |
|
|
|
} |
|
|
|
return std::sqrt(max_r2) + arc_extra; |
|
|
|
} |
|
|
|
return std::sqrt(max_r2); |
|
|
|
} |
|
|
|
|
|
|
|
void extrude_polyline_geometry_t::build() |
|
|
|
{ |
|
|
|
const auto& profile_desc = this->descriptor.profiles[0]; |
|
|
|
const auto& axis_desc = this->descriptor.axis; |
|
|
|
|
|
|
|
const double profile_max_radius = compute_profile_max_radius(profile_desc); |
|
|
|
const double axis_min_fillet_radius = profile_max_radius * 0.01; |
|
|
|
|
|
|
|
std::cout << "[extrude_polyline_geometry_t::build] profile_max_radius=" << profile_max_radius |
|
|
|
<< ", axis_min_fillet_radius=" << axis_min_fillet_radius << "\n"; |
|
|
|
|
|
|
|
std::vector<vector3d> filleted_axis_pts; |
|
|
|
std::vector<double> filleted_axis_bgs; |
|
|
|
const fillet_config_t axis_fillet_cfg{ |
|
|
|
/*segment_ratio=*/0.15, |
|
|
|
/*segment_ratio=*/0.01, |
|
|
|
/*min_turn_angle_deg=*/0.5, |
|
|
|
/*min_fillet_radius=*/axis_min_fillet_radius, |
|
|
|
/*is_axis=*/true}; |
|
|
|
insert_polyline_corner_fillets(axis_desc, filleted_axis_pts, filleted_axis_bgs, axis_fillet_cfg); |
|
|
|
|
|
|
|
@ -68,18 +30,10 @@ void extrude_polyline_geometry_t::build() |
|
|
|
|
|
|
|
axis_geom.build_as_axis(filleted_axis_desc, profile_desc.reference_normal, axis_to_world, polyline_aabb); |
|
|
|
|
|
|
|
for (uint32_t k = 0; k < axis_desc.point_number; ++k) { |
|
|
|
polyline_aabb.extend(Eigen::Vector3d(axis_desc.points[k].x, axis_desc.points[k].y, axis_desc.points[k].z)); |
|
|
|
} |
|
|
|
polyline_aabb.min().array() -= profile_max_radius; |
|
|
|
polyline_aabb.max().array() += profile_max_radius; |
|
|
|
|
|
|
|
// 对 profile 截面插入圆角(不需要最小半径约束)
|
|
|
|
std::vector<vector3d> filleted_profile_pts; |
|
|
|
std::vector<double> filleted_profile_bgs; |
|
|
|
const fillet_config_t profile_fillet_cfg{/*segment_ratio=*/0.05, |
|
|
|
/*min_turn_angle_deg=*/0.5, |
|
|
|
/*min_fillet_radius=*/0.0, // profile 自身不需要最小半径约束
|
|
|
|
/*is_axis=*/false}; |
|
|
|
insert_polyline_corner_fillets(profile_desc, filleted_profile_pts, filleted_profile_bgs, profile_fillet_cfg); |
|
|
|
|
|
|
|
|