feat(v5-M2): G2/G3 continuity + surface analysis + extension + N-side fill + advanced blend
M2.1 — G2/G3 连续性分析 (Agent #0): - surface_continuity.h/.cpp: G0/G1/G2/G3 curve/surface detection - Weingarten equation for curvature, Frénet frame, zebra stripe - surface_analysis.h/.cpp: curvature_map, deviation_analysis, curvature_comb - 24 tests (12 continuity + 12 analysis) M2.2 — 曲面延伸 + N边填充 (Agent #1): - surface_extension.h/.cpp: extend_surface(G1/G2), n_sided_fill, blend_surfaces - Coons patch generalization for N-sided holes - 16/16 tests passed in Docker container M2.3 — 高级过渡曲面 (Agent #2): - advanced_blend.h/.cpp: real implementations replacing stubs - variable_radius_blend, multi_face_blend, rolling_ball_blend, face_face_blend - Ball-rolling envelope + corner sphere filling - 15+ tests with validate() verification
This commit is contained in:
@@ -1,8 +1,126 @@
|
||||
#pragma once
|
||||
/**
|
||||
* @file advanced_blend.h
|
||||
* @brief 高级过渡曲面(Advanced Blend)操作
|
||||
*
|
||||
* 提供多种超出简单恒定半径圆角的过渡曲面算法:
|
||||
* - 沿边变半径过渡(variable_radius_blend)
|
||||
* - 多面同时过渡(multi_face_blend)
|
||||
* - 滚动球算法(rolling_ball_blend)
|
||||
* - 两面间恒定半径过渡(face_face_blend)
|
||||
*
|
||||
* ## 与 fillet/fillet_variable 的关系
|
||||
*
|
||||
* modeling.h 中的 fillet 和 fillet_variable 是面向最终用户的高层 API,
|
||||
* 本模块提供更底层的过渡曲面算法实现。两者可配合使用。
|
||||
*
|
||||
* @ingroup brep
|
||||
*/
|
||||
#include "vde/brep/brep.h"
|
||||
#include <vector>
|
||||
|
||||
namespace vde::brep {
|
||||
[[nodiscard]] BrepModel variable_radius_blend(const BrepModel& body, int edge_id, double r_start, double r_end);
|
||||
[[nodiscard]] BrepModel multi_face_blend(const BrepModel& body, const std::vector<int>& face_ids, double radius);
|
||||
[[nodiscard]] BrepModel rolling_ball_blend(const BrepModel& body, int edge_id, double radius);
|
||||
} // namespace vde::brep
|
||||
|
||||
/**
|
||||
* @brief 沿边变半径过渡
|
||||
*
|
||||
* 沿指定边的参数方向,在 r_start 和 r_end 之间线性插值半径,
|
||||
* 每段独立构建过渡曲面片段,最终拼接为完整过渡。
|
||||
*
|
||||
* 算法:
|
||||
* 1. 定位目标边及其两个邻面
|
||||
* 2. 计算两面法向量及角平分线方向
|
||||
* 3. 沿边曲线采样 N 个截面,每个截面处计算半径和切点
|
||||
* 4. 每相邻两截面间构建一张过渡曲面(NURBS quad patch)
|
||||
* 5. 重建两个邻面,切除过渡区域
|
||||
* 6. 复制未受影响的面,组装壳和体
|
||||
*
|
||||
* @param body 输入实体
|
||||
* @param edge_id 目标边索引
|
||||
* @param r_start 边起点处的过渡半径(≥ 0)
|
||||
* @param r_end 边终点处的过渡半径(≥ 0)
|
||||
* @param samples 沿边的截面采样数(默认 16)
|
||||
* @return 过渡后的新实体
|
||||
*
|
||||
* @pre edge_id 有效,r_start ≥ 0, r_end ≥ 0
|
||||
* @note samples 越大截面过渡越光滑,但面和边数增加
|
||||
*/
|
||||
[[nodiscard]] BrepModel variable_radius_blend(
|
||||
const BrepModel& body, int edge_id,
|
||||
double r_start, double r_end, int samples = 16);
|
||||
|
||||
/**
|
||||
* @brief 多面同时过渡
|
||||
*
|
||||
* 对多个面同时施加恒定半径的过渡处理。每个目标面独立向内偏移,
|
||||
* 目标面之间的交角处构造球面填充,非目标面保持不变。
|
||||
*
|
||||
* 算法:
|
||||
* 1. 对每个目标面,沿面法向量向内偏移半径距离
|
||||
* 2. 检测目标面之间的共享边,在交线处构造圆柱过渡
|
||||
* 3. 检测三面以上交角顶点,用球面贴片填充
|
||||
* 4. 复制非目标面,组装壳和体
|
||||
*
|
||||
* @param body 输入实体
|
||||
* @param face_ids 目标面索引列表
|
||||
* @param radius 过渡半径(> 0)
|
||||
* @return 过渡后的新实体
|
||||
*
|
||||
* @pre face_ids 非空,所有索引有效,radius > 0
|
||||
*/
|
||||
[[nodiscard]] BrepModel multi_face_blend(
|
||||
const BrepModel& body, const std::vector<int>& face_ids, double radius);
|
||||
|
||||
/**
|
||||
* @brief 滚动球算法过渡
|
||||
*
|
||||
* 模拟一个半径为 radius 的球体沿目标边滚动,球体的扫掠包络面即为过渡曲面。
|
||||
* 球体始终保持与边的两个邻面接触,其中心沿边的等距曲线移动。
|
||||
*
|
||||
* 算法:
|
||||
* 1. 计算滚动球中心轨迹(沿边的 offset 曲线,offset = r / cos(half_angle))
|
||||
* 2. 沿边采样球心位置
|
||||
* 3. 每个球心位置计算球与两面的切点
|
||||
* 4. 相邻截面间构建过渡曲面 patch(近似球体扫掠包络)
|
||||
* 5. 重建邻面、复制非影响面、组装壳和体
|
||||
*
|
||||
* 对直边退化为圆柱过渡,对曲边产生自然的变曲率过渡。
|
||||
*
|
||||
* @param body 输入实体
|
||||
* @param edge_id 目标边索引
|
||||
* @param radius 球体半径(> 0)
|
||||
* @param samples 沿边的球心采样数(默认 20)
|
||||
* @return 过渡后的新实体
|
||||
*
|
||||
* @pre edge_id 有效,radius > 0
|
||||
*/
|
||||
[[nodiscard]] BrepModel rolling_ball_blend(
|
||||
const BrepModel& body, int edge_id,
|
||||
double radius, int samples = 20);
|
||||
|
||||
/**
|
||||
* @brief 两面间恒定半径过渡
|
||||
*
|
||||
* 在两个任意面之间构造恒定半径的过渡曲面。与单边过渡不同,
|
||||
* 此函数处理两个面之间的整个共享或邻近区域。
|
||||
*
|
||||
* 算法:
|
||||
* 1. 找到两面之间的共享边,或确定两面的邻近区域
|
||||
* 2. 沿共享边界计算过渡曲面(恒定半径圆柱面)
|
||||
* 3. 切掉两面在过渡区域的部分
|
||||
* 4. 插入过渡曲面,组装壳和体
|
||||
*
|
||||
* @param body 输入实体
|
||||
* @param face_a 第一个面索引
|
||||
* @param face_b 第二个面索引
|
||||
* @param radius 过渡半径(> 0)
|
||||
* @param samples 沿边界的截面采样数(默认 16)
|
||||
* @return 过渡后的新实体
|
||||
*
|
||||
* @pre face_a 和 face_b 有效,radius > 0
|
||||
*/
|
||||
[[nodiscard]] BrepModel face_face_blend(
|
||||
const BrepModel& body, int face_a, int face_b,
|
||||
double radius, int samples = 16);
|
||||
|
||||
} // namespace vde::brep
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
#pragma once
|
||||
/**
|
||||
* @file surface_analysis.h
|
||||
* @brief 曲面分析工具集 — 曲率映射、斑马纹、曲率梳、偏差分析、拔模角
|
||||
*
|
||||
* 提供 CAD 级曲面质量分析功能:
|
||||
* - 高斯/平均/主曲率网格
|
||||
* - 斑马纹反射模拟
|
||||
* - 曲率梳可视化数据
|
||||
* - 曲面间偏差分析
|
||||
* - 拔模角计算(增强现有实现)
|
||||
*
|
||||
* @ingroup curves
|
||||
*/
|
||||
|
||||
#include "vde/curves/nurbs_curve.h"
|
||||
#include "vde/curves/nurbs_surface.h"
|
||||
#include "vde/core/point.h"
|
||||
#include "vde/brep/brep.h"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
|
||||
namespace vde::curves {
|
||||
|
||||
using core::Point3D;
|
||||
using core::Vector3D;
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Curvature Map Types
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 单点的曲率数据
|
||||
struct CurvaturePoint {
|
||||
double gaussian = 0.0; ///< 高斯曲率 K = κ₁·κ₂
|
||||
double mean = 0.0; ///< 平均曲率 H = (κ₁+κ₂)/2
|
||||
double k1 = 0.0; ///< 最大主曲率 κ₁
|
||||
double k2 = 0.0; ///< 最小主曲率 κ₂
|
||||
Vector3D d1; ///< 最大主方向
|
||||
Vector3D d2; ///< 最小主方向
|
||||
};
|
||||
|
||||
/// 曲率网格(res_u+1 × res_v+1)
|
||||
struct CurvatureMap {
|
||||
int res_u, res_v; ///< 网格分辨率
|
||||
std::vector<std::vector<CurvaturePoint>> grid; ///< grid[i][j] 对应 (u_i, v_j)
|
||||
|
||||
/// 高斯曲率极值
|
||||
double min_gaussian = std::numeric_limits<double>::max();
|
||||
double max_gaussian = -std::numeric_limits<double>::max();
|
||||
|
||||
/// 平均曲率极值
|
||||
double min_mean = std::numeric_limits<double>::max();
|
||||
double max_mean = -std::numeric_limits<double>::max();
|
||||
|
||||
/// 是否为可展曲面(高斯曲率 ≈ 0)
|
||||
[[nodiscard]] bool is_developable(double tol = 1e-9) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 计算 NURBS 曲面的曲率映射
|
||||
*
|
||||
* 在参数域均匀采样,计算每个采样点的高斯曲率、平均曲率、
|
||||
* 主曲率及主方向。
|
||||
*
|
||||
* @param surf NURBS 曲面
|
||||
* @param res_u u 方向分辨率(单元格数)
|
||||
* @param res_v v 方向分辨率(单元格数)
|
||||
* @return CurvatureMap
|
||||
*/
|
||||
[[nodiscard]] CurvatureMap curvature_map(
|
||||
const NurbsSurface& surf,
|
||||
int res_u, int res_v);
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Zebra Stripe
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 斑马纹反射数据
|
||||
struct ZebraStripeResult {
|
||||
int res_u, res_v; ///< 网格分辨率
|
||||
std::vector<std::vector<double>> intensity; ///< intensity[i][j] ∈ [0,1]
|
||||
Vector3D light_direction; ///< 光照方向(归一化)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 计算斑马纹反射数据(等照度线模拟)
|
||||
*
|
||||
* 模拟等间距平行光源在曲面上的反射效果,用于检测曲面光顺性。
|
||||
* 斑马纹的密度和均匀度反映曲面的曲率变化。
|
||||
*
|
||||
* @param surf NURBS 曲面
|
||||
* @param light_dir 光照方向(自动归一化)
|
||||
* @param res_u u 方向分辨率
|
||||
* @param res_v v 方向分辨率
|
||||
* @return 反射强度网格
|
||||
*/
|
||||
[[nodiscard]] ZebraStripeResult zebra_stripe(
|
||||
const NurbsSurface& surf,
|
||||
const Vector3D& light_dir,
|
||||
int res_u, int res_v);
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Curvature Comb
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 曲率梳数据点
|
||||
struct CurvatureCombPoint {
|
||||
Point3D curve_point; ///< 曲线上的点
|
||||
Vector3D curvature_vec; ///< 曲率向量(方向=主法线,长度∝曲率)
|
||||
double curvature; ///< 曲率大小
|
||||
};
|
||||
|
||||
/// 曲率梳完整数据
|
||||
struct CurvatureComb {
|
||||
std::vector<CurvatureCombPoint> points;
|
||||
double min_curvature = std::numeric_limits<double>::max();
|
||||
double max_curvature = -std::numeric_limits<double>::max();
|
||||
double scale = 1.0; ///< 缩放因子
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 计算曲线曲率梳数据
|
||||
*
|
||||
* 在曲线上均匀采样,计算各点的曲率向量。
|
||||
* 曲率梳将曲率大小可视化为从曲线向外延伸的线段长度。
|
||||
*
|
||||
* @param curve NURBS 曲线
|
||||
* @param res 采样分辨率(点数)
|
||||
* @param scale 曲率缩放因子(默认自动适配)
|
||||
* @return 曲率梳数据
|
||||
*/
|
||||
[[nodiscard]] CurvatureComb curvature_comb(
|
||||
const NurbsCurve& curve,
|
||||
int res,
|
||||
double scale = 0.0);
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Deviation Analysis
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 偏差分析结果
|
||||
struct DeviationResult {
|
||||
double max_positive = 0.0; ///< 最大正偏差(surf_b 在 surf_a 外侧)
|
||||
double max_negative = 0.0; ///< 最大负偏差(surf_b 在 surf_a 内侧)
|
||||
double rms = 0.0; ///< 均方根偏差
|
||||
double mean_absolute = 0.0; ///< 平均绝对偏差
|
||||
size_t sample_count = 0; ///< 采样点数量
|
||||
std::vector<double> deviations; ///< 各采样点的有符号偏差
|
||||
std::vector<Point3D> sample_points_a; ///< surf_a 上的采样点
|
||||
std::vector<Point3D> sample_points_b; ///< surf_b 上对应的最近点
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 计算两曲面的偏差分析
|
||||
*
|
||||
* 在 surf_a 参数域均匀采样,对每个采样点寻找 surf_b 上的最近点,
|
||||
* 沿 surf_a 法线方向计算有符号偏差。
|
||||
*
|
||||
* @param surf_a 基准曲面
|
||||
* @param surf_b 对比曲面
|
||||
* @param samples 采样点数量(总点数 = samples×samples)
|
||||
* @return 偏差分析结果
|
||||
*/
|
||||
[[nodiscard]] DeviationResult deviation_analysis(
|
||||
const NurbsSurface& surf_a,
|
||||
const NurbsSurface& surf_b,
|
||||
int samples);
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Draft Face Angle (Enhanced)
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* @brief 计算 NURBS 曲面上指定参数点的拔模角
|
||||
*
|
||||
* 拔模角 = angle between surface normal and pull direction minus 90°
|
||||
* 正值表示面沿拔模方向向外张开。
|
||||
*
|
||||
* @param surf NURBS 曲面
|
||||
* @param u u 参数
|
||||
* @param v v 参数
|
||||
* @param pull_dir 拔模方向(自动归一化)
|
||||
* @return 拔模角(弧度)
|
||||
*/
|
||||
[[nodiscard]] double draft_face_angle(
|
||||
const NurbsSurface& surf,
|
||||
double u, double v,
|
||||
const Vector3D& pull_dir);
|
||||
|
||||
/**
|
||||
* @brief 计算 B-Rep 面的拔模角(增强版)
|
||||
*
|
||||
* 在面的参数域中采样多个点,返回面积加权平均拔模角。
|
||||
*
|
||||
* @param body B-Rep 模型
|
||||
* @param face_id 面 ID
|
||||
* @param pull_dir 拔模方向
|
||||
* @param samples 每方向采样点数(默认 10)
|
||||
* @return 面积加权平均拔模角(弧度),若面无效则返回 0
|
||||
*/
|
||||
[[nodiscard]] double draft_face_angle(
|
||||
const brep::BrepModel& body,
|
||||
int face_id,
|
||||
const Vector3D& pull_dir,
|
||||
int samples = 10);
|
||||
|
||||
/**
|
||||
* @brief 计算 B-Rep 面的拔模角分布
|
||||
*
|
||||
* 返回面上多个采样点的拔模角数据。
|
||||
*/
|
||||
struct DraftAngleDistribution {
|
||||
double min_angle, max_angle; ///< 拔模角范围
|
||||
double mean_angle; ///< 平均拔模角
|
||||
double area_weighted_angle; ///< 面积加权平均
|
||||
std::vector<double> sample_angles; ///< 各采样点拔模角
|
||||
std::vector<std::pair<double,double>> sample_params; ///< 对应参数 (u,v)
|
||||
};
|
||||
|
||||
[[nodiscard]] DraftAngleDistribution draft_face_angle_distribution(
|
||||
const brep::BrepModel& body,
|
||||
int face_id,
|
||||
const Vector3D& pull_dir,
|
||||
int samples = 15);
|
||||
|
||||
} // namespace vde::curves
|
||||
@@ -0,0 +1,155 @@
|
||||
#pragma once
|
||||
/**
|
||||
* @file surface_continuity.h
|
||||
* @brief 曲面连续性分析 — G0/G1/G2/G3 连续性检测
|
||||
*
|
||||
* 提供曲线间和曲面间沿公共边的连续性分类。
|
||||
*
|
||||
* ### 连续性等级
|
||||
*
|
||||
* | 等级 | 条件 |
|
||||
* |------|------|
|
||||
* | G0 | 位置连续:两端点重合 |
|
||||
* | G1 | 切向连续:一阶导数共线(方向一致) |
|
||||
* | G2 | 曲率连续:曲率大小和方向匹配 |
|
||||
* | G3 | 曲率变化率连续:曲率的变化率匹配 |
|
||||
*
|
||||
* @ingroup curves
|
||||
*/
|
||||
|
||||
#include "vde/curves/nurbs_curve.h"
|
||||
#include "vde/curves/nurbs_surface.h"
|
||||
#include "vde/core/point.h"
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace vde::curves {
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Continuity Level Enum
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/// 连续性等级
|
||||
enum class ContinuityLevel {
|
||||
None, ///< 不连续(甚至不满足 G0)
|
||||
G0, ///< 位置连续
|
||||
G1, ///< 切向连续
|
||||
G2, ///< 曲率连续
|
||||
G3, ///< 曲率变化率连续
|
||||
};
|
||||
|
||||
/// 将 ContinuityLevel 转为可读字符串
|
||||
[[nodiscard]] const char* to_string(ContinuityLevel level);
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Curve Continuity
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* @brief 分析两条 NURBS 曲线在公共参数点的连续性
|
||||
*
|
||||
* 在给定参数点计算两曲线的位置、一阶、二阶、三阶导数,
|
||||
* 按 G0→G1→G2→G3 逐级判定。
|
||||
*
|
||||
* @param curve_a 第一条 NURBS 曲线
|
||||
* @param t_a curve_a 上公共点的参数值
|
||||
* @param curve_b 第二条 NURBS 曲线
|
||||
* @param t_b curve_b 上公共点的参数值
|
||||
* @param tol 位置容差(默认 1e-6)
|
||||
* @return 满足的最高连续性等级
|
||||
*
|
||||
* @note G1 要求一阶导数共线(方向相同),G2 要求曲率向量一致,
|
||||
* G3 要求曲率变化率一致。判定是累积的:G3 自动满足 G2/G1/G0。
|
||||
*/
|
||||
[[nodiscard]] ContinuityLevel continuity_type(
|
||||
const NurbsCurve& curve_a, double t_a,
|
||||
const NurbsCurve& curve_b, double t_b,
|
||||
double tol = 1e-6);
|
||||
|
||||
/**
|
||||
* @brief 重载:在两条曲线端点处检测连续性
|
||||
*
|
||||
* 自动探测 curve_a 和 curve_b 各两个端点,检查是否有重合端点对,
|
||||
* 然后调用上述函数分析该连接点的连续性等级。
|
||||
*
|
||||
* @param curve_a 第一条曲线
|
||||
* @param curve_b 第二条曲线
|
||||
* @param tol 位置容差
|
||||
* @return 若存在重合端点则返回连续性等级,否则返回 ContinuityLevel::None
|
||||
*/
|
||||
[[nodiscard]] ContinuityLevel continuity_type(
|
||||
const NurbsCurve& curve_a,
|
||||
const NurbsCurve& curve_b,
|
||||
double tol = 1e-6);
|
||||
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
// Surface Continuity
|
||||
// ═══════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* @brief 沿公共等参边分析两张 NURBS 曲面的连续性
|
||||
*
|
||||
* 在沿公共边的采样点处评估曲面连续性,返回最弱点等级。
|
||||
* 例如 surf_a 的 u=u_max 边与 surf_b 的 u=u_min 边相邻。
|
||||
*
|
||||
* @param surf_a 第一张曲面
|
||||
* @param surf_b 第二张曲面
|
||||
* @param edge_param_range_a 公共边在 surf_a 上的参数范围 {{u, v_start}, {u, v_end}}
|
||||
* @param edge_param_range_b 公共边在 surf_b 上的参数范围 {{u, v_start}, {u, v_end}}
|
||||
* @param samples 沿边的采样点数量(默认 20)
|
||||
* @param tol 位置容差(默认 1e-6)
|
||||
* @return 所有采样点中的最低连续性等级
|
||||
*
|
||||
* @note 若曲面在采样点间连续但曲面方向(法线)相反,
|
||||
* 仍判定为 G0(因为 G1 要求一阶导数方向一致)。
|
||||
*/
|
||||
[[nodiscard]] ContinuityLevel surface_continuity(
|
||||
const NurbsSurface& surf_a,
|
||||
const NurbsSurface& surf_b,
|
||||
std::pair<std::pair<double, double>, std::pair<double, double>> edge_param_range_a,
|
||||
std::pair<std::pair<double, double>, std::pair<double, double>> edge_param_range_b,
|
||||
int samples = 20,
|
||||
double tol = 1e-6);
|
||||
|
||||
/**
|
||||
* @brief 沿公共边自动检测并分析两张曲面连续性
|
||||
*
|
||||
* 自动检测 surf_a 和 surf_b 的公共边(通过比较四条等参边界),
|
||||
* 然后调用 surface_continuity 分析。
|
||||
*
|
||||
* @param surf_a 第一张曲面
|
||||
* @param surf_b 第二张曲面
|
||||
* @param samples 采样点数量
|
||||
* @param tol 位置容差
|
||||
* @return 所有公共边中的最低连续性等级(若无公共边则返回 None)
|
||||
*/
|
||||
[[nodiscard]] ContinuityLevel surface_continuity(
|
||||
const NurbsSurface& surf_a,
|
||||
const NurbsSurface& surf_b,
|
||||
int samples = 20,
|
||||
double tol = 1e-6);
|
||||
|
||||
/**
|
||||
* @brief 曲面间连续性详细报告
|
||||
*
|
||||
* 返回每个采样点的连续性等级向量,便于诊断。
|
||||
*/
|
||||
struct SurfaceContinuityReport {
|
||||
ContinuityLevel worst; ///< 最弱等级
|
||||
ContinuityLevel best; ///< 最佳等级
|
||||
double g1_ratio; ///< G1 通过率 (0~1)
|
||||
double g2_ratio; ///< G2 通过率 (0~1)
|
||||
std::vector<ContinuityLevel> per_sample; ///< 各采样点等级
|
||||
std::vector<double> position_errors; ///< 各采样点位置误差
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 获取曲面连续性详细报告
|
||||
*/
|
||||
[[nodiscard]] SurfaceContinuityReport surface_continuity_report(
|
||||
const NurbsSurface& surf_a,
|
||||
const NurbsSurface& surf_b,
|
||||
int samples = 50,
|
||||
double tol = 1e-6);
|
||||
|
||||
} // namespace vde::curves
|
||||
@@ -0,0 +1,116 @@
|
||||
#pragma once
|
||||
#include "vde/curves/nurbs_surface.h"
|
||||
#include "vde/curves/nurbs_curve.h"
|
||||
#include "vde/core/point.h"
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace vde::curves {
|
||||
|
||||
using core::Point3D;
|
||||
using core::Vector3D;
|
||||
|
||||
/**
|
||||
* @brief 连续性级别
|
||||
* @ingroup curves
|
||||
*/
|
||||
enum class Continuity {
|
||||
C0 = 0, ///< 仅位置连续
|
||||
G1 = 1, ///< 切线/切平面连续
|
||||
G2 = 2, ///< 曲率连续
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 曲面延伸
|
||||
*
|
||||
* 沿等参边界延伸曲面,支持 G1 切平面连续。
|
||||
* 对于 G2 连续,在约束方向构造 3 排控制点以保持曲率。
|
||||
*
|
||||
* @param surface 输入 NURBS 曲面
|
||||
* @param edge_id 边界边索引(0=umin, 1=umax, 2=vmin, 3=vmax)
|
||||
* @param distance 延伸距离(参数空间)
|
||||
* @param continuity 期望的连续性级别(默认 G1)
|
||||
* @return 延伸后的 NURBS 曲面
|
||||
*
|
||||
* @note G1 模式:追加 1 排控制点,沿切向延伸
|
||||
* @note G2 模式:追加 2 排控制点,第 2 排由曲率约束计算
|
||||
* @note 延伸仅沿切向线性/二次外推,不保证与原曲面精确 G2 连续
|
||||
*
|
||||
* @code{.cpp}
|
||||
* auto ext = extend_surface(surf, 1, 0.5, Continuity::G1);
|
||||
* @endcode
|
||||
* @ingroup curves
|
||||
*/
|
||||
[[nodiscard]] NurbsSurface extend_surface(const NurbsSurface& surface,
|
||||
int edge_id, double distance,
|
||||
Continuity continuity = Continuity::G1);
|
||||
|
||||
/**
|
||||
* @brief N 边孔洞填充
|
||||
*
|
||||
* 用 N 条边界曲线构造 Coons patch 泛化的填充曲面。
|
||||
* 支持三角形(N=3)、四边形(N=4)、五边形(N=5)等任意边数。
|
||||
*
|
||||
* 算法:将边界曲线映射到单位圆参数域,使用径向基函数插值
|
||||
* 构造中心点,再以双线性 Coons 方式生成内部控制点。
|
||||
*
|
||||
* @param boundary_curves N 条边界曲线,需围成闭合环(首尾相连)
|
||||
* @param continuity 期望的连续性级别(默认 G2)
|
||||
* @return 填充 NURBS 曲面
|
||||
*
|
||||
* @note G1 模式:单层中间环,线性插值
|
||||
* @note G2 模式:双层中间环,保持曲率衰减
|
||||
* @note 至少需要 3 条边界曲线
|
||||
*
|
||||
* @code{.cpp}
|
||||
* auto fill = n_sided_fill({c1, c2, c3}, Continuity::G2); // 三角形孔
|
||||
* @endcode
|
||||
* @ingroup curves
|
||||
*/
|
||||
[[nodiscard]] NurbsSurface n_sided_fill(const std::vector<NurbsCurve>& boundary_curves,
|
||||
Continuity continuity = Continuity::G2);
|
||||
|
||||
/**
|
||||
* @brief 两面间过渡曲面
|
||||
*
|
||||
* 检测两面公共边界,沿该边构造圆弧或 S 形过渡曲面。
|
||||
* 与 nurbs_operations 中的 blend_surfaces 不同,此版本自动检测公共边。
|
||||
*
|
||||
* 算法:
|
||||
* 1. 检测 surf_a 和 surf_b 的共享边界
|
||||
* 2. 沿共享边界两侧各偏移 radius 提取曲线
|
||||
* 3. 在两条偏移曲线间构造过渡曲面(直纹面或 Coons 面)
|
||||
*
|
||||
* @param surf_a 第一个曲面
|
||||
* @param surf_b 第二个曲面
|
||||
* @param radius 过渡半径
|
||||
* @return 过渡 NURBS 曲面
|
||||
*
|
||||
* @note 如果两面无公共边界,返回退化的空曲面
|
||||
* @note 过渡面在边界处与原曲面 G1 连续(等参方向)
|
||||
*
|
||||
* @code{.cpp}
|
||||
* auto blend = blend_surfaces(surf_a, surf_b, 0.3);
|
||||
* @endcode
|
||||
* @ingroup curves
|
||||
*/
|
||||
[[nodiscard]] NurbsSurface blend_surfaces(const NurbsSurface& surf_a,
|
||||
const NurbsSurface& surf_b,
|
||||
double radius);
|
||||
|
||||
/**
|
||||
* @brief 检查两曲面沿共享边界的 G1 连续性
|
||||
*
|
||||
* @param surf_a 第一个曲面
|
||||
* @param surf_b 第二个曲面
|
||||
* @param edge surf_a 的边界边索引(0=umin, 1=umax, 2=vmin, 3=vmax)
|
||||
* @param samples 沿边界的采样点数(默认 10)
|
||||
* @return 所有采样点均满足 G1 连续时返回 true
|
||||
*
|
||||
* @ingroup curves
|
||||
*/
|
||||
[[nodiscard]] bool is_g1_continuous(const NurbsSurface& surf_a,
|
||||
const NurbsSurface& surf_b,
|
||||
int edge, int samples = 10);
|
||||
|
||||
} // namespace vde::curves
|
||||
Reference in New Issue
Block a user