mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 22:04:56 +00:00
fix: replace torus shapes with proper cylinder-based geometry
The torus primitive was creating "donut" shapes that looked unrealistic. Fixed 7 parts by replacing torus with layered cylinders: - flywheel: Now shows proper disc with bolt holes, no ring gear torus - first-gear through fifth-gear: Tiered cylinders with splined hub - release-bearing: Proper cylindrical bearing stack Added torus detection to validate-geometry.ts: - DONUT SHAPE: Warns when torus tubeR > 15% of body radius - DOMINANT TORUS: Warns when torus radius close to body size All 16 gearbox parts now pass validation with scores 84-162. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -34,9 +34,12 @@
|
||||
{ "type": "circle", "r": 8, "fill": "#555" }
|
||||
],
|
||||
"geometry3d": [
|
||||
{ "type": "cylinder", "r": 22, "height": 10, "fill": "#666" },
|
||||
{ "type": "cylinder", "r": 16, "height": 6, "offsetZ": 2, "fill": "#777" },
|
||||
{ "type": "cylinder", "r": 14, "height": 10, "subtract": true },
|
||||
{ "type": "torus", "r": 20, "tubeR": 2, "offsetZ": 4, "fill": "#555" }
|
||||
{ "type": "cylinder", "r": 24, "height": 10, "fill": "#606570" },
|
||||
{ "type": "cylinder", "r": 22, "height": 8, "offsetY": 1, "fill": "#707580" },
|
||||
{ "type": "cylinder", "r": 16, "height": 5, "fill": "#808590" },
|
||||
{ "type": "cylinder", "r": 15, "height": 14, "fill": "#555560" },
|
||||
{ "type": "cylinder", "r": 13, "height": 16, "subtract": true },
|
||||
{ "type": "box", "width": 3, "height": 16, "depth": 28, "subtract": true },
|
||||
{ "type": "box", "width": 28, "height": 16, "depth": 3, "subtract": true }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -33,9 +33,12 @@
|
||||
{ "type": "circle", "r": 16, "fill": "#555" }
|
||||
],
|
||||
"geometry3d": [
|
||||
{ "type": "cylinder", "r": 38, "height": 18, "fill": "#666" },
|
||||
{ "type": "cylinder", "r": 32, "height": 14, "offsetZ": 2, "fill": "#777" },
|
||||
{ "type": "cylinder", "r": 16, "height": 18, "subtract": true },
|
||||
{ "type": "torus", "r": 36, "tubeR": 2, "offsetZ": 8, "fill": "#555" }
|
||||
{ "type": "cylinder", "r": 40, "height": 18, "fill": "#606570" },
|
||||
{ "type": "cylinder", "r": 38, "height": 16, "offsetY": 1, "fill": "#707580" },
|
||||
{ "type": "cylinder", "r": 32, "height": 12, "fill": "#808590" },
|
||||
{ "type": "cylinder", "r": 18, "height": 22, "fill": "#555560" },
|
||||
{ "type": "cylinder", "r": 16, "height": 24, "subtract": true },
|
||||
{ "type": "box", "width": 4, "height": 24, "depth": 34, "subtract": true },
|
||||
{ "type": "box", "width": 34, "height": 24, "depth": 4, "subtract": true }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -41,9 +41,16 @@
|
||||
{ "type": "text", "content": "DMF", "offsetY": 3, "fill": "#888", "fontSize": 10 }
|
||||
],
|
||||
"geometry3d": [
|
||||
{ "type": "cylinder", "r": 55, "height": 25, "fill": "#555" },
|
||||
{ "type": "cylinder", "r": 50, "height": 20, "offsetZ": 2.5, "fill": "#666" },
|
||||
{ "type": "cylinder", "r": 12, "height": 25, "subtract": true },
|
||||
{ "type": "torus", "r": 53, "tubeR": 3, "offsetZ": 10, "fill": "#444" }
|
||||
{ "type": "cylinder", "r": 58, "height": 8, "fill": "#505560" },
|
||||
{ "type": "cylinder", "r": 55, "height": 25, "fill": "#606570" },
|
||||
{ "type": "cylinder", "r": 50, "height": 20, "offsetY": 2.5, "fill": "#707580" },
|
||||
{ "type": "cylinder", "r": 25, "height": 30, "fill": "#555560" },
|
||||
{ "type": "cylinder", "r": 15, "height": 35, "subtract": true },
|
||||
{ "type": "cylinder", "r": 5, "height": 30, "offsetX": 35, "subtract": true },
|
||||
{ "type": "cylinder", "r": 5, "height": 30, "offsetX": -35, "subtract": true },
|
||||
{ "type": "cylinder", "r": 5, "height": 30, "offsetY": 35, "subtract": true },
|
||||
{ "type": "cylinder", "r": 5, "height": 30, "offsetY": -35, "subtract": true },
|
||||
{ "type": "cylinder", "r": 5, "height": 30, "offsetX": 25, "offsetY": 25, "subtract": true },
|
||||
{ "type": "cylinder", "r": 5, "height": 30, "offsetX": -25, "offsetY": -25, "subtract": true }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -31,9 +31,12 @@
|
||||
{ "type": "circle", "r": 10, "fill": "#555" }
|
||||
],
|
||||
"geometry3d": [
|
||||
{ "type": "cylinder", "r": 26, "height": 12, "fill": "#666" },
|
||||
{ "type": "cylinder", "r": 20, "height": 8, "offsetZ": 2, "fill": "#777" },
|
||||
{ "type": "cylinder", "r": 16, "height": 12, "subtract": true },
|
||||
{ "type": "torus", "r": 24, "tubeR": 2, "offsetZ": 5, "fill": "#555" }
|
||||
{ "type": "cylinder", "r": 28, "height": 12, "fill": "#606570" },
|
||||
{ "type": "cylinder", "r": 26, "height": 10, "offsetY": 1, "fill": "#707580" },
|
||||
{ "type": "cylinder", "r": 20, "height": 6, "fill": "#808590" },
|
||||
{ "type": "cylinder", "r": 18, "height": 16, "fill": "#555560" },
|
||||
{ "type": "cylinder", "r": 16, "height": 18, "subtract": true },
|
||||
{ "type": "box", "width": 4, "height": 18, "depth": 34, "subtract": true },
|
||||
{ "type": "box", "width": 34, "height": 18, "depth": 4, "subtract": true }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -31,9 +31,10 @@
|
||||
{ "type": "circle", "r": 10, "fill": "#2a2a2a" }
|
||||
],
|
||||
"geometry3d": [
|
||||
{ "type": "cylinder", "r": 22, "height": 18, "fill": "#444" },
|
||||
{ "type": "cylinder", "r": 18, "height": 12, "offsetZ": 3, "fill": "#555" },
|
||||
{ "type": "cylinder", "r": 12, "height": 18, "subtract": true },
|
||||
{ "type": "torus", "r": 15, "tubeR": 4, "fill": "#666" }
|
||||
{ "type": "cylinder", "r": 24, "height": 12, "fill": "#505560" },
|
||||
{ "type": "cylinder", "r": 22, "height": 18, "fill": "#606570" },
|
||||
{ "type": "cylinder", "r": 20, "height": 14, "offsetY": 2, "fill": "#707580" },
|
||||
{ "type": "cylinder", "r": 16, "height": 8, "offsetY": 7, "fill": "#808590" },
|
||||
{ "type": "cylinder", "r": 14, "height": 20, "subtract": true }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -31,9 +31,12 @@
|
||||
{ "type": "circle", "r": 14, "fill": "#555" }
|
||||
],
|
||||
"geometry3d": [
|
||||
{ "type": "cylinder", "r": 34, "height": 16, "fill": "#666" },
|
||||
{ "type": "cylinder", "r": 28, "height": 12, "offsetZ": 2, "fill": "#777" },
|
||||
{ "type": "cylinder", "r": 16, "height": 16, "subtract": true },
|
||||
{ "type": "torus", "r": 32, "tubeR": 2, "offsetZ": 7, "fill": "#555" }
|
||||
{ "type": "cylinder", "r": 36, "height": 16, "fill": "#606570" },
|
||||
{ "type": "cylinder", "r": 34, "height": 14, "offsetY": 1, "fill": "#707580" },
|
||||
{ "type": "cylinder", "r": 28, "height": 10, "fill": "#808590" },
|
||||
{ "type": "cylinder", "r": 18, "height": 20, "fill": "#555560" },
|
||||
{ "type": "cylinder", "r": 16, "height": 22, "subtract": true },
|
||||
{ "type": "box", "width": 4, "height": 22, "depth": 34, "subtract": true },
|
||||
{ "type": "box", "width": 34, "height": 22, "depth": 4, "subtract": true }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -31,9 +31,12 @@
|
||||
{ "type": "circle", "r": 12, "fill": "#555" }
|
||||
],
|
||||
"geometry3d": [
|
||||
{ "type": "cylinder", "r": 30, "height": 14, "fill": "#666" },
|
||||
{ "type": "cylinder", "r": 24, "height": 10, "offsetZ": 2, "fill": "#777" },
|
||||
{ "type": "cylinder", "r": 16, "height": 14, "subtract": true },
|
||||
{ "type": "torus", "r": 28, "tubeR": 2, "offsetZ": 6, "fill": "#555" }
|
||||
{ "type": "cylinder", "r": 32, "height": 14, "fill": "#606570" },
|
||||
{ "type": "cylinder", "r": 30, "height": 12, "offsetY": 1, "fill": "#707580" },
|
||||
{ "type": "cylinder", "r": 24, "height": 8, "fill": "#808590" },
|
||||
{ "type": "cylinder", "r": 18, "height": 18, "fill": "#555560" },
|
||||
{ "type": "cylinder", "r": 16, "height": 20, "subtract": true },
|
||||
{ "type": "box", "width": 4, "height": 20, "depth": 34, "subtract": true },
|
||||
{ "type": "box", "width": 34, "height": 20, "depth": 4, "subtract": true }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -206,6 +206,32 @@ function detectBogusPatterns(geoms: Geometry3D[], errors: string[], warnings: st
|
||||
warnings.push(`Shape [${i}] has very thin dimension (${minDim}mm) - may be invisible`)
|
||||
}
|
||||
})
|
||||
|
||||
// Pattern 9: Dominant torus (donut shape overwhelms part)
|
||||
// A torus with tubeR > 10% of main body radius makes the part look like a donut
|
||||
const torusShapes = geoms.filter(g => g.type === 'torus' && !g.subtract)
|
||||
if (torusShapes.length > 0 && unionShapes.length > 0) {
|
||||
const mainBody = unionShapes[0]
|
||||
const mainDims = getShapeDimensions(mainBody)
|
||||
const mainRadius = Math.max(...mainDims) / 2
|
||||
|
||||
torusShapes.forEach((torus) => {
|
||||
const tubeR = torus.tubeR || 0
|
||||
const torusR = torus.r || 0
|
||||
|
||||
// Warning if torus tube is thick relative to main body
|
||||
if (tubeR > mainRadius * 0.15) {
|
||||
const idx = geoms.indexOf(torus)
|
||||
warnings.push(`DONUT SHAPE: Torus [${idx}] has thick tube (${tubeR}mm) relative to body (${mainRadius}mm radius) - part will look like a donut`)
|
||||
}
|
||||
|
||||
// Warning if torus radius is close to or larger than main body
|
||||
if (torusR > mainRadius * 0.9) {
|
||||
const idx = geoms.indexOf(torus)
|
||||
warnings.push(`DOMINANT TORUS: Torus [${idx}] radius (${torusR}mm) dominates body (${mainRadius}mm) - consider using cylinder rings instead`)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function getShapeBounds(geom: Geometry3D): { maxDim: number } {
|
||||
|
||||
Reference in New Issue
Block a user