Browse Source

fix: the orientation of corner fillets and inserting arcs on the polyline axis

main
linchforever 3 days ago
parent
commit
57c7a7a865
  1. 2
      primitive_process/interface/subface/geometry/polyline_fillet.hpp
  2. 19
      primitive_process/src/subface/geometry/extrude_helixline_geometry.cpp
  3. 75
      primitive_process/src/subface/geometry/extrude_polyline_geometry.cpp
  4. 14
      primitive_process/src/subface/geometry/polyline_fillet.cpp

2
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<vector3d>& out_points,
std::vector<double>& out_bulges,
const fillet_config_t& cfg = {});

19
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<vector3d> filleted_pts;
std::vector<double> 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<uint32_t>(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);

75
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<vector3d> filleted_axis_pts;
std::vector<double> 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<uint32_t>(filleted_axis_pts.size());
filleted_axis_desc.points = filleted_axis_pts.data();
filleted_axis_desc.bulge_number = static_cast<uint32_t>(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";
axis_geom.build_as_axis(filleted_axis_desc, // 改为 filleted_axis_desc
profile_desc.reference_normal,
axis_to_world,
polyline_aabb);
// 对 profile 各衔接顶点插入微小圆角弧
// segment_ratio=0.05 意味着每段损失约 5%,棱角感仍然明显。
// 如需更锋利,将 segment_ratio 调至 0.01-0.02;
// 如需更平滑,调至 0.1-0.2。
std::vector<vector3d> filleted_pts;
std::vector<double> 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<uint32_t>(filleted_pts.size());
filleted_desc.points = filleted_pts.data();
filleted_desc.bulge_number = static_cast<uint32_t>(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;
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<vector3d> filleted_profile_pts;
std::vector<double> 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<uint32_t>(filleted_profile_pts.size());
filleted_profile_desc.points = filleted_profile_pts.data();
filleted_profile_desc.bulge_number = static_cast<uint32_t>(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();

14
primitive_process/src/subface/geometry/polyline_fillet.cpp

@ -85,7 +85,7 @@ Corner compute_corner(const std::vector<Eigen::Vector2d>& 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<vector3d>& 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<vector3d>& out_points,
std::vector<double>& 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);
}
if (closed) {
assert(out_points.size() == out_bulges.size());
} else {
assert(out_bulges.size() + 1 == out_points.size()); // 开放折线:凸度数量 = 点数 - 1
}
}
} // namespace internal
Loading…
Cancel
Save