Files
ViewDesignEngine/include/vde/brep/gdt.h
T
茂之钳 11b606bd39
CI / Build & Test (push) Failing after 33s
CI / Release Build (push) Failing after 32s
Build & Test / build-and-test (push) Has been cancelled
Build & Test / python-bindings (push) Has been cancelled
feat(v6.0): FFD freeform deformation + auto-dimensioning + PMI/MBD + Web viewer
v6.0.1 — FFD Freeform Deformation:
- ffd_deformation.h/.cpp: Bezier volume lattice, deform_brep/deform_mesh
- Bernstein polynomial mapping, topology-preserving
- Cage-based + lattice-based FFD, create_cage_lattice()

v6.0.2 — Auto-Dimensioning + PMI/MBD + GD&T:
- auto_dimensioning.h/.cpp: linear/angular/radial/diameter detection
- ISO/ANSI/JIS drawing standards, smart label placement
- gdt.h/.cpp: 14 GD&T symbols (ASME Y14.5), MMC/LMC/RFS material conditions
- pmi_mbd.h/.cpp: PMIAnnotation, attach_pmi, PMIView, STEP AP242 export
- 70/70 tests passing (23 auto-dim + 25 PMI + 22 GD&T regression)

v6.0.3 — Web 3D Viewer Enhancement:
- viewer/index.html + app.js: Three.js GLB/STL loading
- OrbitControls, face coloring, dimension overlay, GD&T display
- Measure tool (raycaster), clip plane slider, explode animation
- Drag-and-drop file upload, responsive layout
2026-07-26 21:55:16 +08:00

400 lines
14 KiB
C++

