Files
ViewDesignEngine/include/vde/brep/modeling.h
T

295 lines
9.3 KiB
C++
Raw Normal View History

2026-07-23 07:19:13 +00:00
#pragma once
/**
* @file modeling.h
* @brief 高层 B-Rep 建模 API
*
* 提供 B-Rep 实体的创建和编辑操作,类比于 CAD 系统的特征建模功能。
*
* ## 功能概览
*
* | 类别 | 操作 |
* |----------------|---------------------------------------------|
* | 基本体 | make_box, make_cylinder, make_sphere |
* | 扫掠特征 | extrude, revolve, sweep, loft |
* | 编辑操作 | fillet, chamfer, shell |
*
* ## 使用模式
*
* 每个函数返回一个新的 BrepModel(值语义),适合链式构建:
*
* @code{.cpp}
* auto body = make_box(10, 5, 3);
* // 或者更复杂的构建:
* auto profile = NURBS 曲线;
* auto swept = extrude(profile, Vector3D(0, 0, 10));
* auto rounded = fillet(swept, 0, 2.0);
* @endcode
*
* @ingroup brep
*/
#include "vde/core/point.h"
2026-07-23 07:19:13 +00:00
#include "vde/brep/brep.h"
namespace vde::brep {
using core::Point3D;
using core::Vector3D;
using core::AABB3D;
2026-07-23 07:19:13 +00:00
// ═══════════════════════════════════════════════
// 扫掠特征
// ═══════════════════════════════════════════════
/**
* @brief 沿方向挤出平面轮廓
*
* 将平面曲线沿给定方向扫掠,生成柱状实体。
*
* **算法:** 曲线的每个点沿方向向量平移,两端加盖平面形成封闭实体。
*
* @param profile 轮廓曲线(必须位于一个平面内)
* @param dir 挤出方向向量(其长度决定挤出距离)
* @return 挤出后的 B-Rep 实体
*
* @pre profile 必须是平面曲线(存在于某个平面内)且闭合
*
* @code{.cpp}
* // 沿 Z 轴挤出 5 个单位
* auto circle = NurbsCurve::create_circle(Point3D(0,0,0), 2.0);
* auto cylinder = extrude(circle, Vector3D(0, 0, 5));
* @endcode
*
* @see revolve 旋转扫掠
* @see sweep 沿任意路径扫掠
*/
2026-07-23 07:19:13 +00:00
[[nodiscard]] BrepModel extrude(const curves::NurbsCurve& profile, const Vector3D& dir);
/**
* @brief 绕轴旋转平面轮廓
*
* 将轮廓绕给定轴旋转,生成旋转体(如轮子、瓶子等)。
*
* @param profile 轮廓曲线(通常位于轴的半平面中)
* @param axis_origin 旋转轴上的一个点
* @param axis_dir 旋转轴方向(单位向量)
* @param angle_rad 旋转角度(弧度,默认 2π = 完整的旋转体)
* @return 旋转后的 B-Rep 实体
*
* @pre profile 必须在轴的同一侧(不应跨越轴线)
*
* @code{.cpp}
* // 绕 Y 轴旋转半圆,生成球体的一半
* NurbsCurve semicircle = 在 XZ 平面中的半圆弧;
* auto half_sphere = revolve(semicircle, Point3D(0,0,0),
* Vector3D(0,1,0), M_PI);
* @endcode
*
* @see extrude 线性挤出
* @see make_sphere 直接创建球体
*/
2026-07-23 07:19:13 +00:00
[[nodiscard]] BrepModel revolve(const curves::NurbsCurve& profile,
const Point3D& axis_origin,
const Vector3D& axis_dir,
double angle_rad = 2.0 * M_PI);
/**
* @brief 沿任意路径扫掠轮廓
*
* 轮廓沿一条空间路径曲线运动,生成管道或异形截面杆。
*
* @param profile 截面轮廓(需位于路径起点的垂直平面内)
* @param path 扫掠路径曲线
* @return 扫掠后的 B-Rep 实体
*
* @note 路径曲率过大处可能出现自交,需要控制路径的光滑性。
*
* @code{.cpp"}
* auto circle = NurbsCurve::create_circle(Point3D(0,0,0), 0.5);
* auto helix = NurbsCurve::create_helix(// ...);
* auto pipe = sweep(circle, helix);
* @endcode
*
* @see extrude 直线挤出
* @see revolve 旋转扫掠
*/
2026-07-23 07:19:13 +00:00
[[nodiscard]] BrepModel sweep(const curves::NurbsCurve& profile,
const curves::NurbsCurve& path);
/**
* @brief 在两个或多个轮廓曲线之间放样
*
* 通过线性或平滑插值连接多个平行或非平行轮廓,
* 生成过渡实体。
*
* @param profiles 轮廓曲线列表(至少 2 条)
* @return 放样后的 B-Rep 实体
*
* @pre profiles.size() ≥ 2
* @pre 所有轮廓应是平面曲线(逐一)
*
* @code{.cpp}
* auto profile_a = NurbsCurve::create_circle(Point3D(0,0,0), 5.0);
* auto profile_b = NurbsCurve::create_circle(Point3D(0,0,10), 2.0);
* auto cone = loft({profile_a, profile_b});
* @endcode
*
* @see extrude 单轮廓挤出
*/
2026-07-23 07:19:13 +00:00
[[nodiscard]] BrepModel loft(const std::vector<curves::NurbsCurve>& profiles);
// ═══════════════════════════════════════════════
// 基本体
// ═══════════════════════════════════════════════
/**
* @brief 创建立方体
*
* 以原点为中心、轴对齐的立方体。
*
* @param w 宽度(X 方向),必须 > 0
* @param h 高度(Y 方向),必须 > 0
* @param d 深度(Z 方向),必须 > 0
* @return 实心立方体 B-Rep
*
* @code{.cpp}
* auto box = make_box(10, 5, 3); // 10×5×3 的盒子
* @endcode
*
* @see make_cylinder 圆柱体
* @see make_sphere 球体
*/
2026-07-23 07:19:13 +00:00
[[nodiscard]] BrepModel make_box(double w, double h, double d);
/**
* @brief 创建圆柱体
*
* 沿 Y 轴、以原点为中心的圆柱体。
*
* @param radius 截面半径,必须 > 0
* @param height 总高度,沿 Y 轴从 -h/2 到 +h/2
* @param segments 截面分段数(边数,默认 32)
* @return 实心圆柱体 B-Rep
*
* @note segments 越大圆柱越光滑,但面和边数增加。
*
* @code{.cpp}
* auto cyl = make_cylinder(2.0, 10.0, 64); // 高精度圆柱
* @endcode
*
* @see make_box 立方体
* @see make_sphere 球体
*/
2026-07-23 07:19:13 +00:00
[[nodiscard]] BrepModel make_cylinder(double radius, double height, int segments = 32);
/**
* @brief 创建球体
*
* 以原点为中心的球体。
*
* @param radius 球半径,必须 > 0
* @param segments_u 经度方向分段数(默认 32)
* @param segments_v 纬度方向分段数(默认 16)
* @return 实心球体 B-Rep
*
* @code{.cpp}
* auto sphere = make_sphere(5.0, 32, 32);
* @endcode
*
* @see make_cylinder 圆柱体
*/
2026-07-23 07:19:13 +00:00
[[nodiscard]] BrepModel make_sphere(double radius, int segments_u = 32, int segments_v = 16);
// ═══════════════════════════════════════════════
// 编辑操作
// ═══════════════════════════════════════════════
/**
* @brief 对边做圆角处理
*
* 在指定的边上施加恒定半径的圆角(倒圆)。
* 适用于凹边和凸边。
*
* @param body 输入实体
* @param edge_id 要倒圆的边 ID
* @param radius 圆角半径,必须 > 0
* @return 圆角后的新实体
*
* @note 圆角半径不能超过相邻面的最小宽度,否则会产生自交。
*
* @code{.cpp}
* auto box = make_box(10, 5, 3);
* auto rounded = fillet(box, 0, 2.0); // 对边 0 做半径 2 的圆角
* @endcode
*
* @see fillet_variable 变半径圆角
* @see chamfer 倒角
* @see shell 抽壳
*/
2026-07-23 07:19:13 +00:00
[[nodiscard]] BrepModel fillet(const BrepModel& body, int edge_id, double radius);
/**
* @brief 变半径圆角
*
* 沿边的参数方向在 r_start 和 r_end 之间线性插值半径,
* 生成平滑过渡的圆角曲面。
*
* @param body 输入实体
* @param edge_id 要倒圆的边 ID
* @param r_start 边起点处的圆角半径
* @param r_end 边终点处的圆角半径
* @param samples 沿边的横截面采样数(默认 8)
* @return 变半径圆角后的新实体
*
* @pre r_start ≥ 0, r_end ≥ 0,且至少一个 > 0
* @note samples 越大截面过渡越光滑,但面和边数增加。
*
* @code{.cpp}
* auto box = make_box(10, 5, 3);
* auto result = fillet_variable(box, 0, 0.5, 2.0, 12);
* // 边 0 从 0.5 到 2.0 逐渐变化的圆角
* @endcode
*
* @see fillet 恒定半径圆角
*/
[[nodiscard]] BrepModel fillet_variable(const BrepModel& body, int edge_id,
double r_start, double r_end, int samples = 8);
/**
* @brief 对边做倒角
*
* 将尖锐边替换为 45° 斜面。
*
* @param body 输入实体
* @param edge_id 要倒角的边 ID
* @param distance 倒角距离(从原边沿两个面各偏移的距离)
* @return 倒角后的新实体
*
* @pre distance > 0
*
* @see fillet 圆角
*/
2026-07-23 07:19:13 +00:00
[[nodiscard]] BrepModel chamfer(const BrepModel& body, int edge_id, double distance);
/**
* @brief 抽壳(挖空实体)
*
* 将实体变为等厚度的壳,去除指定面形成开口。
*
* @param body 输入实心实体
* @param face_id 要移除的面 ID(形成开口),-1 表示封闭壳(不开口)
* @param thickness 壁厚(正值 = 向外偏移,负值 = 向内偏移)
* @return 抽壳后的新实体
*
* @note 壁厚不应超过实体最小尺寸的一半。
* @note 当 face_id = -1 时,结果是一个封闭的壳(中空但没有开口)。
*
* @code{.cpp"}
* auto box = make_box(10, 5, 3);
* auto shelled = shell(box, 0, 0.5); // 移除面 0,壁厚 0.5
* @endcode
*
* @see fillet 圆角
*/
2026-07-23 07:19:13 +00:00
[[nodiscard]] BrepModel shell(const BrepModel& body, int face_id, double thickness);
} // namespace vde::brep