Files

118 lines
5.7 KiB
C++
Raw Permalink Normal View History

/// \file 09_brep_fab/main.cpp
/// \brief Fabrication-oriented B-Rep modeling: box → shell → STEP + GLB export
///
/// Demonstrates a typical design-for-manufacturing workflow using boundary
/// representation (B-Rep). The part is exported both to STEP (AP214, for
/// CAM/CNC) and to GLB (for quick 3D preview in any viewer).
#include <vde/brep/modeling.h>
#include <vde/brep/step_export.h>
#include <vde/foundation/io_gltf.h>
#include <vde/core/aabb.h>
#include <iostream>
#include <iomanip>
using namespace vde::brep;
using namespace vde::foundation;
using namespace vde::core;
// ═══════════════════════════════════════════════════════════════════════
// Main — B-Rep Fabrication
// ═══════════════════════════════════════════════════════════════════════
int main() {
std::cout << std::fixed << std::setprecision(3);
std::cout << "╔══════════════════════════════════╗\n"
<< "║ B-Rep Fabrication ║\n"
<< "╚══════════════════════════════════╝\n\n";
// ── Step 1: Base solid box ───────────────────────────────────────
//
// External dimensions: 100 × 50 × 30 mm (typical enclosure part)
double w = 100.0, h = 50.0, d = 30.0;
auto part = make_box(w, h, d);
AABB3D bb_raw = part.bounds();
std::cout << "Step 1: make_box(" << w << ", " << h << ", " << d << ")\n"
<< " volume: " << w * h * d << " mm³ (raw)\n"
<< " bbox: (" << bb_raw.min().x() << ", " << bb_raw.min().y()
<< ", " << bb_raw.min().z() << ") → ("
<< bb_raw.max().x() << ", " << bb_raw.max().y()
<< ", " << bb_raw.max().z() << ")\n";
// ── Step 2: Shell to a thin-walled enclosure ─────────────────────
//
// face_id = -1 → closed shell (no openings, hollow interior)
// thickness = 2.0 mm → typical for injection-moulded / 3D-printed parts
const double wall_thickness = 2.0;
part = shell(part, -1, wall_thickness);
AABB3D bb_shell = part.bounds();
std::cout << "\nStep 2: shell(face_id=-1, thickness=" << wall_thickness << ")\n"
<< " faces: " << part.num_faces() << "\n"
<< " edges: " << part.num_edges() << "\n"
<< " bbox: (" << bb_shell.min().x() << ", " << bb_shell.min().y()
<< ", " << bb_shell.min().z() << ") → ("
<< bb_shell.max().x() << ", " << bb_shell.max().y()
<< ", " << bb_shell.max().z() << ")\n";
// ── Step 3: Export to STEP for CAM ────────────────────────────────
//
// AP214 format is the standard exchange format for CNC machining,
// 5-axis milling, sheet-metal bending, and coordinate measurement.
std::cout << "\nStep 3: Export STEP (AP214)\n";
const char* step_path = "output_fab.stp";
export_step_file(step_path, {part});
// Show the raw STEP header for verification
std::string step_str = export_step({part});
// Find the end of the header section
auto header_end = step_str.find("FILE_SCHEMA");
if (header_end != std::string::npos) {
header_end = step_str.find("ENDSEC;", header_end);
}
size_t preview_len = std::min(header_end + 6, step_str.size());
if (preview_len > 0 && preview_len < step_str.size()) {
std::cout << "" << step_path << " ("
<< step_str.size() << " chars)\n";
std::cout << " Header excerpt:\n"
<< step_str.substr(0, preview_len) << "\n ...\n";
} else {
std::cout << "" << step_path << " ("
<< step_str.size() << " chars)\n";
}
// ── Step 4: Export to GLB for 3D preview ─────────────────────────
std::cout << "\nStep 4: Export GLB for visualization\n";
const char* glb_path = "output_fab.glb";
const int tess_res = 32; // segments per curved edge
if (write_brep_gltf(glb_path, part, tess_res)) {
std::cout << "" << glb_path << " (tessellation level "
<< tess_res << ")\n";
std::cout << " Open in: gltf-viewer.donmccurdy.com, blender, three.js editor\n";
} else {
std::cerr << " ✗ Failed to write " << glb_path << "\n";
return 1;
}
// ── Summary ──────────────────────────────────────────────────────
std::cout << "\n╔══════════════════════════════════════════╗\n"
<< "║ Export Summary ║\n"
<< "╠══════════════════════════════════════════╣\n"
<< "║ B-Rep → STEP (CAM/CNC) ✓ ║\n"
<< "║ B-Rep → GLB (Preview) ✓ ║\n"
<< "╚══════════════════════════════════════════╝\n";
std::cout << "\nDone.\n";
return 0;
}