295 lines
9.3 KiB
C++
295 lines
9.3 KiB
C++
#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"
|
||
#include "vde/brep/brep.h"
|
||
|
||
namespace vde::brep {
|
||
using core::Point3D;
|
||
using core::Vector3D;
|
||
using core::AABB3D;
|
||
|
||
// ═══════════════════════════════════════════════
|
||
// 扫掠特征
|
||
// ═══════════════════════════════════════════════
|
||
|
||
/**
|
||
* @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 沿任意路径扫掠
|
||
*/
|
||
[[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 直接创建球体
|
||
*/
|
||
[[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 旋转扫掠
|
||
*/
|
||
[[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 单轮廓挤出
|
||
*/
|
||
[[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 球体
|
||
*/
|
||
[[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 球体
|
||
*/
|
||
[[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 圆柱体
|
||
*/
|
||
[[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 抽壳
|
||
*/
|
||
[[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 圆角
|
||
*/
|
||
[[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 圆角
|
||
*/
|
||
[[nodiscard]] BrepModel shell(const BrepModel& body, int face_id, double thickness);
|
||
|
||
} // namespace vde::brep
|