Files
茂之钳 9b89fc179f
CI / Build & Test (push) Failing after 34s
CI / Release Build (push) Failing after 27s
Build & Test / build-and-test (push) Has been cancelled
Build & Test / python-bindings (push) Has been cancelled
feat: N-side filling + G3 continuity
2026-07-24 16:16:18 +00:00

255 lines
9.2 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include "vde/curves/nurbs_surface.h"
#include "vde/curves/nurbs_curve.h"
#include "vde/core/point.h"
#include <utility>
#include <vector>
namespace vde::curves {
using core::Point3D;
using core::Vector3D;
/**
* @brief NURBS 曲面等距偏移
*
* 基于 Piegl & Tiller 近似方法:在每个控制点的 Greville 横坐标处
* 计算曲面法向,将控制点沿法向平移 distance。
*
* @param surf 输入 NURBS 曲面
* @param distance 偏移距离(正值 = 沿法向外,负值 = 向内)
* @return 偏移后的 NURBS 曲面(近似,阶次与原曲面相同)
*
* @note 这是几何近似,非精确偏移。对于大变曲率曲面,增大控制点数量
* 可提高精度。精确偏移需要更高阶曲面或细分方法。
* @note 偏移可能导致自交(distance 超过曲面局部曲率半径时)
* @see trim_surface blend_surfaces
* @ingroup curves
*/
[[nodiscard]] NurbsSurface offset_surface(const NurbsSurface& surf, double distance);
/**
* @brief NURBS 曲面参数域裁剪
*
* 将原始定义域 [u_min,u_max]×[v_min,v_max] 通过节点重参数化
* 映射到 [0,1]×[0,1],不改变控制点和权重——仅缩放平移节点向量,
* 曲面几何保持不变。
*
* @param surf 输入曲面
* @param u_min,u_max 裁剪后的 u 参数范围(必须在原 domain 内)
* @param v_min,v_max 裁剪后的 v 参数范围(必须在原 domain 内)
* @return 裁剪后的 NURBS 曲面
*
* @note 裁剪是"软裁剪"——几何不变,仅改变参数化。如需"硬裁剪"
* (沿等参线切除曲面边缘),需结合曲面细分。
* @code{.cpp}
* auto trimmed = trim_surface(surf, 0.2, 0.8, 0.1, 0.9);
* // trimmed 的参数域为 [0,1]×[0,1],但几何仅对应原曲面的子区域
* @endcode
* @ingroup curves
*/
[[nodiscard]] NurbsSurface trim_surface(const NurbsSurface& surf,
double u_min, double u_max,
double v_min, double v_max);
/**
* @brief 两 NURBS 曲面沿边界边的过渡面
*
* 提取两个曲面的指定边界曲线,各沿法向向内偏移 blend_radius 后,
* 在两偏移曲线之间创建直纹面作为过渡。
*
* @param surf_a 第一个曲面
* @param surf_b 第二个曲面
* @param edge_a surf_a 的边界边索引(0=u_min, 1=u_max, 2=v_min, 3=v_max
* @param edge_b surf_b 的边界边索引(0=u_min, 1=u_max, 2=v_min, 3=v_max
* @param blend_radius 过渡半径
* @return 过渡 NURBS 曲面(在偏移边界曲线间的直纹面)
*
* @note 过渡面与原始曲面在边界处为 C⁰ 连续(非切线连续)
* @code{.cpp}
* // surf_a 的 u_max 边过渡到 surf_b 的 u_min 边
* auto blend = blend_surfaces(surf_a, surf_b,
* 1, 0, // edge indices: umax → umin
* 0.5); // blend radius
* @endcode
* @see ruled_surface
* @ingroup curves
*/
[[nodiscard]] NurbsSurface blend_surfaces(const NurbsSurface& surf_a,
const NurbsSurface& surf_b,
int edge_a, int edge_b,
double blend_radius);
/**
* @brief 两 NURBS 曲线间的直纹面
*
* 在两条曲线之间线性插值生成曲面:
* S(u,v) = (1-v)·C_a(u) + v·C_b(u)
* 纵向保持输入曲线的阶次,直纹方向为线性(degree=1)。
*
* @param curve_a 第一条曲线(v=0 边界)
* @param curve_b 第二条曲线(v=1 边界)
* @return 直纹 NURBS 曲面
*
* @note 两条曲线需有兼容的阶次和节点结构(内部执行升阶和节点精化)
* @code{.cpp}
* auto ruled = ruled_surface(profile_bottom, profile_top);
* @endcode
* @see coons_patch blend_surfaces
* @ingroup curves
*/
[[nodiscard]] NurbsSurface ruled_surface(const NurbsCurve& curve_a,
const NurbsCurve& curve_b);
/**
* @brief 由四条边界曲线创建 Coons 曲面
*
* 双线性混合:
* S(u,v) = (1-u)·C_{v0}(v) + u·C_{v1}(v)
* + (1-v)·C_{u0}(u) + v·C_{u1}(u)
* - 角点修正项
*
* 四条曲线须围成闭合环且有兼容的阶次/节点结构。
*
* @param curve_u0 v=0 处边界(沿 u 方向)
* @param curve_u1 v=1 处边界(沿 u 方向)
* @param curve_v0 u=0 处边界(沿 v 方向)
* @param curve_v1 u=1 处边界(沿 v 方向)
* @return Coons 曲面
*
* @note 仅保证边界插值,不保证内部形状与设计意图一致
* @code{.cpp}
* auto patch = coons_patch(bottom, top, left, right);
* @endcode
* @see ruled_surface
* @ingroup curves
*/
[[nodiscard]] NurbsSurface coons_patch(const NurbsCurve& curve_u0,
const NurbsCurve& curve_u1,
const NurbsCurve& curve_v0,
const NurbsCurve& curve_v1);
/**
* @brief 沿方向向量拉伸 NURBS 曲线为曲面
*
* 创建阶次 (d)×1 的 NURBS 曲面(d = 曲线阶次)。
* 第一排控制点 = 曲线控制点,最后一排 = 偏移后的控制点。
*
* @param curve 截面曲线
* @param direction 拉伸方向(内部归一化)
* @param length 拉伸长度
* @return 拉伸 NURBS 曲面
*
* @code{.cpp}
* auto surface = extrude_curve(profile, {0, 0, 1}, 10.0);
* // 沿 Z 轴拉伸 10 单位
* @endcode
* @ingroup curves
*/
[[nodiscard]] NurbsSurface extrude_curve(const NurbsCurve& curve,
const Vector3D& direction,
double length);
/**
* @brief 提取 NURBS 曲面的等参边界曲线
*
* 沿曲面的 u/v 参数极值提取边界 NURBS 曲线。
*
* @param surf 输入曲面
* @param edge 边界索引:0=u_min, 1=u_max, 2=v_min, 3=v_max
* @return 指定边界上的 NURBS 曲线
*
* @note 边界曲线继承原曲面该方向的阶次和节点向量
* @code{.cpp}
* auto umin_curve = extract_boundary_curve(surf, 0);
* auto vmax_curve = extract_boundary_curve(surf, 3);
* @endcode
* @ingroup curves
*/
[[nodiscard]] NurbsCurve extract_boundary_curve(const NurbsSurface& surf, int edge);
/**
* @brief 曲面点的曲率(平均曲率与高斯曲率)
*
* 基于第一基本形式 (E,F,G) 和第二基本形式 (L,M,N) 的微分几何定义:
* - 平均曲率 H = (EN - 2FM + GL) / (2(EG - F²))
* - 高斯曲率 K = (LN - M²) / (EG - F²)
*
* @param surf 输入曲面
* @param u u 参数
* @param v v 参数
* @return (mean_curvature, gaussian_curvature)
*
* @note H > 0 表示曲面沿法向弯曲,K > 0 为椭圆点,K < 0 为双曲点
* @code{.cpp}
* auto [H, K] = surface_curvature(surf, 0.5, 0.5);
* @endcode
* @see is_g2_continuous
* @ingroup curves
*/
[[nodiscard]] std::pair<double, double> surface_curvature(
const NurbsSurface& surf, double u, double v);
/**
* @brief 检查两曲面沿共享边界的 G²(曲率)连续性
*
* 沿 surf_a 的指定边与 surf_b 的对应边采样多个点,
* 依次检查位置连续(G⁰)、切平面连续(G¹)和曲率连续(G²)。
*
* @param surf_a 第一个曲面
* @param surf_b 第二个曲面
* @param edge surf_a 的边索引(0=umin, 1=umax, 2=vmin, 3=vmax
* @param samples 沿边界的采样点数(默认 10)
* @return 所有采样点均满足 G² 连续时返回 true
*
* @note G² 连续性要求:位置、切平面和曲率在边界两侧一致
* @note 默认容差:位置 1e-6,法向量 1e-3,曲率相对误差 1e-3
* @code{.cpp}
* bool is_smooth = is_g2_continuous(surf_a, surf_b, 1);
* // 检查 surf_a 的 umax 边是否与 surf_b 的 umin 边 G² 连续
* @endcode
* @see surface_curvature extend_surface
* @ingroup curves
*/
[[nodiscard]] bool is_g2_continuous(const NurbsSurface& surf_a,
const NurbsSurface& surf_b, int edge, int samples = 10);
/**
* @brief 沿边界边延伸 NURBS 曲面
*
* 在指定边方向上追加一行(或一列)控制点,
* 新控制点由边界控制点沿切向平移 distance 得到。
* 节点向量相应扩展,延伸区间的参数长度为 distance。
*
* @param surf 输入曲面
* @param edge 延伸起始边(0=umin, 1=umax, 2=vmin, 3=vmax
* @param length 延伸长度(参数空间)
* @return 延伸后的 NURBS 曲面
*
* @note 延伸仅沿切向线性外推,不保证与原曲面 C² 连续
* @note 大延伸长度可能引起自交或形状失真
* @code{.cpp}
* auto extended = extend_surface(surf, 1, 0.5); // 沿 umax 延伸 0.5
* @endcode
* @see is_g2_continuous
* @ingroup curves
*/
[[nodiscard]] NurbsSurface extend_surface(const NurbsSurface& surf,
int edge, double length);
/// Fill an N-sided hole with a smooth surface
/// @param boundary_curves N boundary curves forming a closed loop
/// @param continuity Desired continuity (1=G1 tangent, 2=G2 curvature)
/// @return Filling NURBS surface
[[nodiscard]] NurbsSurface fill_n_sided(const std::vector<NurbsCurve>& boundary_curves,
int continuity = 1);
/// Check G3 (torsion) continuity between two surfaces along a shared boundary
[[nodiscard]] bool is_g3_continuous(const NurbsSurface& surf_a,
const NurbsSurface& surf_b, int edge, int samples = 10);
/// Compute torsion of a surface at a point
[[nodiscard]] double surface_torsion(const NurbsSurface& surf, double u, double v);
} // namespace vde::curves