Files
ViewDesignEngine/include/vde/brep/pmi_mbd.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

332 lines
12 KiB
C++

#pragma once
/**
* @file pmi_mbd.h
* @brief Product Manufacturing Information (PMI) and Model-Based Definition (MBD)
*
* Attaches semantic PMI annotations (dimensions, tolerances, GD&T, surface finish,
* notes) directly to 3D B-Rep models. Supports STEP AP242 export with embedded PMI.
*
* PMI annotations are the digital equivalent of 2D drawing annotations placed
* directly on the 3D model, enabling paperless manufacturing workflows.
*
* @ingroup brep
*/
#include "vde/brep/brep.h"
#include "vde/brep/gdt.h"
#include "vde/brep/auto_dimensioning.h"
#include "vde/core/point.h"
#include <vector>
#include <string>
#include <memory>
#include <map>
#include <set>
namespace vde::brep {
// ═══════════════════════════════════════════════════════════
// PMI Annotation Types
// ═══════════════════════════════════════════════════════════
/// PMI annotation category
enum class PMIType {
Dimension, ///< Linear/angular/radial dimension
GDTCalloutType, ///< Geometric dimensioning & tolerancing
DatumTarget, ///< Datum target symbol
SurfaceFinish, ///< Surface finish / roughness
Note, ///< General note / text
WeldSymbol, ///< Welding symbol
DatumFeature, ///< Datum feature identifier
Balloon, ///< Balloon callout (for BOM)
Custom, ///< Custom annotation
};
/// PMI annotation display properties
struct PMIDisplayProps {
bool visible = true; ///< Visibility toggle
std::string color = "#000000"; ///< Text/line color (hex)
double text_height = 3.5; ///< Text height in mm
double line_width = 0.35; ///< Line width in mm
std::string font = "ISOCP"; ///< Font name (ISO standard)
bool show_leader = true; ///< Show leader line
bool show_frame = false; ///< Show bounding frame
int layer = 0; ///< Display layer for organization
};
/// PMI annotation — semantic 3D annotation attached to model geometry
struct PMIAnnotation {
int id = -1; ///< Unique annotation ID
PMIType type = PMIType::Note; ///< Annotation category
std::string label; ///< Display label / identifier
/// Associated geometry elements (face IDs, edge IDs, vertex IDs)
std::vector<int> associated_faces;
std::vector<int> associated_edges;
std::vector<int> associated_vertices;
/// 3D position of the annotation text
core::Point3D text_position;
/// Leader attachment point on the model surface
core::Point3D attachment_point;
/// Plane normal for annotation orientation (text plane normal)
core::Vector3D annotation_normal;
/// Text content
std::string content; ///< Main annotation text
std::string sub_content; ///< Secondary line text
std::string prefix; ///< Text prefix (Ø, R, etc.)
std::string suffix; ///< Text suffix
/// For dimension-type PMI
double nominal_value = 0.0;
double tolerance_upper = 0.0;
double tolerance_lower = 0.0;
/// For GD&T-type PMI
GDTType gdt_type = GDTType::Flatness;
std::vector<DatumReference> datum_refs;
/// Display properties
PMIDisplayProps display;
/// Custom metadata key-value pairs
std::map<std::string, std::string> metadata;
/// Get annotation type name string
[[nodiscard]] std::string type_name() const;
/// Generate STEP AP242 representation string for this annotation
[[nodiscard]] std::string to_step_ap242(int& next_id) const;
};
// ═══════════════════════════════════════════════════════════
// PMI View Management
// ═══════════════════════════════════════════════════════════
/// PMI view — a named view with specific annotation visibility
class PMIView {
public:
PMIView() = default;
explicit PMIView(const std::string& name) : name_(name) {}
/// Set view name
void set_name(const std::string& name) { name_ = name; }
[[nodiscard]] const std::string& name() const { return name_; }
/// Set view direction
void set_direction(const core::Vector3D& dir) { direction_ = dir; }
[[nodiscard]] const core::Vector3D& direction() const { return direction_; }
/// Add a visible annotation to this view
void add_annotation(int annotation_id);
/// Remove an annotation from this view
void remove_annotation(int annotation_id);
/// Check if an annotation is visible in this view
[[nodiscard]] bool is_visible(int annotation_id) const;
/// Get all visible annotation IDs
[[nodiscard]] const std::set<int>& visible_annotations() const { return visible_ids_; }
/// Set all annotations visible (except hidden)
void set_all_visible(const std::vector<int>& all_ids);
/// Set all annotations hidden
void clear_all();
/// Hide specific annotations
void hide_annotations(const std::vector<int>& ids);
/// Add a note to this view
void set_note(const std::string& note) { note_ = note; }
[[nodiscard]] const std::string& note() const { return note_; }
/// View scale
void set_scale(double s) { scale_ = s; }
[[nodiscard]] double scale() const { return scale_; }
private:
std::string name_;
core::Vector3D direction_{0, 0, -1}; ///< Default: front view
std::set<int> visible_ids_;
std::string note_;
double scale_ = 1.0;
};
// ═══════════════════════════════════════════════════════════
// PMI Model — container for all PMI on a model
// ═══════════════════════════════════════════════════════════
/// PMI model — collection of all PMI annotations and views for a B-Rep model
class PMIModel {
public:
PMIModel() = default;
// ── Annotation management ──
/// Attach a PMI annotation to the model
/// @return The assigned annotation ID
int attach_pmi(const PMIAnnotation& annotation);
/// Attach PMI and return reference
int attach_pmi(PMIAnnotation&& annotation);
/// Remove an annotation by ID
/// @return true if found and removed
bool remove_pmi(int annotation_id);
/// Get annotation by ID
[[nodiscard]] const PMIAnnotation* get_annotation(int id) const;
/// Get all annotations
[[nodiscard]] const std::vector<PMIAnnotation>& annotations() const { return annotations_; }
/// Get annotations associated with a specific face
[[nodiscard]] std::vector<const PMIAnnotation*> annotations_for_face(int face_id) const;
/// Get annotations associated with a specific edge
[[nodiscard]] std::vector<const PMIAnnotation*> annotations_for_edge(int edge_id) const;
/// Get annotations of a specific type
[[nodiscard]] std::vector<const PMIAnnotation*> annotations_of_type(PMIType type) const;
/// Total annotation count
[[nodiscard]] size_t count() const { return annotations_.size(); }
// ── View management ──
/// Add or update a PMI view
void set_view(const std::string& name, const PMIView& view);
void set_view(const std::string& name, PMIView&& view);
/// Get a view by name
[[nodiscard]] const PMIView* get_view(const std::string& name) const;
/// Get all views
[[nodiscard]] const std::map<std::string, PMIView>& views() const { return views_; }
/// Remove a view
void remove_view(const std::string& name);
/// Create default views (front, top, right, iso)
void create_default_views();
// ── STEP AP242 export ──
/// Export PMI as STEP AP242 embedded annotations
[[nodiscard]] std::string to_step_ap242() const;
/// Total size of STEP AP242 output (approximate)
[[nodiscard]] size_t step_ap242_byte_count() const;
private:
std::vector<PMIAnnotation> annotations_;
std::map<std::string, PMIView> views_;
int next_annotation_id_ = 1;
};
// ═══════════════════════════════════════════════════════════
// Top-level API
// ═══════════════════════════════════════════════════════════
/**
* @brief Attach PMI annotations to a B-Rep model
*
* Convenience function: adds annotation to a PMIModel associated with the body.
*
* @param body B-Rep model
* @param annotation PMI annotation to attach
* @param pmi_model PMI model container (modified in-place)
* @return Assigned annotation ID
*/
int attach_pmi(BrepModel& body, const PMIAnnotation& annotation,
PMIModel& pmi_model);
/**
* @brief Export B-Rep model with PMI as STEP AP242
*
* Produces a STEP AP242 file containing both geometry and embedded PMI.
*
* @param body B-Rep model
* @param pmi_model PMI annotations and views
* @return STEP AP242 string with PMI
*/
[[nodiscard]] std::string export_pmi_step_ap242(
const BrepModel& body, const PMIModel& pmi_model);
/**
* @brief Export to STEP AP242 file
*
* @param filepath Output file path (.stp, .step, .p21)
* @param body B-Rep model
* @param pmi_model PMI annotations and views
*/
void export_pmi_step_ap242_file(const std::string& filepath,
const BrepModel& body, const PMIModel& pmi_model);
/**
* @brief Auto-generate PMI annotations from B-Rep model
*
* Creates dimension PMI, GD&T PMI, and surface finish annotations.
*
* @param body B-Rep model
* @param pmi_model PMI model to populate (modified in-place)
* @param standard Drawing standard for format
* @return Number of annotations generated
*/
int auto_generate_pmi(const BrepModel& body, PMIModel& pmi_model,
DrawingStandard standard = DrawingStandard::ISO);
/**
* @brief Create a PMI dimension annotation
*
* @param type PMI type
* @param value Dimension value
* @param position 3D text position
* @param face_ids Associated face IDs
* @return PMIAnnotation ready to attach
*/
[[nodiscard]] PMIAnnotation make_pmi_dimension(
PMIType type, double value,
const core::Point3D& position,
const std::vector<int>& face_ids);
/**
* @brief Create a PMI GD&T annotation from a GDTCallout
*
* @param callout GD&T callout
* @param position 3D text position
* @return PMIAnnotation ready to attach
*/
[[nodiscard]] PMIAnnotation make_pmi_gdt(
const GDTCallout& callout,
const core::Point3D& position);
/**
* @brief Create a PMI surface finish annotation
*
* @param roughness_ra Ra value in μm
* @param face_id Associated face ID
* @param position 3D text position
* @return PMIAnnotation ready to attach
*/
[[nodiscard]] PMIAnnotation make_pmi_surface_finish(
double roughness_ra, int face_id,
const core::Point3D& position);
/**
* @brief Create a PMI datum target annotation
*
* @param label Datum label (A, B, C...)
* @param face_id Associated face ID
* @param position 3D position
* @return PMIAnnotation ready to attach
*/
[[nodiscard]] PMIAnnotation make_pmi_datum_target(
const std::string& label, int face_id,
const core::Point3D& position);
} // namespace vde::brep