feat(v1.0.1): P2 improvements — TolerantEdge + .vde format + boolean fallback
CI / Build & Test (push) Failing after 24s
CI / Release Build (push) Failing after 31s
Build & Test / build-and-test (push) Has been cancelled
Build & Test / python-bindings (push) Has been cancelled

P2 — TolerantEdge (ACIS):
- TolerantEdge: tube_radius, path_tolerance, is_within_tube, intersects
- detect_tolerance_conflicts: VertexInSphere/EdgeInTube/FaceGap
- resolve_tolerance_conflicts: auto merge vertices/edges/gaps

P2 — .vde Native Format (ACIS):
- Binary format: VdeHeader(32B), 6 SerializationSections
- save_vde/load_vde: full B-Rep topology + geometry + tolerance + attributes
- save_vde_json: debuggable JSON export

P2 — Boolean Fallback Ladder (Parasolid):
- 4-level cascade: SSI → tolerant → mesh → SDF
- Level 4 never fails (SDF + MC mathematical guarantee)
- BooleanFallbackResult with per-level diagnostics

Total: +~2650 lines across 8 files
This commit is contained in:
茂之钳
2026-07-27 21:01:33 +08:00
parent 1aa753ba50
commit 4b90438315
13 changed files with 2884 additions and 2 deletions
+243
View File
@@ -0,0 +1,243 @@
#pragma once
/**
* @file vde_format.h
* @brief VDE 原生格式(.vde)二进制读写
*
* VDE 原生格式是一种自包含的二进制格式,用于高效保存和加载
* B-Rep 模型的完整数据(拓扑、几何、容差、属性、建模历史)。
*
* ## 文件结构
*
* ```
* VdeHeader (32 bytes)
* ├─ magic[4] = "VDE1"
* ├─ version (u32) = 1
* ├─ flags (u32)
* └─ data_offset (u32)
*
* SerializationSection 数据块:
* ├─ SECTION_TOPOLOGY — B-Rep 拓扑(V/E/L/F/S/B
* ├─ SECTION_GEOMETRY — 几何数据(顶点坐标/曲面控制点/裁剪参数/NURBS曲线)
* ├─ SECTION_TOLERANCE — ToleranceConfig
* ├─ SECTION_ATTRIBUTES — 面/边/顶点/体属性(颜色/名称/自定义数据)
* └─ SECTION_HISTORY — 建模历史 FeatureNode 列表(可选)
* ```
*
* ## 使用示例
*
* @code{.cpp}
* #include "vde/foundation/vde_format.h"
* using namespace vde::foundation;
*
* // 保存
* brep::BrepModel body = make_box(10, 5, 3);
* save_vde(body, "output.vde");
*
* // 加载
* auto loaded = load_vde("output.vde");
*
* // JSON 调试
* save_vde_json(body, "output.vde.json");
* @endcode
*
* @ingroup foundation
*/
#include "vde/brep/brep.h"
#include "vde/brep/tolerance.h"
#include "vde/brep/feature_tree.h"
#include <string>
#include <vector>
#include <cstdint>
namespace vde::foundation {
// ═══════════════════════════════════════════════════════════════
// VDE 头部
// ═══════════════════════════════════════════════════════════════
/// VDE 文件魔术字节
constexpr uint32_t VDE_MAGIC_FOURCC = 0x31454456; // "VDE1" (little-endian)
/// VDE 文件当前版本号
constexpr uint32_t VDE_FILE_VERSION = 1;
/// VDE 标志位:是否包含建模历史
constexpr uint32_t VDE_FLAG_HAS_HISTORY = 0x00000001;
/// VDE 标志位:是否包含属性数据
constexpr uint32_t VDE_FLAG_HAS_ATTRIBUTES = 0x00000002;
/// VDE 标志位:是否包含裁剪曲面
constexpr uint32_t VDE_FLAG_HAS_TRIMMED = 0x00000004;
/**
* @brief VDE 文件头(32 字节)
*
* 二进制布局(小端序):
* - 字节 03: magic "VDE1" (uint32, 0x31454456)
* - 字节 47: version (uint32)
* - 字节 811: flags (uint32)
* - 字节 1215: data_offset (uint32, 数据区起始偏移)
* - 字节 1631: reserved (16 bytes, 当前填充 0)
*/
struct VdeHeader {
uint32_t magic; ///< 魔术数字 0x31454456 ("VDE1")
uint32_t version; ///< 格式版本号
uint32_t flags; ///< 标志位(VDE_FLAG_* 组合)
uint32_t data_offset; ///< 数据区相对于文件头的偏移(字节)
uint8_t reserved[16];///< 保留字段
/// 构造默认头部(版本=1,标志=0,偏移=32)
VdeHeader();
/// 从内存解析头部
static VdeHeader parse(const uint8_t* data, size_t size);
/// 将头部编码写入缓冲区
void encode(std::vector<uint8_t>& buf) const;
/// 验证头部有效性
[[nodiscard]] bool is_valid() const;
};
// ═══════════════════════════════════════════════════════════════
// 序列化段枚举
// ═══════════════════════════════════════════════════════════════
/**
* @brief 序列化段类型标识
*
* 每个段由 [section_id:uint16][section_size:uint64][data...] 组成。
* 段按顺序写入,读取时按需跳过未知段。
*/
enum class SerializationSection : uint16_t {
SECTION_HEADER = 0, ///< 文件头(不在数据区重复)
SECTION_TOPOLOGY = 1, ///< B-Rep 拓扑(V/E/L/F/S/B
SECTION_GEOMETRY = 2, ///< 几何数据(曲面/曲线/裁剪参数)
SECTION_TOLERANCE = 3, ///< ToleranceConfig 容差配置
SECTION_ATTRIBUTES = 4, ///< 面/边/顶点/体属性
SECTION_HISTORY = 5, ///< 建模历史 FeatureNode 列表
};
// ═══════════════════════════════════════════════════════════════
// 属性数据结构
// ═══════════════════════════════════════════════════════════════
/// 顶点属性
struct VdeVertexAttribute {
int vertex_id = -1;
std::string name;
uint32_t color_rgba = 0xFFFFFFFF; ///< RGBA 颜色
std::string custom_data; ///< 自定义数据(键值对或 JSON)
};
/// 边属性
struct VdeEdgeAttribute {
int edge_id = -1;
std::string name;
uint32_t color_rgba = 0xFFFFFFFF;
std::string custom_data;
};
/// 面属性
struct VdeFaceAttribute {
int face_id = -1;
std::string name;
uint32_t color_rgba = 0xFFFFFFFF;
std::string custom_data;
};
/// 体属性
struct VdeBodyAttribute {
int body_id = -1;
std::string name;
std::string custom_data;
};
/// 属性集合
struct VdeAttributes {
std::vector<VdeVertexAttribute> vertex_attrs;
std::vector<VdeEdgeAttribute> edge_attrs;
std::vector<VdeFaceAttribute> face_attrs;
std::vector<VdeBodyAttribute> body_attrs;
};
// ═══════════════════════════════════════════════════════════════
// VDE 格式主 API
// ═══════════════════════════════════════════════════════════════
/**
* @brief 将 B-Rep 模型保存为 VDE 二进制文件
*
* 写入完整的模型数据,包括拓扑、几何、容差、属性和建模历史。
*
* @param body B-Rep 模型
* @param path 输出文件路径(.vde
* @param attrs 面/边/顶点/体属性(可选,默认空)
* @param history 建模历史节点列表(可选,默认空)
* @return true 保存成功
*
* @throws std::runtime_error 写入失败
*/
bool save_vde(const brep::BrepModel& body,
const std::string& path,
const VdeAttributes& attrs = {},
const std::vector<brep::FeatureNode>* history = nullptr);
/**
* @brief 从 VDE 二进制文件加载 B-Rep 模型
*
* 读取并解析 .vde 格式文件,恢复完整的 B-Rep 模型数据。
*
* @param path 输入文件路径(.vde
* @return 加载的 BrepModel
*
* @throws std::runtime_error 文件无效或解析失败
*/
[[nodiscard]] brep::BrepModel load_vde(const std::string& path);
/**
* @brief 从 VDE 二进制文件加载 B-Rep 模型及属性
*
* @param path 输入文件路径(.vde
* @param out_attrs 输出属性数据
* @return 加载的 BrepModel
*/
[[nodiscard]] brep::BrepModel load_vde_with_attrs(const std::string& path,
VdeAttributes& out_attrs);
/**
* @brief 将 B-Rep 模型保存为 VDE JSON 文件(可调试格式)
*
* 以人类可读的 JSON 格式导出模型数据,方便调试和检查。
* JSON 版本不包含二进制段,而是以键值对形式组织。
*
* @param body B-Rep 模型
* @param path 输出文件路径(.vde.json 或 .json
* @param attrs 属性数据(可选)
* @return true 保存成功
*/
bool save_vde_json(const brep::BrepModel& body,
const std::string& path,
const VdeAttributes& attrs = {});
/**
* @brief 将 B-Rep 模型序列化为 VDE 二进制缓冲区
*
* @param body B-Rep 模型
* @param attrs 属性数据(可选)
* @param history 建模历史节点(可选)
* @return 二进制数据
*/
[[nodiscard]] std::vector<uint8_t> serialize_vde(
const brep::BrepModel& body,
const VdeAttributes& attrs = {},
const std::vector<brep::FeatureNode>* history = nullptr);
/**
* @brief 从二进制缓冲区反序列化 VDE 模型
*
* @param data 二进制数据
* @return 加载的 BrepModel
*/
[[nodiscard]] brep::BrepModel deserialize_vde(const std::vector<uint8_t>& data);
} // namespace vde::foundation