$npx -y skills add rawwerks/VibeCAD --skill model-compareCompare 3D CAD models using boolean operations (IoU, Dice, precision/recall). Use when evaluating generated models against gold references, diffing CAD revisions, or computing similarity metrics for ML training. Triggers on: model diff, compare models, IoU, intersection over unio
| 1 | # 3D Model Comparison Tool |
| 2 | |
| 3 | Compare CAD models using boolean operations to compute similarity metrics like IoU, Dice, precision, and recall. Useful for: |
| 4 | |
| 5 | - Evaluating ML-generated models against gold references |
| 6 | - Comparing revisions of CAD designs |
| 7 | - Computing metrics for training 3D generative models |
| 8 | - Visualizing geometric differences |
| 9 | |
| 10 | ## Quick Start |
| 11 | |
| 12 | ```bash |
| 13 | # Compare two STEP files |
| 14 | uvx --from build123d python scripts/model_diff.py reference.step generated.step |
| 15 | |
| 16 | # JSON output for training pipelines |
| 17 | uvx --from build123d python scripts/model_diff.py ref.step gen.step --json --no-export |
| 18 | |
| 19 | # Demo mode (no files needed) |
| 20 | uvx --from build123d python scripts/model_diff.py --demo |
| 21 | ``` |
| 22 | |
| 23 | ## Supported Formats |
| 24 | |
| 25 | | Format | Extension | Notes | |
| 26 | |--------|-----------|-------| |
| 27 | | STEP | `.step`, `.stp` | Recommended - full CAD fidelity | |
| 28 | | BREP | `.brep` | OpenCASCADE native format | |
| 29 | | STL | `.stl` | Mesh format - may have boolean issues | |
| 30 | |
| 31 | ## Output Metrics |
| 32 | |
| 33 | ### Primary Metrics (for ML training) |
| 34 | |
| 35 | | Metric | Range | Description | |
| 36 | |--------|-------|-------------| |
| 37 | | **IoU** (Jaccard) | 0-1 | `|A∩B| / |A∪B|` - standard similarity | |
| 38 | | **Dice** (F1) | 0-1 | `2|A∩B| / (|A|+|B|)` - more sensitive to small overlaps | |
| 39 | | **Precision** | 0-1 | `|A∩B| / |B|` - how much of generated is correct | |
| 40 | | **Recall** | 0-1 | `|A∩B| / |A|` - how much of reference was captured | |
| 41 | |
| 42 | ### Diagnostic Metrics |
| 43 | |
| 44 | | Metric | Description | |
| 45 | |--------|-------------| |
| 46 | | `volume_ratio` | B/A volume ratio (1.0 = same size) | |
| 47 | | `center_offset` | Distance between centers of mass | |
| 48 | | `bbox_iou` | Bounding box IoU (coarse alignment) | |
| 49 | | `size_ratio_x/y/z` | Per-axis scale comparison | |
| 50 | | `surface_ratio` | Surface area comparison | |
| 51 | |
| 52 | ### Interpretation |
| 53 | |
| 54 | The tool provides automatic interpretation: |
| 55 | - **Over-generating**: Low precision, high extra geometry |
| 56 | - **Under-generating**: Low recall, missing geometry |
| 57 | - **Size issues**: Volume ratio far from 1.0 |
| 58 | - **Position issues**: Large center offset |
| 59 | |
| 60 | ## CLI Options |
| 61 | |
| 62 | ``` |
| 63 | usage: model_diff.py [-h] [-o OUTPUT_DIR] [--json] [--no-export] [--demo] |
| 64 | [reference] [generated] |
| 65 | |
| 66 | positional arguments: |
| 67 | reference Reference/gold model file (STEP, BREP, or STL) |
| 68 | generated Generated/predicted model file to compare |
| 69 | |
| 70 | options: |
| 71 | -o, --output-dir Output directory for GLB files (default: .) |
| 72 | --json Output only JSON metrics (for pipelines) |
| 73 | --no-export Skip exporting GLB visualization files |
| 74 | --demo Run with built-in demo models |
| 75 | ``` |
| 76 | |
| 77 | ## Output Files |
| 78 | |
| 79 | When `--no-export` is not set, produces GLB files for visualization: |
| 80 | |
| 81 | | File | Description | |
| 82 | |------|-------------| |
| 83 | | `diff_reference.glb` | The reference model (A) | |
| 84 | | `diff_generated.glb` | The generated model (B) | |
| 85 | | `diff_missing.glb` | Geometry in A but not B (under-generation) | |
| 86 | | `diff_extra.glb` | Geometry in B but not A (over-generation) | |
| 87 | | `diff_common.glb` | Geometry in both (correct match) | |
| 88 | |
| 89 | ## Example: Training Pipeline Integration |
| 90 | |
| 91 | ```bash |
| 92 | # Batch evaluation |
| 93 | for gen in outputs/*.step; do |
| 94 | uvx --from build123d python model_diff.py gold.step "$gen" --json --no-export |
| 95 | done | jq -s '{ |
| 96 | avg_iou: (map(.iou) | add / length), |
| 97 | avg_precision: (map(.precision) | add / length), |
| 98 | avg_recall: (map(.recall) | add / length) |
| 99 | }' |
| 100 | ``` |
| 101 | |
| 102 | ## Example: Loss Function |
| 103 | |
| 104 | ```python |
| 105 | # In your training code, use metrics for loss: |
| 106 | loss = ( |
| 107 | (1 - metrics['iou']) * 1.0 + # Primary shape match |
| 108 | abs(1 - metrics['volume_ratio']) * 0.5 + # Scale accuracy |
| 109 | metrics['center_offset'] * 0.1 # Position accuracy |
| 110 | ) |
| 111 | ``` |
| 112 | |
| 113 | ## How It Works |
| 114 | |
| 115 | The tool uses boolean operations from OpenCASCADE (via build123d): |
| 116 | |
| 117 | ``` |
| 118 | Missing = Reference - Generated (A - B) |
| 119 | Extra = Generated - Reference (B - A) |
| 120 | Common = Reference & Generated (A ∩ B) |
| 121 | Union = Reference + Generated (A ∪ B) |
| 122 | |
| 123 | IoU = volume(Common) / volume(Union) |
| 124 | Dice = 2 * volume(Common) / (volume(A) + volume(B)) |
| 125 | Precision = volume(Common) / volume(B) |
| 126 | Recall = volume(Common) / volume(A) |
| 127 | ``` |
| 128 | |
| 129 | ## Sample Output |
| 130 | |
| 131 | ``` |
| 132 | ================================================================= |
| 133 | 3D MODEL COMPARISON REPORT |
| 134 | Reference (A) vs Generated (B) |
| 135 | ================================================================= |
| 136 | |
| 137 | ──────────────────────────── VOLUMES ──────────────────────────── |
| 138 | Reference (A): 51,433.629 |
| 139 | Generated (B): 45,904.426 |
| 140 | Intersection (A∩B): 42,292.031 |
| 141 | Missing (A-B): 9,141.598 (17.8% of A) |
| 142 | Extra (B-A): 3,612.395 (7.9% of B) |
| 143 | |
| 144 | ──────────────────────── PRIMARY METRICS ─────────────── |