feat(v1.0.1): P2 improvements — TolerantEdge + .vde format + boolean fallback
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:
@@ -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 字节)
|
||||
*
|
||||
* 二进制布局(小端序):
|
||||
* - 字节 0–3: magic "VDE1" (uint32, 0x31454456)
|
||||
* - 字节 4–7: version (uint32)
|
||||
* - 字节 8–11: flags (uint32)
|
||||
* - 字节 12–15: data_offset (uint32, 数据区起始偏移)
|
||||
* - 字节 16–31: 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
|
||||
Reference in New Issue
Block a user