#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 #include #include 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& 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 vertex_attrs; std::vector edge_attrs; std::vector face_attrs; std::vector 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* 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 serialize_vde( const brep::BrepModel& body, const VdeAttributes& attrs = {}, const std::vector* history = nullptr); /** * @brief 从二进制缓冲区反序列化 VDE 模型 * * @param data 二进制数据 * @return 加载的 BrepModel */ [[nodiscard]] brep::BrepModel deserialize_vde(const std::vector& data); } // namespace vde::foundation