11b606bd39
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
332 lines
12 KiB
C++
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
|