Browse Source

fix: Improve 'insert_polyline_corner_fillets' function and fix the mapping issue in 'polyline_geometry_data::calculate_closest_param'

main
linchforever 3 days ago
parent
commit
da3efa945c
  1. 6
      primitive_process/src/subface/geometry/extrude_helixline_geometry.cpp
  2. 77
      primitive_process/src/subface/geometry/extrude_polyline_geometry.cpp
  3. 159
      primitive_process/src/subface/geometry/geometry_data.cpp
  4. 119
      primitive_process/src/subface/geometry/polyline_fillet.cpp
  5. 6
      primitive_process/src/subface/simple/extrude_helixline_side_face.cpp

6
primitive_process/src/subface/geometry/extrude_helixline_geometry.cpp

@ -15,8 +15,10 @@ void extrude_helixline_geometry_t::build()
// 对 profile 各衔接顶点插入微小圆角弧
std::vector<vector3d> filleted_pts;
std::vector<double> filleted_bgs;
const fillet_config_t fillet_cfg{/*segment_ratio=*/3.0,
/*min_turn_angle_deg=*/0.5};
const fillet_config_t fillet_cfg{/*segment_ratio=*/0.05,
/*min_turn_angle_deg=*/0.5,
/*min_fillet_radius=*/0.0, // profile 自身不需要最小半径约束
/*is_axis=*/true};
insert_polyline_corner_fillets(profile_desc, filleted_pts, filleted_bgs, fillet_cfg);
polyline_descriptor_t filleted_desc{};

77
primitive_process/src/subface/geometry/extrude_polyline_geometry.cpp

@ -1,24 +1,60 @@
#include <subface/geometry/extrude_polyline_geometry.hpp>
#include <subface/geometry/polyline_fillet.hpp>
#include <cmath>
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;
// 对 axis 折线插入微小圆角弧
std::cout << "[extrude_polyline_geometry_t::build]: inserting tiny curve for axis"
<< " segment_ratio=" << 0.1 << ", min_turn_angle_deg=" << 0.0 << "\n";
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.1,
/*min_turn_angle_deg=*/0.0};
const fillet_config_t axis_fillet_cfg{
/*segment_ratio=*/0.15,
/*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);
// 构建圆角后的 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();
@ -28,20 +64,23 @@ void extrude_polyline_geometry_t::build()
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: " << axis_desc.point_number << " pts → " << filleted_axis_desc.point_number << " pts (after fillet)\n";
axis_geom.build_as_axis(filleted_axis_desc, // 改为 filleted_axis_desc
profile_desc.reference_normal,
axis_to_world,
polyline_aabb);
axis_geom.build_as_axis(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";
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.1,
/*min_turn_angle_deg=*/0.0};
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);
polyline_descriptor_t filleted_profile_desc{};
@ -53,10 +92,8 @@ void extrude_polyline_geometry_t::build()
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_profile_desc.point_number
<< "\n";
<< "profile: " << profile_desc.point_number << " pts → " << filleted_profile_desc.point_number
<< " pts (after fillet)\n";
// 从 axis_to_world 中提取投影方向
const Eigen::Vector3d proj_x = axis_to_world.matrix().col(0).head<3>(); // Binormal

159
primitive_process/src/subface/geometry/geometry_data.cpp

