244 lines
8.4 KiB
C++
244 lines
8.4 KiB
C++
|
|
#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
|