#pragma once
/**
* @file gdt.h
* @brief GD&T 几何公差标注与验证
*
* 支持 ASME Y14.5 标准几何公差:形状公差、方向公差、位置公差、跳动公差。
* 提供公差标注数据结构和公差带计算。
*
* @ingroup brep
*/
#include "vde/core/point.h"
#include "vde/brep/brep.h"
#include <vector>
#include <string>
#include <optional>
namespace vde::brep {
// ═══════════════════════════════════════════════════════════
// Tolerance Types (ASME Y14.5)
// ═══════════════════════════════════════════════════════════
/// GD&T 公差类型
enum class GDTType {
// Form tolerances (形状公差)
Flatness, ///< 平面度
Straightness, ///< 直线度
Circularity, ///< 圆度
Cylindricity, ///< 圆柱度
// Orientation tolerances (方向公差)
Parallelism, ///< 平行度
Perpendicularity,///< 垂直度
Angularity, ///< 倾斜度
// Location tolerances (位置公差)
Position, ///< 位置度
Concentricity, ///< 同心度
Symmetry, ///< 对称度
// Profile tolerances (轮廓公差)
ProfileOfLine, ///< 线轮廓度
ProfileOfSurface,///< 面轮廓度
// Runout tolerances (跳动公差)
CircularRunout, ///< 圆跳动
TotalRunout, ///< 全跳动
};
/// Material condition for tolerance / datum modifiers
enum class GDTMaterialCondition {
RFS, ///< Regardless of Feature Size — no modifier
MMC, ///< Maximum Material Condition — Ⓜ
LMC, ///< Least Material Condition — Ⓛ
};
/// Datum reference with material condition
struct DatumReference {
std::string label; ///< Datum label (A, B, C...)
int face_id = -1; ///< Associated B-Rep face ID
bool is_primary = false; ///< Primary datum
GDTMaterialCondition material_condition = GDTMaterialCondition::RFS;
/// Constructor for backward compat (label, face_id, is_primary)
DatumReference() = default;
DatumReference(const std::string& l, int f, bool p)
: label(l), face_id(f), is_primary(p) {}
DatumReference(const std::string& l, int f, bool p, GDTMaterialCondition mc)
: label(l), face_id(f), is_primary(p), material_condition(mc) {}
[[nodiscard]] std::string to_string() const;
};
/// 特征控制框(一个完整的 GD&T 标注)
struct GDTFeature {
GDTType type = GDTType::Flatness; ///< 公差类型
double tolerance_value = 0.1; ///< 公差值
std::vector<DatumReference> datums; ///< 基准引用
int target_face_id = -1; ///< 目标面 ID
/// 附加修饰符
bool mmc = false; ///< 最大实体条件 MⓂ
bool lmc = false; ///< 最小实体条件 LⓁ
bool projected = false; ///< 投影公差带 PⓅ
double projected_height = 0.0; ///< 投影高度
/// 公差带形状(默认平行平面)
enum class ZoneShape { ParallelPlanes, Cylindrical, Spherical, Uniform };
ZoneShape zone_shape = ZoneShape::ParallelPlanes;
/// 获取公差符号(用于显示)
[[nodiscard]] std::string symbol() const;
/// 获取完整标注字符串
[[nodiscard]] std::string to_string() const;
};
// ═══════════════════════════════════════════════════════════
// GD&T Validation Result
// ═══════════════════════════════════════════════════════════
/// GD&T 验证结果
struct GDTValidationResult {
bool pass = true; ///< 是否合格
double actual_deviation = 0.0; ///< 实际偏差
double tolerance = 0.0; ///< 公差要求
std::string description; ///< 描述
std::vector<std::string> warnings; ///< 警告信息
};
// ═══════════════════════════════════════════════════════════
// GD&T Annotations (for drawing views)
// ═══════════════════════════════════════════════════════════
/// 单个 GD&T 标注(含 2D 位置信息,用于工程图)
struct GDTAnnotation {
GDTFeature feature; ///< 特征控制框
core::Point3D leader_point; ///< 引线箭头位置
core::Point3D frame_position; ///< 控制框放置位置
std::string view_name; ///< 所属视图名称
/// 生成 DXF 格式的控制框文本
[[nodiscard]] std::string to_dxf_text() const;
};
// ═══════════════════════════════════════════════════════════
// API
// ═══════════════════════════════════════════════════════════
/**
* @brief 验证 B-Rep 模型的 GD&T 要求
*
* @param body B-Rep 模型
* @param feature GD&T 特征要求
* @return 验证结果
*/
[[nodiscard]] GDTValidationResult validate_gdt(
const BrepModel& body, const GDTFeature& feature);
/**
* @brief 计算面的平面度
*
* 测量面到最佳拟合平面(最小二乘)的最大偏差。
*
* @param body B-Rep 模型
* @param face_id 面 ID
* @return 平面度偏差值
*/
[[nodiscard]] double compute_flatness(const BrepModel& body, int face_id);
/**
* @brief 计算两面的平行度
*
* 测量实际面相对于基准面的平行偏差。
*
* @param body B-Rep 模型
* @param face_id 被测面 ID
* @param datum_face_id 基准面 ID
* @return 平行度偏差值
*/
[[nodiscard]] double compute_parallelism(
const BrepModel& body, int face_id, int datum_face_id);
/**
* @brief 计算两面的垂直度
*
* @param body B-Rep 模型
* @param face_id 被测面
* @param datum_face_id 基准面
* @return 垂直度偏差值
*/
[[nodiscard]] double compute_perpendicularity(
const BrepModel& body, int face_id, int datum_face_id);
/**
* @brief 计算同心度
*
* 测量两圆柱/圆特征轴线的偏移。
*
* @param body B-Rep 模型
* @param face_id 被测特征面
* @param datum_face_id 基准特征面
* @return 同心度偏差值
*/
[[nodiscard]] double compute_concentricity(
const BrepModel& body, int face_id, int datum_face_id);
/**
* @brief 计算位置度
*
* 测量特征实际位置与理论位置的偏差。
*
* @param body B-Rep 模型
* @param face_id 被测面
* @param theoretical_position 理论位置
* @return 位置度偏差值
*/
[[nodiscard]] double compute_position(
const BrepModel& body, int face_id,
const core::Point3D& theoretical_position);
/**
* @brief 将 GD&T 标注转换为 DXF 文本
*
* @param annotations GD&T 标注列表
* @return DXF 格式文本
*/
[[nodiscard]] std::string export_gdt_annotations_dxf(
const std::vector<GDTAnnotation>& annotations);
// ═══════════════════════════════════════════════════════════
// GDTCallout — Complete feature control frame
// ═══════════════════════════════════════════════════════════
/// Tolerance value with optional material condition modifier
struct GDTToleranceValue {
double value = 0.1; ///< Tolerance value
GDTMaterialCondition material_condition = GDTMaterialCondition::RFS;
bool diameter_symbol = false; ///< Ø prefix (cylindrical zone)
bool spherical_diameter = false; ///< SØ prefix
/// Format as string e.g. "Ø0.1Ⓜ", "0.05", "SØ0.2"
[[nodiscard]] std::string to_string() const;
};
/// Feature control frame — complete GD&T callout
struct GDTCallout {
GDTType type = GDTType::Flatness; ///< GD&T characteristic type
GDTToleranceValue tolerance; ///< Tolerance value + modifiers
std::vector<DatumReference> datums; ///< Datum references (0-3)
int target_face_id = -1; ///< Target face ID
int target_edge_id = -1; ///< Target edge ID
bool projected_tolerance = false; ///< Projected tolerance zone Ⓟ
double projected_height = 0.0; ///< Projected height
GDTFeature::ZoneShape zone_shape = GDTFeature::ZoneShape::ParallelPlanes;
/// Generate full feature control frame text
/// e.g. "⟂ | Ø0.1Ⓜ | A | BⓂ | C"
[[nodiscard]] std::string to_frame_string() const;
/// Get the GD&T symbol character
[[nodiscard]] std::string symbol() const;
/// Convert to legacy GDTFeature for backward compatibility
[[nodiscard]] GDTFeature to_feature() const;
/// Create from legacy GDTFeature
[[nodiscard]] static GDTCallout from_feature(const GDTFeature& f);
};
// ═══════════════════════════════════════════════════════════
// GD&T Frame Builder API
// ═══════════════════════════════════════════════════════════
/**
* @brief Create a complete GD&T control frame for a set of features
*
* Given a B-Rep model and a list of target face/edge IDs, generates
* appropriate GD&T callouts based on feature geometry analysis.
*
* @param model B-Rep model
* @param face_ids Target face IDs to annotate
* @param datum_face_ids Datum face IDs for reference
* @return Vector of GD&T callouts
*/
[[nodiscard]] std::vector<GDTCallout> create_gdt_frame(
const BrepModel& model,
const std::vector<int>& face_ids,
const std::vector<int>& datum_face_ids = {});
/**
* @brief Create a GD&T callout with full parameter control
*
* @param type GD&T type
* @param tolerance_value Tolerance value
* @param datums Datum references (can be empty for form tolerances)
* @param target_face_id Target face
* @return Complete GDTCallout
*/
[[nodiscard]] GDTCallout make_gdt_callout(
GDTType type,
double tolerance_value,
const std::vector<DatumReference>& datums = {},
int target_face_id = -1);
/**
* @brief Check if GD&T type requires a datum reference
*
* Form tolerances (Flatness, Straightness, Circularity, Cylindricity)
* and Profile do not require datums.
*
* @param type GD&T type
* @return true if datums are required
*/
[[nodiscard]] bool gdt_requires_datum(GDTType type);
/**
* @brief Get recommended datum count for a GD&T type
*
* @param type GD&T type
* @return Expected number of datums (0-3)
*/
[[nodiscard]] int gdt_expected_datums(GDTType type);
/**
* @brief Validate a GD&T callout for correctness
*
* Checks: datum requirements, tolerance positivity, face ID validity.
*
* @param model B-Rep model
* @param callout GD&T callout to validate
* @return Error messages (empty = valid)
*/
[[nodiscard]] std::vector<std::string> validate_gdt_callout(
const BrepModel& model, const GDTCallout& callout);
/**
* @brief Compute circularity (roundness) of a cylindrical face
*
* @param body B-Rep model
* @param face_id Cylindrical face ID
* @return Circularity deviation
*/
[[nodiscard]] double compute_circularity(const BrepModel& body, int face_id);
/**
* @brief Compute cylindricity of a cylindrical face
*
* @param body B-Rep model
* @param face_id Cylindrical face ID
* @return Cylindricity deviation
*/
[[nodiscard]] double compute_cylindricity(const BrepModel& body, int face_id);
/**
* @brief Compute straightness of an edge
*
* @param body B-Rep model
* @param edge_id Edge ID
* @return Straightness deviation from best-fit line
*/
[[nodiscard]] double compute_straightness(const BrepModel& body, int edge_id);
/**
* @brief Compute angularity between face and datum
*
* @param body B-Rep model
* @param face_id Target face
* @param datum_face_id Datum face
* @param nominal_angle_deg Nominal angle in degrees
* @return Angularity deviation
*/
[[nodiscard]] double compute_angularity(const BrepModel& body,
int face_id, int datum_face_id, double nominal_angle_deg);
/**
* @brief Compute symmetry between face and datum
*
* @param body B-Rep model
* @param face_id Target face
* @param datum_face_id Datum face
* @return Symmetry deviation
*/
[[nodiscard]] double compute_symmetry(const BrepModel& body,
int face_id, int datum_face_id);
/**
* @brief Compute profile of a surface (uniform tolerance zone)
*
* @param body B-Rep model
* @param face_id Target face
* @return Maximum deviation from nominal surface
*/
[[nodiscard]] double compute_profile_of_surface(const BrepModel& body, int face_id);
/**
* @brief Compute circular runout
*
* @param body B-Rep model
* @param face_id Target cylindrical face
* @param datum_axis_face_id Datum axis face
* @return Circular runout value
*/
[[nodiscard]] double compute_circular_runout(const BrepModel& body,
int face_id, int datum_axis_face_id);
/**
* @brief Compute total runout
*
* @param body B-Rep model
* @param face_id Target cylindrical face
* @param datum_axis_face_id Datum axis face
* @return Total runout value
*/
[[nodiscard]] double compute_total_runout(const BrepModel& body,
int face_id, int datum_axis_face_id);
} // namespace vde::brep