@ -205,8 +205,10 @@ void polyline_geometry_data::build_as_axis(const polyline_descriptor_t&
profile_aabb);
const auto& profile_aabb_min = profile_aabb.min();
const auto& profile_aabb_max = profile_aabb.max();
aabb = aabb_t(Eigen::Vector3d(profile_aabb_min.y(), 0.0, profile_aabb_min.x()),
Eigen::Vector3d(profile_aabb_max.y(), 0.0, profile_aabb_max.x()));
aabb = aabb_t(
Eigen::Vector3d(profile_aabb_min.y(), 0.0, profile_aabb_min.x()),
Eigen::Vector3d(profile_aabb_max.y(), 0.0, profile_aabb_max.x())
);
}
void polyline_geometry_data::build_as_axis(polyline_descriptor_t&& desc,
@ -282,94 +284,26 @@ void polyline_geometry_data::build_as_axis(polyline_descriptor_t&&
frac = 1.0;
}
// 调试控制:每1000次调用打印一次调试信息
static int debug_counter = 0;
constexpr int DEBUG_INTERVAL = 10000;
bool should_debug = (++debug_counter % DEBUG_INTERVAL == 0);
if (should_debug) {
std::cout << "[DEBUG calculate_normal] 调用#" << debug_counter << " t=" << t << " n=" << n << " frac=" << frac
<< " 总段数=" << this->start_indices.size() << " 类型=" << (this->thetas[n] <= EPSILON ? "直线" : "圆弧")
<< std::endl;
}
const auto iter = this->vertices.begin() + this->start_indices[n];
if (this->thetas[n] <= EPSILON) {
// 直线段:计算切向量然后获取法向量
const auto temp = (*(iter + 1) - *iter).normalized();
if (should_debug) {
std::cout << "[DEBUG 直线段] 起点: (" << iter->x() << ", " << iter->y() << ")"
<< " 终点: (" << (iter + 1)->x() << ", " << (iter + 1)->y() << ")"
<< " 切向量: (" << temp.x() << ", " << temp.y() << ")"
<< " 切向量长度: " << temp.norm() << std::endl;
}
Eigen::Vector2d normal = {-temp.y(), temp.x()};
if (should_debug) {
std::cout << "[DEBUG 直线段] 法向量: (" << normal.x() << ", " << normal.y() << ")"
<< " 法向量长度: " << normal.norm() << std::endl;
}
return normal;
} else {
// 圆弧段:计算法向量方向
const Eigen::Vector2d vec_ca = *iter - *(iter + 1); // a - c
const Eigen::Vector2d vec_cd = *(iter + 2) - *(iter + 1); // d - c
if (should_debug) {
std::cout << "[DEBUG 圆弧段] 起点A: (" << iter->x() << ", " << iter->y() << ")"
<< " 圆心C: (" << (iter + 1)->x() << ", " << (iter + 1)->y() << ")"
<< " 中间点D: (" << (iter + 2)->x() << ", " << (iter + 2)->y() << ")"
<< " 终点B: (" << (iter + 3)->x() << ", " << (iter + 3)->y() << ")" << std::endl;
std::cout << "[DEBUG 圆弧段] vec_ca: (" << vec_ca.x() << ", " << vec_ca.y() << ") 长度: " << vec_ca.norm()
<< " vec_cd: (" << vec_cd.x() << ", " << vec_cd.y() << ") 长度: " << vec_cd.norm() << std::endl;
}
const double cross = vec_ca.x() * vec_cd.y() - vec_ca.y() * vec_cd.x();
const double bulge_sign = (cross > 1e-12) ? 1.0 : -1.0;
if (should_debug) {
std::cout << "[DEBUG 圆弧段] 叉积=" << cross << " 方向sign=" << bulge_sign << " theta=" << this->thetas[n] << "("
<< (this->thetas[n] * 180.0 / pi) << "°)"
<< " 半径=" << vec_ca.norm() << std::endl;
}
const auto alpha = std::cos(frac * this->thetas[n]);
const auto beta = std::sin(frac * this->thetas[n]);
if (should_debug) {
std::cout << "[DEBUG 圆弧段] 参数计算: frac*theta=" << (frac * this->thetas[n]) << "("
<< (frac * this->thetas[n] * 180.0 / pi) << "°)"
<< " alpha=cos=" << alpha << " beta=sin=" << beta << std::endl;
}
// 计算法向量
Eigen::Vector2d normal = bulge_sign * ((alpha + beta) * *(iter + 1) - alpha * *iter - beta * *(iter + 2));
if (should_debug) {
std::cout << "[DEBUG 圆弧段] 法向量: (" << normal.x() << ", " << normal.y() << ")"
<< " 长度: " << normal.norm() << std::endl;
// 检查法向量长度是否正常
double norm_length = normal.norm();
if (norm_length < 0.5 || norm_length > 2.0) {
std::cout << "[DEBUG 警告] 法向量长度异常: " << norm_length << std::endl;
// 输出详细分量信息用于调试
Eigen::Vector2d comp1 = (alpha + beta) * *(iter + 1);
Eigen::Vector2d comp2 = -alpha * *iter;
Eigen::Vector2d comp3 = -beta * *(iter + 2);
Eigen::Vector2d sum = comp1 + comp2 + comp3;
std::cout << "[DEBUG 分量详情] comp1=(" << comp1.x() << "," << comp1.y() << ")"
<< " comp2=(" << comp2.x() << "," << comp2.y() << ")"
<< " comp3=(" << comp3.x() << "," << comp3.y() << ")"
<< " 未缩放向量=(" << sum.x() << "," << sum.y() << ")" << std::endl;
}
}
return normal;
}
}
@ -389,11 +323,12 @@ void polyline_geometry_data::build_as_axis(polyline_descriptor_t&&
auto make_vertex_3d = [&](const Eigen::Vector2d& v) -> Eigen::Vector3d {
if (this->is_axis)
return {v.y(), 0., v.x()};
return {v.y(), 0., v.x()}; // Axis: (x,z) -> (z,0,x)
else
return {v.x(), v.y(), 0.};
return {v.x(), v.y(), 0.}; // Profile: (x,y) -> (x,y,0)
};
// 直线段最近点计算
auto line_cpm = [&](auto index) -> comparable_closest_param_t {
const auto iter = this->vertices.begin() + this->start_indices[index];
const auto line_vec = *(iter + 1) - *iter;
@ -412,48 +347,36 @@ void polyline_geometry_data::build_as_axis(polyline_descriptor_t&&
const auto raw_t = line_vec.dot(p_dir);
// 投影越界时直接返回较近端点
// raw_t ≤ 0 说明 P 在起点外侧,无需计算终点距离
if (raw_t <= 0) {
Eigen::Vector3d v = make_vertex_3d(*iter);
return {v, 0.0, (p - v).norm(), 1., false};
}
// raw_t ≥ len² 说明 P 在终点外侧,无需计算起点距离
if (raw_t >= line_vec_length_2) {
Eigen::Vector3d v = make_vertex_3d(*(iter + 1));
return {v, 1.0, (p - v).norm(), 1., false};
}
const auto p_dir_length_2 = p_dir.squaredNorm();
const auto t = raw_t / line_vec_length_2;
Eigen::Vector3d closest_point_3d;
double dist;
// 计算最近点
const Eigen::Vector2d closest_2d = *iter + t * line_vec;
Eigen::Vector3d closest_point_3d = make_vertex_3d(closest_2d);
if (this->is_axis) {
// Axis
closest_point_3d.x() = (1 - t) * iter->y() + t * (iter + 1)->y();
closest_point_3d.y() = 0;
closest_point_3d.z() = (1 - t) * iter->x() + t * (iter + 1)->x();
dist = (p - closest_point_3d).norm();
} else {
// Profile
closest_point_3d.x() = (1 - t) * iter->x() + t * (iter + 1)->x();
closest_point_3d.y() = (1 - t) * iter->y() + t * (iter + 1)->y();
closest_point_3d.z() = 0;
double dist = (p - closest_point_3d).norm();
dist = std::sqrt(p_dir_length_2 - raw_t * raw_t / line_vec_length_2 + p[2] * p[2]);
}
return {closest_point_3d, t, dist, 1., true};
};
// 圆弧段最近点计算
auto circle_cpm = [&](auto index) -> comparable_closest_param_t {
const auto iter = this->vertices.begin() + this->start_indices[index];
const auto theta = this->thetas[index];
const auto base_vec1 = *iter - *(iter + 1); // 起点 - 圆心
const auto base_vec2 = *(iter + 2) - *(iter + 1); // 切线辅助点 d - 圆心 c(非弧终点 b
const auto base_vec2 = *(iter + 2) - *(iter + 1); // 切线辅助点 d - 圆心 c
Eigen::Vector2d p_vec;
double cross_bv = base_vec1.x() * base_vec2.y() - base_vec1.y() * base_vec2.x();
bool is_cw = (cross_bv < 0);
if (this->is_axis) {
p_vec = Eigen::Vector2d(p[2], p[0]) - *(iter + 1);
} else {
@ -462,46 +385,41 @@ void polyline_geometry_data::build_as_axis(polyline_descriptor_t&&
const auto p_vec_norm = p_vec.norm(); // 查询点到圆心的距离
const auto r = base_vec1.norm(); // 圆弧半径
const double off_plane = this->is_axis ? p[1] : p[2];
if (p_vec_norm < EPSILON) {
// 查询点恰好在圆心,选弧段起点
const auto closest_point = *iter;
const Eigen::Vector3d closest_point = make_vertex_3d(*iter);
const auto dis_on_plane = -r;
return {
{closest_point.x(), closest_point.y(), 0},
0.0,
std::sqrt(p[2] * p[2] + dis_on_plane * dis_on_plane),
1.,
false
};
return {closest_point, 0.0, std::sqrt(off_plane * off_plane + dis_on_plane * dis_on_plane), 1., false};
}
const auto local_x = base_vec1.dot(p_vec);
const auto local_y = base_vec2.dot(p_vec);
double phi = std::atan2(local_y, local_x);
// [DEBUG_CIRCLE_CPM] 对凹弧(CW)打印 phi 分布,验证是否全为负
{
static std::atomic<int> cw_cnt{0};
if (is_cw && ++cw_cnt <= 100) {
std::cout << "[DEBUG_CIRCLE_CPM] CW弧 #" << cw_cnt << " seg=" << index << " phi=" << phi << " theta=" << theta
<< " phi_in_range=[" << (-theta) << "," << 0 << "]"
<< " cross_bv=" << cross_bv << " p_vec=(" << p_vec.x() << "," << p_vec.y() << ")"
<< " base_vec1=(" << base_vec1.x() << "," << base_vec1.y() << ")"
<< " base_vec2=(" << base_vec2.x() << "," << base_vec2.y() << ")"
<< " -> fallback_to_endpoint=" << (phi < -EPSILON || phi > theta + 1e-9 ? "YES" : "NO") << "\n";
}
// 根据圆弧转向调整 phi
if (!is_cw) {
// CCW: 有效区间 [0, theta]
if (theta > pi + 1e-9) {
if (phi < -EPSILON) phi += two_pi;
} else {
if (phi < -EPSILON) phi = -1.0; // 触发端点回退
}
} else {
// CW: 有效区间 [-theta, 0],翻转后统一用 [0, theta] 处理
phi = -phi; // 将 CW 的 phi 反号,使有效范围变为 [0, theta]
if (theta > pi + 1e-9) {
if (phi < -EPSILON) { phi += two_pi; }
if (phi < -EPSILON) phi += two_pi;
} else {
// 劣弧:phi 只应在 [0, theta],负值直接视为 gap
if (phi < -EPSILON) {
phi = -1.0; // 强制触发端点回退
if (phi < -EPSILON) phi = -1.0;
}
}
// 弧段越界时返回较近端点
if (phi < -1e-9 || phi > theta + 1e-9) {
const Eigen::Vector3d start_3d = {iter->x(), iter->y(), 0.};
const Eigen::Vector3d end_3d = {(iter + 3)->x(), (iter + 3)->y(), 0.};
const Eigen::Vector3d start_3d = make_vertex_3d(*iter);
const Eigen::Vector3d end_3d = make_vertex_3d(*(iter + 3));
const double dist_start = (p - start_3d).norm();
const double dist_end = (p - end_3d).norm();
if (dist_start <= dist_end)
@ -511,18 +429,19 @@ void polyline_geometry_data::build_as_axis(polyline_descriptor_t&&
}
const auto dis_on_plane = p_vec_norm - r;
const auto closest_point = p_vec / p_vec_norm * r + *(iter + 1);
const Eigen::Vector2d closest_2d = p_vec / p_vec_norm * r + *(iter + 1);
Eigen::Vector3d closest_3d = make_vertex_3d(closest_2d);
return {
{closest_point.x(), closest_point.y(), 0},
closest_3d,
phi / theta,
std::sqrt(p[2] * p[2] + dis_on_plane * dis_on_plane),
std::sqrt(off_plane * off_plane + dis_on_plane * dis_on_plane),
1.,
true
};
};
// 单次遍历
// 计算每个线段的最近点
std::vector<comparable_closest_param_t> closest_params(this->thetas.size());
std::vector<size_t> indices(this->thetas.size());
std::iota(indices.begin(), indices.end(), 0);

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

@ -1,6 +1,5 @@
#include <subface/geometry/polyline_fillet.hpp>
#include <math/math_defs.hpp>
//#include <algorithm>
namespace internal
{
@ -105,7 +104,8 @@ inline void push_point(std::vector<vector3d>& out_points,
} // anonymous namespace
void insert_polyline_corner_fillets(const polyline_descriptor_t& profile,
void insert_polyline_corner_fillets(const polyline_descriptor_t& desc,
std::vector<vector3d>& out_points,
std::vector<double>& out_bulges,
const fillet_config_t& cfg)
@ -113,107 +113,80 @@ void insert_polyline_corner_fillets(const polyline_descriptor_t& profile,
out_points.clear();
out_bulges.clear();
const uint32_t n = profile.point_number;
const bool closed = profile.is_close;
const uint32_t n = desc.point_number;
const bool closed = desc.is_close;
std::function<Eigen::Vector2d(const vector3d&)> to_2d;
std::function<vector3d(const Eigen::Vector2d&, double)> to_3d;
// ── 退化情况:点数过少,无内部衔接顶点可处理 ────────────────────────
// 闭合:至少需要 3 点才有顶点(含衔接)
// 不闭合:至少需要 3 点才有内部顶点(至少 1 个 interior vertex)
if (cfg.is_axis) {
// axis:XZ 平面
to_2d = [](const vector3d& p) -> Eigen::Vector2d {return {p.x, p.z};};
to_3d = [](const Eigen::Vector2d& q, double fixed_y) -> vector3d { return {q.x(), fixed_y, q.y()};};
} else {
// profile:XY 平面
to_2d = [](const vector3d& p) -> Eigen::Vector2d {return {p.x, p.y};};
to_3d = [](const Eigen::Vector2d& q, double fixed_z) -> vector3d {return {q.x(), q.y(), fixed_z};};
}
// 退化情况
if (n < 3) {
for (uint32_t i = 0; i < n; ++i) {
out_points.push_back(profile.points[i]);
// 只有前n-1个顶点需要凸度(开放折线)
if (i < n - 1) { out_bulges.push_back(profile.bulges ? profile.bulges[i] : 0.0); }
out_points.push_back(desc.points[i]);
if (i < n - 1) out_bulges.push_back(desc.bulges ? desc.bulges[i] : 0.0);
}
return;
}
std::vector<Eigen::Vector2d> pts(n);
std::vector<double> bulges(n);
// fixed_coord:axis→y分量(恒=0),profile→z分量(恒=0)
std::vector<double> fixed_coords(n);
for (uint32_t i = 0; i < n; ++i) {
pts[i] = {profile.points[i].x, profile.points[i].y};
bulges[i] = profile.bulges ? profile.bulges[i] : 0.0;
pts[i] = to_2d(desc.points[i]);
bulges[i] = desc.bulges ? desc.bulges[i] : 0.0;
fixed_coords[i] = cfg.is_axis ? desc.points[i].y // axis:保留 y(=0)
: desc.points[i].z; // profile:保留 z(=0)
}
// ── 逐顶点计算圆角 ────────────────────────────────────────────────────
// 闭合:处理全部 n 个顶点(首尾环形相连)
// 不闭合:仅处理内部顶点 [1, n-2](首尾为端点,无入/出射配对)
// 计算每个顶点的圆角
std::vector<Corner> corners(n);
if (closed) {
for (uint32_t i = 0; i < n; ++i) {
const uint32_t prev = (i + n - 1) % n;
const uint32_t next = (i + 1) % n;
corners[i] = compute_corner(pts, bulges, i, prev, next, cfg);
}
for (uint32_t i = 0; i < n; ++i) corners[i] = compute_corner(pts, bulges, i, (i + n - 1) % n, (i + 1) % n, cfg);
} else {
// corners[0] 和 corners[n-1] 保持默认 inactive
for (uint32_t i = 1; i <= n - 2; ++i) { corners[i] = compute_corner(pts, bulges, i, i - 1, i + 1, cfg); }
for (uint32_t i = 1; i <= n - 2; ++i) corners[i] = compute_corner(pts, bulges, i, i - 1, i + 1, cfg);
}
auto push_pt = [&](const Eigen::Vector2d& p2d, double fixed, double bulge) {
out_points.push_back(to_3d(p2d, fixed));
out_bulges.push_back(bulge);
};
out_points.reserve(n * 2);
out_bulges.reserve(n * 2);
if (closed) {
// 闭合:环形迭代,输出隐式首尾相连
//
// 对每段 i(pts[i]→pts[next],bulge=bulges[i]):
// 1.段起点:corners[i].active ? trim_out[i] : pts[i]
// 2.若 corners[next].active:插入 trim_in[next](附 fillet_bulge[next])
// 下一迭代自然从 trim_out[next] 开始
for (uint32_t i = 0; i < n; ++i) {
const uint32_t next = (i + 1) % n;
const double z_i = profile.points[i].z;
const double z_nxt = profile.points[next].z;
const Eigen::Vector2d& seg_start = corners[i].active ? corners[i].trim_out : pts[i];
push_point(out_points, out_bulges, seg_start, z_i, bulges[i]);
if (corners[next].active) {
push_point(out_points, out_bulges, corners[next].trim_in, z_nxt, corners[next].fillet_bulge);
}
const auto& seg_start = corners[i].active ? corners[i].trim_out : pts[i];
push_pt(seg_start, fixed_coords[i], bulges[i]);
if (corners[next].active) push_pt(corners[next].trim_in, fixed_coords[next], corners[next].fillet_bulge);
}
} else {
// 不闭合:线性迭代,明确保留首尾端点
//
// 对每段 i(0..n-2),输出段起点;若 next 顶点有圆角(且非末点),
// 则额外插入 trim_in[next](附 fillet_bulge[next])作为本段实际终点,
// 下一迭代从 trim_out[next] 开始。
for (uint32_t i = 0; i < n - 1; ++i) {
const uint32_t next = i + 1;
const double z_i = profile.points[i].z;
const double z_nxt = profile.points[next].z;
// 段起点:
// i==0 → 始终为 pts[0](端点,没有圆角)
// corners[i].active → trim_out[i](由上一迭代的圆角偏移得到)
// 否则 → pts[i]
const Eigen::Vector2d& seg_start = (i == 0) ? pts[0] : corners[i].active ? corners[i].trim_out : pts[i];
// 若 next 有圆角(且 next 不是末点,末点无圆角):
// 本段实际终点为 trim_in[next],之后插入圆弧,
// 下一迭代从 trim_out[next] 开始
if (next < n - 1 && corners[next].active) {
push_point(out_points, out_bulges, seg_start, z_i, bulges[i]);
push_point(out_points, out_bulges, corners[next].trim_in, z_nxt, corners[next].fillet_bulge);
} else {
// next 无圆角(或 next 是末点):正常输出段起点
push_point(out_points, out_bulges, seg_start, z_i, bulges[i]);
const auto& seg_start = (i == 0) ? pts[0] : corners[i].active ? corners[i].trim_out : pts[i];
push_pt(seg_start, fixed_coords[i], bulges[i]);
if (next < n - 1 && corners[next].active)
push_pt(corners[next].trim_in, fixed_coords[next], corners[next].fillet_bulge);
}
out_points.push_back(desc.points[n - 1]); // 末点原样保留
}
// 末点:始终为 pts[n-1](端点,没有圆角)
out_points.push_back(profile.points[n - 1]);
//out_bulges.push_back(0.0);
}
if (closed) {
if (closed)
assert(out_points.size() == out_bulges.size());
} else {
assert(out_bulges.size() + 1 == out_points.size()); // 开放折线:凸度数量 = 点数 - 1
}
else
assert(out_bulges.size() + 1 == out_points.size());
}
} // namespace internal

6
primitive_process/src/subface/simple/extrude_helixline_side_face.cpp

@ -210,12 +210,6 @@ std::tuple<Eigen::Vector4d, double, double> extrude_helixline_side_function_impl
Eigen::Vector3d axis_normal = face->get_axis_geom().calculate_normal(t_axis);
Eigen::Vector3d B = axis_normal.cross(axis_tangent).normalized();
//Eigen::Transform<double, 3, Eigen::Isometry> TBN;
//TBN.matrix().col(0).head<3>() = B;
//TBN.matrix().col(1).head<3>() = axis_normal;
//TBN.matrix().col(2).head<3>() = axis_tangent;
//TBN.matrix().col(3).head<3>() = axis_point;
//TBN.matrix()(3, 3) = 1.0;
auto TBN = get_local_TBN_helixline(face->get_axis_geom(), axis_point, t_axis);
// ==================== 处理 Profile 参数 ====================

Loading…
Cancel
Save