Files
ViewDesignEngine/include/vde/boolean/boolean_mesh.h
T

192 lines
5.5 KiB
C++
Raw Normal View History

/**
* @file boolean_mesh.h
* @brief 三维网格布尔运算
*
* 基于半边的网格布尔操作:并集、交集、差集、对称差。
* 通过面片重心内外判定 (ray-casting) 实现拓扑分类。
*
* @ingroup boolean
*/
#pragma once
#include "vde/boolean/boolean_2d.h"
#include "vde/core/polygon.h"
#include "vde/mesh/halfedge_mesh.h"
namespace vde::boolean {
using core::Point2D;
using core::Polygon2D;
using mesh::HalfedgeMesh;
// ── Core 3D mesh boolean operations ──────────────────────────────
/**
* @brief 网格并集 A B
*
* 保留网格 A 中重心在网格 B 外的面片,
* 以及网格 B 中重心在网格 A 外的面片。
* 合并后形成两个网格的并集体积。
*
* 原理:对每个面片计算重心坐标,用射线投射判断
* 该点是否在对方网格内部,据此决定保留或剔除。
*
* @param a 网格 A
* @param b 网格 B
* @return A B 的合并网格
*
* @code{.cpp}
* HalfedgeMesh result = mesh_union(cube, sphere);
* @endcode
*
* @see mesh_intersection, mesh_difference, is_point_inside_mesh
*/
2026-07-23 12:36:39 +00:00
HalfedgeMesh mesh_union(const HalfedgeMesh& a, const HalfedgeMesh& b);
/**
* @brief 网格交集 A ∩ B
*
* 保留网格 A 中重心在网格 B 内的面片,
* 以及网格 B 中重心在网格 A 内的面片。
*
* @param a 网格 A
* @param b 网格 B
* @return A ∩ B 的交集网格
*
* @note 结果体积为两网格公共区域
*
* @see mesh_union, mesh_difference
*/
2026-07-23 12:36:39 +00:00
HalfedgeMesh mesh_intersection(const HalfedgeMesh& a, const HalfedgeMesh& b);
/**
* @brief 网格差集 A B
*
* 保留网格 A 中重心在网格 B 外的面片,
* 以及网格 B 中重心在网格 A 内的面片(翻转法线)。
*
* @param a 网格 A
* @param b 网格 B
* @return A B 的差集网格
*
* @note 结果中来自 B 的面片会被翻转法线以保持内-外一致性
*
* @see mesh_union, mesh_intersection, mesh_sym_diff
*/
2026-07-23 12:36:39 +00:00
HalfedgeMesh mesh_difference(const HalfedgeMesh& a, const HalfedgeMesh& b);
/**
* @brief 网格对称差 (A B) (B A)
*
* 等价于:
* @code{.cpp}
* mesh_union(mesh_difference(a, b), mesh_difference(b, a))
* @endcode
*
* @param a 网格 A
* @param b 网格 B
* @return 对称差网格
*
* @see mesh_difference, mesh_union
*/
2026-07-23 12:36:39 +00:00
HalfedgeMesh mesh_sym_diff(const HalfedgeMesh& a, const HalfedgeMesh& b);
// ── Helpers ─────────────────────────────────────────────────────
2026-07-23 12:36:39 +00:00
/**
* @brief 用网格 B 裁剪网格 A
*
* 保留网格 A 中位于 B 体外的面片。
* 是 mesh_difference 的简化变体,仅输出来自 A 的面片。
*
* @param a 待裁剪网格
* @param b 裁剪体网格
* @param invert_b 若为 true,将 B 的内外判定取反(裁剪外部)
* @return 裁剪后的网格(仅包含 A 的面片)
*
* @code{.cpp}
* // 裁剪 cube 外部的 sphere 面片
* auto clipped = clip_mesh(sphere, cube, false // invert_b);
* // 保留 cube 内部的 sphere 面片
* auto inner = clip_mesh(sphere, cube, true // invert_b);
* @endcode
*
* @see mesh_difference, is_point_inside_mesh
*/
2026-07-23 12:36:39 +00:00
HalfedgeMesh clip_mesh(const HalfedgeMesh& a, const HalfedgeMesh& b,
bool invert_b = false);
/**
* @brief 翻转网格所有面片的法线方向
*
* 遍历所有面片,反转其顶点环绕顺序。
* 常用于生成负体积(反向外壳)或差集操作中。
*
* @param m 原始网格
* @return 法线翻转后的网格
*
* @see mesh_difference
*/
2026-07-23 12:36:39 +00:00
HalfedgeMesh invert_mesh(const HalfedgeMesh& m);
/**
* @brief 合并两个网格
*
* 将两个网格的顶点和面片直接拼接,不做布尔操作。
* 用于将分离的网格组件合并到单个数据结构中。
*
* @param a 网格 A
* @param b 网格 B
* @return 包含 A 和 B 全部顶点和面片的合并网格
*
* @note 不处理重叠区域;仅做纯几何拼接
*
* @see mesh_union(做布尔合并)
*/
2026-07-23 12:36:39 +00:00
HalfedgeMesh merge_meshes(const HalfedgeMesh& a, const HalfedgeMesh& b);
/**
* @brief 网格布尔运算统一接口
*
* 根据布尔操作类型分发到对应的具体函数。
*
* @param a 网格 A
* @param b 网格 B
* @param op 布尔操作类型
* @return 结果网格
*
* @code{.cpp}
* auto result = mesh_boolean(cube, sphere, BooleanOp::Intersection);
* @endcode
*
* @see BooleanOp, mesh_union, mesh_intersection, mesh_difference, mesh_sym_diff
*/
HalfedgeMesh mesh_boolean(const HalfedgeMesh& a, const HalfedgeMesh& b, BooleanOp op);
// ── Point classification ────────────────────────────────────────
2026-07-23 12:36:39 +00:00
/**
* @brief 判断三维点是否在封闭网格内部
*
* 使用射线投射法:从点 p 向任意方向射出射线,
* 统计与网格面片的交点数量。
* 奇数表示在内部,偶数表示在外部。
*
* 算法:
* 1. 构造从 p 出发沿 +x 方向的射线
* 2. 遍历所有三角形进行射线-三角形求交
* 3. 统计交点数量
* 4. 返回奇偶性判定结果
*
* @param p 待判定点
* @param mesh 封闭网格
* @return 点在网格内部返回 true
*
* @note 网格必须是封闭(水密)的,否则结果不可靠。
* 点恰好落在面上时行为未定义。
*
* @see clip_mesh, mesh_difference
*/
2026-07-23 12:36:39 +00:00
bool is_point_inside_mesh(const core::Point3D& p, const HalfedgeMesh& mesh);
} // namespace vde::boolean