Browse Source

fix: circle_cpm value constraint blind spot and pmc adjustment

main
linchforever 1 day ago
parent
commit
b361128f45
  1. 105
      primitive_process/src/subface/geometry/geometry_data.cpp

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

@ -115,14 +115,8 @@ void polyline_geometry_data::build_internal(const polyline_descriptor_t&
if (on_arc) {
const Eigen::Vector2d ext_pt = c + r * Eigen::Vector2d(std::cos(ext_angle), std::sin(ext_angle));
aabb->extend(ext_pt);
std::cout << " [ARC_AABB] adding extremum at " << (ext_angle * 180.0 / pi) << "° → (" << ext_pt[0] << ","
<< ext_pt[1] << ")\n";
}
}
// 调试输出:AABB 当前状态
std::cout << " [ARC_AABB] after arc extrema: AABB min=(" << aabb->min().x() << "," << aabb->min().y() << ") max=("
<< aabb->max().x() << "," << aabb->max().y() << ")\n";
}
});
}
@ -395,16 +389,13 @@ void polyline_geometry_data::build_as_axis(polyline_descriptor_t&&
const auto local_y = base_vec2.dot(p_vec);
double phi = std::atan2(local_y, local_x);
if (theta > pi + 1e-9) {
if (phi < -EPSILON) { phi += two_pi; }
if (phi < 0.0) { phi += two_pi; } // 优弧:折叠到正值范围
} else {
// 劣弧:phi 只应在 [0, theta],负值直接视为 gap
if (phi < -EPSILON) {
phi = -1.0; // 强制触发端点回退
}
if (phi < 0.0) { phi = -1.0; } // 劣弧:强制触发端点回退
}
// 弧段越界时返回较近端点
if (phi < -1e-9 || phi > theta + 1e-9) {
if (phi < 0.0 || phi > theta + 1e-9) {
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();
@ -451,77 +442,61 @@ void polyline_geometry_data::build_as_axis(polyline_descriptor_t&&
// Convention: return true = OUTSIDE (SDF > 0), false = INSIDE (SDF <= 0)
const Eigen::Vector2d vec = p - closest_param.point.topRows<2>();
if (closest_param.is_peak_value) {
return vec.dot(this->calculate_normal(closest_param.t)) < 0;
}
if (closest_param.is_peak_value) { return vec.dot(this->calculate_normal(closest_param.t)) < 0; }
constexpr double kChordEps = 1e-12; // 弦长退化阈值
constexpr double kCrossThresh = 1e-9; // 叉积共线阈值
constexpr double kCrossThresh = 1e-9;
constexpr double kTangEps = 1e-7;
const auto N = static_cast<uint32_t>(this->thetas.size());
auto n = static_cast<uint32_t>(std::round(closest_param.t));
const bool is_closed = (this->vertices.back() - this->vertices.front()).squaredNorm() < EPSILON;
// 对闭合曲线,顶点索引 N 等同于顶点 0
if (is_closed && n >= N) n = 0u;
// 顶点 i(0 ≤ i < N)的 2D 坐标存储在 vertices[start_indices[i]]。
// i == N 时(开放曲线末端),使用 vertices.back()。
auto get_vertex_2d = [&](uint32_t idx) -> Eigen::Vector2d {
return (idx < N) ? this->vertices[this->start_indices[idx]] : this->vertices.back();
};
const Eigen::Vector2d v_curr = get_vertex_2d(n);
Eigen::Vector2d v_next = v_curr;
{
const uint32_t n1 = n + 1;
if (n1 <= N) {
v_next = get_vertex_2d(n1);
} else if (is_closed) {
v_next = get_vertex_2d(0);
}
// else: 开放曲线 n == N,无后继,v_next 保持 = v_curr
}
Eigen::Vector2d v_prev = v_curr;
if (n > 0u) {
v_prev = get_vertex_2d(n - 1u);
} else if (is_closed && N > 1u) {
v_prev = get_vertex_2d(N - 1u);
}
// 入射切线:从段 n-1 的末端取(t = n - ε)
Eigen::Vector2d tang_in;
if (n > 0u)
tang_in = this->calculate_tangent(static_cast<double>(n) - kTangEps);
else if (is_closed && N > 1u)
tang_in = this->calculate_tangent(static_cast<double>(N) - kTangEps);
else
tang_in = this->calculate_tangent(kTangEps); // 开放曲线起点退化
// 出射切线:从段 n 的起始取(t = n + ε)
Eigen::Vector2d tang_out;
if (n < N)
tang_out = this->calculate_tangent(static_cast<double>(n) + kTangEps);
else if (is_closed)
tang_out = this->calculate_tangent(kTangEps);
else
tang_out = tang_in; // 开放曲线终点退化
const Eigen::Vector2d chord_out_raw = v_next - v_curr;
const Eigen::Vector2d chord_in_raw = v_curr - v_prev;
const double len_out = chord_out_raw.norm();
const double len_in = chord_in_raw.norm();
const double len_in = tang_in.norm();
const double len_out = tang_out.norm();
// 顶点重合,回退到弧/线法线
if (len_out < kChordEps && len_in < kChordEps) {
const double t_fallback = std::min(static_cast<double>(n) + 1e-9, static_cast<double>(N) - 1e-9);
return vec.dot(this->calculate_normal(t_fallback)) < 0;
if (len_in < 1e-12 && len_out < 1e-12) {
const double t_fb = std::min(static_cast<double>(n) + 1e-9, static_cast<double>(N) - 1e-9);
return vec.dot(this->calculate_normal(t_fb)) < 0;
}
// 归一化(单边退化时用另一边代替)
const Eigen::Vector2d chord_out = (len_out >= kChordEps) ? (chord_out_raw / len_out) : (chord_in_raw / len_in);
const Eigen::Vector2d chord_in = (len_in >= kChordEps) ? (chord_in_raw / len_in) : (chord_out_raw / len_out);
const Eigen::Vector2d t_in = (len_in >= 1e-12) ? tang_in / len_in : tang_out / len_out;
const Eigen::Vector2d t_out = (len_out >= 1e-12) ? tang_out / len_out : tang_in / len_in;
const Eigen::Vector2d n_in_chord(-chord_in.y(), chord_in.x());
const Eigen::Vector2d n_out_chord(-chord_out.y(), chord_out.x());
// CCW 轮廓内向法线 = 切线的左法线
const Eigen::Vector2d n_in(-t_in.y(), t_in.x());
const Eigen::Vector2d n_out(-t_out.y(), t_out.x());
const double dot_in = vec.dot(n_in_chord);
const double dot_out = vec.dot(n_out_chord);
const double dot_in = vec.dot(n_in);
const double dot_out = vec.dot(n_out);
const double cross = t_in.x() * t_out.y() - t_in.y() * t_out.x();
const double cross = chord_in.x() * chord_out.y() - chord_in.y() * chord_out.x();
if (cross > kCrossThresh) {
// 凸角
// 凸角:外部 = 两个外半平面的并集
return dot_in < 0.0 || dot_out < 0.0;
} else if (cross < -kCrossThresh) {
// 凹角
return dot_in < 0.0 && dot_out < 0.0;
// 反凸/凹角:外部 = 两个外半平面的交集
return dot_in < 0.0 && dot_out < 0.0;
} else {
// 平角(切向共线,光滑连接)
// 两半平面方向近似相同,取双法线加权平均
// 近共线:平滑过渡
return (dot_in + dot_out) < 0.0;
}
}

Loading…
Cancel
Save