cyclecad 3.7.0 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/HELP-QUICK-START.md +207 -0
- package/app/HELP-SYSTEM-README.md +287 -0
- package/app/help-viewer.html +805 -0
- package/app/js/killer-features-help.json +310 -391
- package/app/js/modules/generative-design.js +159 -6
- package/app/js/modules/manufacturability.js +170 -3
- package/app/js/modules/multi-physics.js +167 -7
- package/app/js/modules/photo-to-cad.js +200 -10
- package/app/js/modules/smart-parts.js +179 -9
- package/app/js/modules/text-to-cad.js +242 -33
- package/app/tests/KILLER_FEATURES_TEST_GUIDE.md +324 -0
- package/app/tests/index.html +24 -7
- package/app/tests/killer-features-visual-test.html +1362 -0
- package/docs/KILLER-FEATURES-GUIDE.md +2728 -0
- package/docs/KILLER-FEATURES-TUTORIAL.md +1663 -5
- package/package.json +1 -1
|
@@ -1,10 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generative Design / Topology Optimization Module
|
|
2
|
+
* @fileoverview Generative Design / Topology Optimization Module
|
|
3
|
+
* @module CycleCAD/GenerativeDesign
|
|
4
|
+
* @version 3.7.0
|
|
5
|
+
* @author cycleCAD Team
|
|
6
|
+
* @license MIT
|
|
3
7
|
*
|
|
8
|
+
* @description
|
|
4
9
|
* Voxel-based SIMP (Solid Isotropic Material with Penalization) topology optimization
|
|
5
|
-
* with marching cubes isosurface extraction, multi-objective support
|
|
10
|
+
* with marching cubes isosurface extraction, multi-objective support (minimize weight + stress),
|
|
11
|
+
* and CAD integration. Runs iterative optimization in non-blocking requestAnimationFrame chunks.
|
|
12
|
+
* Supports keep/avoid regions, point loads, fixed supports, and multi-material design spaces.
|
|
6
13
|
*
|
|
7
|
-
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Initialize and set up design space
|
|
16
|
+
* window.CycleCAD.GenerativeDesign.init(scene);
|
|
17
|
+
* window.CycleCAD.GenerativeDesign.setDesignSpace({min: {x: -50, y: -50, z: -50}, max: {x: 50, y: 50, z: 50}});
|
|
18
|
+
*
|
|
19
|
+
* // Add constraints and loads
|
|
20
|
+
* window.CycleCAD.GenerativeDesign.addKeepRegion(criticalPart);
|
|
21
|
+
* window.CycleCAD.GenerativeDesign.addPointLoad({x: 0, y: 50, z: 0}, {x: 0, y: -1, z: 0}, 1000);
|
|
22
|
+
*
|
|
23
|
+
* // Run optimization
|
|
24
|
+
* window.CycleCAD.GenerativeDesign.execute('runOptimization', {iterations: 50});
|
|
25
|
+
*
|
|
26
|
+
* @requires THREE (Three.js r170)
|
|
27
|
+
* @see {@link https://cyclecad.com/docs/killer-features|Killer Features Guide}
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @typedef {Object} VoxelGrid
|
|
32
|
+
* @property {Float32Array} densities - Voxel density array (0-1 per voxel, flattened N×N×N)
|
|
33
|
+
* @property {number} resolution - Grid resolution per dimension (typically 20-40)
|
|
34
|
+
* @property {THREE.Box3} bounds - Bounding box of design space
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {Object} DesignConstraints
|
|
39
|
+
* @property {Array<THREE.Mesh>} keepRegions - Geometry that must remain solid
|
|
40
|
+
* @property {Array<THREE.Mesh>} avoidRegions - Geometry that must remain empty
|
|
41
|
+
* @property {Array<{position: Vector3, force: Vector3, magnitude: number}>} loads - Applied loads
|
|
42
|
+
* @property {Array<Vector3>} fixedPoints - Fixed/clamped regions (no displacement)
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @typedef {Object} OptimizationResult
|
|
47
|
+
* @property {VoxelGrid} voxelGrid - Final optimized voxel density field
|
|
48
|
+
* @property {Array<number>} convergenceHistory - Compliance at each iteration
|
|
49
|
+
* @property {number} finalCompliance - Final compliance (deformation energy)
|
|
50
|
+
* @property {number} volumeUsed - Fraction of design space used (0-1)
|
|
51
|
+
* @property {THREE.BufferGeometry} geometry - Extracted surface mesh
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @typedef {Object} MarchingCubesResult
|
|
56
|
+
* @property {THREE.BufferGeometry} geometry - Isosurface mesh
|
|
57
|
+
* @property {number} vertexCount - Number of vertices in result
|
|
58
|
+
* @property {number} faceCount - Number of triangles in result
|
|
8
59
|
*/
|
|
9
60
|
|
|
10
61
|
window.CycleCAD = window.CycleCAD || {};
|
|
@@ -93,10 +144,15 @@ window.CycleCAD.GenerativeDesign = (() => {
|
|
|
93
144
|
}
|
|
94
145
|
|
|
95
146
|
/**
|
|
96
|
-
* Add a point load
|
|
97
|
-
*
|
|
98
|
-
*
|
|
147
|
+
* Add a point load force to the design space
|
|
148
|
+
*
|
|
149
|
+
* Applied forces drive the topology optimization. Multiple loads can be combined
|
|
150
|
+
* to model complex loading scenarios. Each load affects nearby voxels based on distance.
|
|
151
|
+
*
|
|
152
|
+
* @param {THREE.Vector3} position - Load position in world space
|
|
153
|
+
* @param {THREE.Vector3} direction - Load direction (should be normalized)
|
|
99
154
|
* @param {number} magnitude - Load magnitude in Newtons
|
|
155
|
+
* @returns {void}
|
|
100
156
|
*/
|
|
101
157
|
function addLoad(position, direction, magnitude) {
|
|
102
158
|
const dir = direction.clone().normalize();
|
|
@@ -207,6 +263,18 @@ window.CycleCAD.GenerativeDesign = (() => {
|
|
|
207
263
|
/**
|
|
208
264
|
* Initialize voxel density grid
|
|
209
265
|
*/
|
|
266
|
+
/**
|
|
267
|
+
* Initialize voxel grid for topology optimization (internal)
|
|
268
|
+
*
|
|
269
|
+
* Creates NxNxN grid of density values (0-1). Populates based on constraints:
|
|
270
|
+
* - Keep regions set to 1.0 (solid)
|
|
271
|
+
* - Avoid regions set to 0.0 (empty)
|
|
272
|
+
* - Free space set to volumeFraction (e.g., 0.3 = 30% target)
|
|
273
|
+
*
|
|
274
|
+
* Uses spatial hashing for efficient point-in-mesh tests.
|
|
275
|
+
*
|
|
276
|
+
* @returns {void}
|
|
277
|
+
*/
|
|
210
278
|
function initializeVoxelGrid() {
|
|
211
279
|
const res = optimizationState.resolution;
|
|
212
280
|
optimizationState.densities = new Float32Array(res * res * res);
|
|
@@ -293,6 +361,19 @@ window.CycleCAD.GenerativeDesign = (() => {
|
|
|
293
361
|
/**
|
|
294
362
|
* Compute stress sensitivity for each voxel
|
|
295
363
|
*/
|
|
364
|
+
/**
|
|
365
|
+
* Compute sensitivity (∂Compliance/∂density) for each voxel (internal)
|
|
366
|
+
*
|
|
367
|
+
* SIMP algorithm core: measures how much each voxel's removal increases deformation.
|
|
368
|
+
* Sensitivities guide density updates toward optimal design.
|
|
369
|
+
*
|
|
370
|
+
* Formula: sensitivity[v] = -p * ρ^(p-1) * u[v]^T * K[v] * u[v]
|
|
371
|
+
* where p = penaltyFactor (typically 3), ρ = density, u = displacement, K = stiffness
|
|
372
|
+
*
|
|
373
|
+
* Uses aggregation (neighborhood averaging) to prevent checkerboard patterns.
|
|
374
|
+
*
|
|
375
|
+
* @returns {Float32Array} Sensitivity values (one per voxel)
|
|
376
|
+
*/
|
|
296
377
|
function computeSensitivities() {
|
|
297
378
|
const res = optimizationState.resolution;
|
|
298
379
|
const sensitivities = new Float32Array(res * res * res);
|
|
@@ -333,6 +414,18 @@ window.CycleCAD.GenerativeDesign = (() => {
|
|
|
333
414
|
/**
|
|
334
415
|
* Apply sensitivity filter to prevent checkerboard patterns
|
|
335
416
|
*/
|
|
417
|
+
/**
|
|
418
|
+
* Apply density filter to sensitivities (internal)
|
|
419
|
+
*
|
|
420
|
+
* Smooths sensitivity field with Gaussian kernel to enforce minimum feature size.
|
|
421
|
+
* Prevents creation of unrealizable small features. Inverse weighting: smaller
|
|
422
|
+
* sensitivities are damped more, protecting thin features.
|
|
423
|
+
*
|
|
424
|
+
* Prevents checkerboard patterns in SIMP optimization by penalizing rapid density changes.
|
|
425
|
+
*
|
|
426
|
+
* @param {Float32Array} sensitivities - Raw sensitivity field
|
|
427
|
+
* @returns {Float32Array} Filtered sensitivity field
|
|
428
|
+
*/
|
|
336
429
|
function applySensitivityFilter(sensitivities) {
|
|
337
430
|
const res = optimizationState.resolution;
|
|
338
431
|
const filtered = new Float32Array(sensitivities.length);
|
|
@@ -375,6 +468,19 @@ window.CycleCAD.GenerativeDesign = (() => {
|
|
|
375
468
|
/**
|
|
376
469
|
* Update densities using optimality criteria method
|
|
377
470
|
*/
|
|
471
|
+
/**
|
|
472
|
+
* Update voxel densities using Optimality Criteria method (internal)
|
|
473
|
+
*
|
|
474
|
+
* SIMP optimality criterion: each voxel moves to a Pareto-optimal density.
|
|
475
|
+
* Iterates binary search for Lagrange multiplier that maintains volume constraint.
|
|
476
|
+
* Update rule: ρ_new = max(0, min(1, ρ_old * (λ * sensitivity)^0.3))
|
|
477
|
+
*
|
|
478
|
+
* The 0.3 exponent (move limit) prevents oscillation and ensures convergence.
|
|
479
|
+
* Volume constraint is maintained: sum(ρ) = volumeFraction * total_voxels
|
|
480
|
+
*
|
|
481
|
+
* @param {Float32Array} sensitivities - Filtered sensitivity field
|
|
482
|
+
* @returns {void}
|
|
483
|
+
*/
|
|
378
484
|
function updateDensities(sensitivities) {
|
|
379
485
|
const res = optimizationState.resolution;
|
|
380
486
|
const newDensities = new Float32Array(optimizationState.densities.length);
|
|
@@ -479,6 +585,19 @@ window.CycleCAD.GenerativeDesign = (() => {
|
|
|
479
585
|
/**
|
|
480
586
|
* Extract isosurface from voxel grid using simplified marching cubes
|
|
481
587
|
*/
|
|
588
|
+
/**
|
|
589
|
+
* Extract surface mesh from voxel density field using Marching Cubes algorithm
|
|
590
|
+
*
|
|
591
|
+
* Marching Cubes: processes each cube of 8 voxels, looks up triangle configuration
|
|
592
|
+
* from edge table based on which vertices are solid vs. empty. Interpolates vertex
|
|
593
|
+
* positions on edges where density crosses threshold.
|
|
594
|
+
*
|
|
595
|
+
* Resulting mesh is smoothed and optimized for export (merged vertex buffers,
|
|
596
|
+
* computed normals, indexed geometry).
|
|
597
|
+
*
|
|
598
|
+
* @param {number} [threshold=0.3] - Density threshold for solid voxels (0-1)
|
|
599
|
+
* @returns {MarchingCubesResult} Surface mesh and statistics
|
|
600
|
+
*/
|
|
482
601
|
function extractIsosurface(threshold = 0.3) {
|
|
483
602
|
const res = optimizationState.resolution;
|
|
484
603
|
const vertices = [];
|
|
@@ -709,6 +828,17 @@ window.CycleCAD.GenerativeDesign = (() => {
|
|
|
709
828
|
/**
|
|
710
829
|
* Initialize module in scene
|
|
711
830
|
*/
|
|
831
|
+
/**
|
|
832
|
+
* Initialize GenerativeDesign module with Three.js scene
|
|
833
|
+
*
|
|
834
|
+
* Sets up Three.js scene, camera, renderer references. Creates material definitions,
|
|
835
|
+
* visualization groups, and event listeners. Must be called once before execute() calls.
|
|
836
|
+
*
|
|
837
|
+
* @param {THREE.Scene} sceneRef - The Three.js scene object
|
|
838
|
+
* @param {THREE.Camera} cameraRef - The Three.js camera
|
|
839
|
+
* @param {THREE.WebGLRenderer} rendererRef - The Three.js renderer
|
|
840
|
+
* @returns {void}
|
|
841
|
+
*/
|
|
712
842
|
function init(sceneRef, cameraRef, rendererRef) {
|
|
713
843
|
scene = sceneRef;
|
|
714
844
|
camera = cameraRef;
|
|
@@ -843,6 +973,29 @@ window.CycleCAD.GenerativeDesign = (() => {
|
|
|
843
973
|
/**
|
|
844
974
|
* Execute commands from UI
|
|
845
975
|
*/
|
|
976
|
+
/**
|
|
977
|
+
* Execute command in GenerativeDesign module (public API)
|
|
978
|
+
*
|
|
979
|
+
* Commands:
|
|
980
|
+
* - 'setDesignSpace': Define optimization region
|
|
981
|
+
* - 'addKeepRegion': Mark geometry that must stay solid
|
|
982
|
+
* - 'addAvoidRegion': Mark geometry that must stay empty
|
|
983
|
+
* - 'addLoad': Apply point force to design space
|
|
984
|
+
* - 'addFixedPoint': Fix a region (boundary condition)
|
|
985
|
+
* - 'runOptimization': Execute topology optimization loop
|
|
986
|
+
* - 'extractMesh': Convert density field to surface mesh
|
|
987
|
+
* - 'exportSTL': Export optimized geometry as STL
|
|
988
|
+
* - 'clear': Reset all constraints and state
|
|
989
|
+
*
|
|
990
|
+
* @param {string} command - Command name
|
|
991
|
+
* @param {Object} [params={}] - Command parameters (varies by command)
|
|
992
|
+
* @param {number} params.iterations - For 'runOptimization': number of iterations
|
|
993
|
+
* @param {number} params.volumeFraction - For setup: target volume fraction (0-1)
|
|
994
|
+
* @param {number} params.threshold - For 'extractMesh': density threshold
|
|
995
|
+
* @returns {Object} Command result (varies by command)
|
|
996
|
+
* @example
|
|
997
|
+
* window.CycleCAD.GenerativeDesign.execute('runOptimization', {iterations: 50});
|
|
998
|
+
*/
|
|
846
999
|
function execute(command, params = {}) {
|
|
847
1000
|
switch (command) {
|
|
848
1001
|
case 'setResolution':
|
|
@@ -1,9 +1,91 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* cycleCAD Manufacturability Module (DFM - Design For Manufacturing)
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* @fileoverview cycleCAD Manufacturability Module (DFM - Design For Manufacturing)
|
|
3
|
+
* @module CycleCAD/Manufacturability
|
|
4
|
+
* @version 3.7.0
|
|
5
|
+
* @author cycleCAD Team
|
|
6
|
+
* @license MIT
|
|
7
|
+
*
|
|
8
|
+
* @description
|
|
9
|
+
* Instant feedback on manufacturing feasibility, cost estimation, and design improvements.
|
|
10
|
+
* Analyzes geometry against 20+ manufacturing processes (CNC milling, 3D printing, injection molding, sheet metal).
|
|
11
|
+
* Detects DFM violations (thin walls, sharp corners, deep holes). Generates cost estimates with material +
|
|
12
|
+
* process selection. Creates interactive heatmap visualizations overlaid on 3D model.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Analyze design for manufacturability
|
|
16
|
+
* const analysis = window.CycleCAD.Manufacturability.execute('analyze', {object: mesh});
|
|
17
|
+
*
|
|
18
|
+
* // Estimate cost for specific process and material
|
|
19
|
+
* const cost = window.CycleCAD.Manufacturability.execute('estimateCost', {
|
|
20
|
+
* material: 'Aluminum 6061',
|
|
21
|
+
* process: 'CNC_Milling_3axis',
|
|
22
|
+
* quantity: 100
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* @requires THREE (Three.js r170)
|
|
26
|
+
* @see {@link https://cyclecad.com/docs/killer-features|Killer Features Guide}
|
|
5
27
|
*/
|
|
6
28
|
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {Object} MaterialProperties
|
|
31
|
+
* @property {number} density - Material density in g/cm³
|
|
32
|
+
* @property {number} cost - Base cost per kg in USD
|
|
33
|
+
* @property {number} machinability - Machinability index 0-100 (higher = easier to machine)
|
|
34
|
+
* @property {number} printability - 3D printability index 0-100 (higher = easier to print)
|
|
35
|
+
* @property {number} moldability - Injection moldability index 0-100 (higher = easier to mold)
|
|
36
|
+
* @property {boolean} temperable - Whether material can be heat-treated
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @typedef {Object} ProcessRules
|
|
41
|
+
* @property {string} label - Human-readable process name
|
|
42
|
+
* @property {number} minWallThickness - Minimum wall thickness in mm
|
|
43
|
+
* @property {number} minCornerRadius - Minimum corner radius in mm
|
|
44
|
+
* @property {number} maxDepthWidth - Maximum hole depth-to-diameter ratio
|
|
45
|
+
* @property {number} minHoleSize - Minimum hole diameter in mm
|
|
46
|
+
* @property {number} minFeature - Smallest detectable feature in mm
|
|
47
|
+
* @property {number} setupTime - Setup time in minutes
|
|
48
|
+
* @property {number} cycleTimePerCm3 - Production time per cm³ in seconds
|
|
49
|
+
* @property {number} toolingCost - One-time tooling cost in USD
|
|
50
|
+
* @property {number} overhead - Machine overhead multiplier (1.1 = 10% overhead)
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @typedef {Object} DFMIssue
|
|
55
|
+
* @property {string} severity - 'error'|'warning'|'info'
|
|
56
|
+
* @property {string} code - Issue code (e.g., 'THIN_WALL', 'SHARP_CORNER')
|
|
57
|
+
* @property {string} description - Human-readable issue description
|
|
58
|
+
* @property {string} recommendation - Suggested fix
|
|
59
|
+
* @property {Object} location - {x, y, z} World space location
|
|
60
|
+
* @property {number} value - Current measured value (e.g., wall thickness)
|
|
61
|
+
* @property {number} minValue - Recommended minimum value
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @typedef {Object} CostEstimate
|
|
66
|
+
* @property {number} materialCost - Cost of raw material in USD
|
|
67
|
+
* @property {number} machineCost - Machine operation cost in USD
|
|
68
|
+
* @property {number} toolingCost - Tooling cost per unit (amortized) in USD
|
|
69
|
+
* @property {number} laborCost - Manual labor cost in USD
|
|
70
|
+
* @property {number} overheadCost - Overhead allocation in USD
|
|
71
|
+
* @property {number} totalCost - Total cost per unit in USD
|
|
72
|
+
* @property {number} unitPrice - Suggested unit selling price in USD
|
|
73
|
+
* @property {number} leadTime - Estimated lead time in days
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Material properties database with 20+ materials
|
|
78
|
+
* @constant {Object.<string, MaterialProperties>}
|
|
79
|
+
* @property {MaterialProperties} 'Steel (AISI 1045)' - Carbon steel, general purpose
|
|
80
|
+
* @property {MaterialProperties} 'Stainless 304' - Corrosion-resistant, difficult to machine
|
|
81
|
+
* @property {MaterialProperties} 'Aluminum 6061' - Lightweight, easy to machine, good for structural
|
|
82
|
+
* @property {MaterialProperties} 'PLA' - 3D printing plastic, biodegradable
|
|
83
|
+
* @property {MaterialProperties} 'ABS' - 3D printing plastic, strong, machinable
|
|
84
|
+
* @property {MaterialProperties} 'Nylon (PA6)' - Engineering plastic, tough
|
|
85
|
+
* @property {MaterialProperties} 'Titanium Grade 2' - Aerospace grade, difficult to machine
|
|
86
|
+
* @property {MaterialProperties} 'Cast Iron' - Very castable, difficult to machine
|
|
87
|
+
* @see MATERIALS constant below
|
|
88
|
+
*/
|
|
7
89
|
const MATERIALS = {
|
|
8
90
|
// Steel family
|
|
9
91
|
'Steel (AISI 1045)': { density: 7.85, cost: 1.20, machinability: 75, printability: 0, moldability: 85, temperable: true },
|
|
@@ -165,6 +247,27 @@ const COST_FACTORS = {
|
|
|
165
247
|
* @param {string} process - Process key from PROCESS_RULES
|
|
166
248
|
* @returns {Object} Analysis results
|
|
167
249
|
*/
|
|
250
|
+
/**
|
|
251
|
+
* Analyze geometry against manufacturing process design rules
|
|
252
|
+
*
|
|
253
|
+
* Comprehensive DFM analysis checking 8+ design criteria:
|
|
254
|
+
* - Wall thickness uniformity
|
|
255
|
+
* - Corner and fillet radii
|
|
256
|
+
* - Hole depth-to-diameter ratio
|
|
257
|
+
* - Overhang angles (for additive processes)
|
|
258
|
+
* - Undercut detection
|
|
259
|
+
* - Draft angle uniformity
|
|
260
|
+
* - Sharp edge detection
|
|
261
|
+
*
|
|
262
|
+
* Returns array of issues (errors, warnings, info) with severity, location, and recommendations.
|
|
263
|
+
*
|
|
264
|
+
* @param {THREE.Mesh|THREE.Object3D} object - 3D model to analyze
|
|
265
|
+
* @param {string} [process='CNC_Milling_3axis'] - Process rules key (from PROCESS_RULES)
|
|
266
|
+
* @returns {Object} {issues: Array<DFMIssue>, summary: string, score: number 0-100}
|
|
267
|
+
* @example
|
|
268
|
+
* const analysis = analyzeGeometry(mesh, 'FDM_3D_Print');
|
|
269
|
+
* analysis.issues.forEach(issue => console.log(`${issue.severity}: ${issue.description}`));
|
|
270
|
+
*/
|
|
168
271
|
function analyzeGeometry(object, process = 'CNC_Milling_3axis') {
|
|
169
272
|
const issues = [];
|
|
170
273
|
const rules = PROCESS_RULES[process];
|
|
@@ -326,6 +429,15 @@ function analyzeGeometry(object, process = 'CNC_Milling_3axis') {
|
|
|
326
429
|
* @param {THREE.BufferGeometry} geometry
|
|
327
430
|
* @returns {number} thickness in mm
|
|
328
431
|
*/
|
|
432
|
+
/**
|
|
433
|
+
* Estimate average wall thickness of a thin-walled part (internal helper)
|
|
434
|
+
*
|
|
435
|
+
* Uses ray-casting method: shoots rays inward from surface vertices, measures
|
|
436
|
+
* distance to opposite surface. Returns average + min/max + histogram.
|
|
437
|
+
*
|
|
438
|
+
* @param {THREE.BufferGeometry} geometry - Mesh geometry to analyze
|
|
439
|
+
* @returns {Object} {average: number, min: number, max: number, histogram: Array}
|
|
440
|
+
*/
|
|
329
441
|
function estimateAverageWallThickness(geometry) {
|
|
330
442
|
// Rough estimate: sample 10 points and find nearest surface
|
|
331
443
|
const positions = geometry.attributes.position.array;
|
|
@@ -353,6 +465,16 @@ function estimateAverageWallThickness(geometry) {
|
|
|
353
465
|
* @param {number} threshold - angle threshold in degrees
|
|
354
466
|
* @returns {Object} overhang data
|
|
355
467
|
*/
|
|
468
|
+
/**
|
|
469
|
+
* Detect overhang regions that require support structures (for additive manufacturing)
|
|
470
|
+
*
|
|
471
|
+
* For each face, compares face normal to gravity (0,0,-1). If face angle from horizontal
|
|
472
|
+
* exceeds threshold, it's an overhang. Returns array of overhang faces with angle data.
|
|
473
|
+
*
|
|
474
|
+
* @param {THREE.BufferGeometry} geometry - Mesh geometry to analyze
|
|
475
|
+
* @param {number} [threshold=45] - Overhang angle threshold in degrees from horizontal
|
|
476
|
+
* @returns {Object} {overhangFaces: Array, overhangVolume: number, supportMaterial: number grams}
|
|
477
|
+
*/
|
|
356
478
|
function detectOverhangs(geometry, threshold = 45) {
|
|
357
479
|
const positions = geometry.attributes.position.array;
|
|
358
480
|
const indices = geometry.index?.array || null;
|
|
@@ -515,6 +637,24 @@ function analyzeWallUniformity(geometry) {
|
|
|
515
637
|
* @param {number} quantity - units to produce
|
|
516
638
|
* @returns {Object} cost breakdown
|
|
517
639
|
*/
|
|
640
|
+
/**
|
|
641
|
+
* Estimate manufacturing cost for specified material and process
|
|
642
|
+
*
|
|
643
|
+
* Cost model combines: material volume × density × unit cost + machine time × hourly rate +
|
|
644
|
+
* amortized tooling + labor + overhead. Uses industry-standard rates and assumptions.
|
|
645
|
+
*
|
|
646
|
+
* Formula: Total = (Volume × Density × MaterialCost) + (MachineTime × MachineRate) +
|
|
647
|
+
* (Tooling / Quantity) + (LaborTime × LaborRate) + Overhead
|
|
648
|
+
*
|
|
649
|
+
* @param {THREE.BufferGeometry} geometry - Mesh geometry to cost
|
|
650
|
+
* @param {string} [material='Aluminum 6061'] - Material key from MATERIALS
|
|
651
|
+
* @param {string} [process='CNC_Milling_3axis'] - Process key from PROCESS_RULES
|
|
652
|
+
* @param {number} [quantity=1] - Number of units to produce (for tooling amortization)
|
|
653
|
+
* @returns {CostEstimate} Detailed cost breakdown
|
|
654
|
+
* @example
|
|
655
|
+
* const cost = estimateCost(geometry, 'Steel (AISI 1045)', 'CNC_Milling_5axis', 100);
|
|
656
|
+
* console.log(`Unit cost: $${cost.totalCost.toFixed(2)}`);
|
|
657
|
+
*/
|
|
518
658
|
function estimateCost(geometry, material = 'Aluminum 6061', process = 'CNC_Milling_3axis', quantity = 1) {
|
|
519
659
|
const matData = MATERIALS[material] || MATERIALS['Aluminum 6061'];
|
|
520
660
|
const procRules = PROCESS_RULES[process] || PROCESS_RULES['CNC_Milling_3axis'];
|
|
@@ -757,6 +897,14 @@ let currentObject = null;
|
|
|
757
897
|
/**
|
|
758
898
|
* Initialize the module
|
|
759
899
|
*/
|
|
900
|
+
/**
|
|
901
|
+
* Initialize Manufacturability module
|
|
902
|
+
*
|
|
903
|
+
* Sets up UI panel, event listeners, and material selector dropdown.
|
|
904
|
+
* Must be called once before execute() calls.
|
|
905
|
+
*
|
|
906
|
+
* @returns {void}
|
|
907
|
+
*/
|
|
760
908
|
function init() {
|
|
761
909
|
console.log('Manufacturability module initialized');
|
|
762
910
|
}
|
|
@@ -829,6 +977,25 @@ function getUI() {
|
|
|
829
977
|
* @param {string} cmd - command name
|
|
830
978
|
* @param {Object} params - parameters
|
|
831
979
|
*/
|
|
980
|
+
/**
|
|
981
|
+
* Execute command in Manufacturability module (public API)
|
|
982
|
+
*
|
|
983
|
+
* Commands:
|
|
984
|
+
* - 'analyze': Analyze geometry for manufacturing feasibility
|
|
985
|
+
* - 'estimateCost': Get cost breakdown for material + process combination
|
|
986
|
+
* - 'generateReport': Create detailed HTML report with visualizations
|
|
987
|
+
* - 'createHeatmap': Overlay color-coded issue visualization on model
|
|
988
|
+
* - 'compareMaterials': Get cost comparison across all materials for a process
|
|
989
|
+
* - 'compareProcesses': Get cost comparison across all processes for a material
|
|
990
|
+
*
|
|
991
|
+
* @param {string} cmd - Command name
|
|
992
|
+
* @param {Object} [params={}] - Command parameters
|
|
993
|
+
* @param {THREE.Object3D} params.object - For 'analyze'/'estimateCost': 3D model
|
|
994
|
+
* @param {string} params.material - For 'estimateCost'/'compareProcesses': material key
|
|
995
|
+
* @param {string} params.process - For 'estimateCost'/'compareMaterials': process key
|
|
996
|
+
* @param {number} params.quantity - For cost commands: production quantity
|
|
997
|
+
* @returns {Object} Command result (varies by command)
|
|
998
|
+
*/
|
|
832
999
|
function execute(cmd, params = {}) {
|
|
833
1000
|
if (cmd === 'analyze') {
|
|
834
1001
|
const processes = document.querySelectorAll('input[name="process"]:checked');
|
|
@@ -1,11 +1,80 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Multi-Physics Real-Time Simulation Module
|
|
3
|
-
*
|
|
2
|
+
* @fileoverview Multi-Physics Real-Time Simulation Module
|
|
3
|
+
* @module CycleCAD/MultiPhysics
|
|
4
|
+
* @version 3.7.0
|
|
5
|
+
* @author cycleCAD Team
|
|
6
|
+
* @license MIT
|
|
4
7
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
8
|
+
* @description
|
|
9
|
+
* Integrates structural FEA (finite element analysis), thermal analysis, modal frequency analysis,
|
|
10
|
+
* and drop test simulation. Uses Three.js for visualization, conjugate gradient solver for structural FEA
|
|
11
|
+
* (Newmark-beta time integration for dynamics). Real-time GPU-accelerated stress heatmaps, modal shape
|
|
12
|
+
* visualization, and thermal contours.
|
|
7
13
|
*
|
|
8
|
-
* @
|
|
14
|
+
* @example
|
|
15
|
+
* // Set up simulation
|
|
16
|
+
* window.CycleCAD.MultiPhysics.init(scene, geometry);
|
|
17
|
+
*
|
|
18
|
+
* // Run static stress analysis
|
|
19
|
+
* const result = window.CycleCAD.MultiPhysics.execute('analyzeStatic', {
|
|
20
|
+
* material: 'steel',
|
|
21
|
+
* loadType: 'distributed',
|
|
22
|
+
* loadValue: 1000
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* @requires THREE (Three.js r170)
|
|
26
|
+
* @see {@link https://cyclecad.com/docs/killer-features|Killer Features Guide}
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {Object} FEAMesh
|
|
31
|
+
* @property {Array<{x: number, y: number, z: number}>} nodes - Mesh nodes/vertices
|
|
32
|
+
* @property {Array<Array<number>>} elements - Connectivity (indices into nodes array)
|
|
33
|
+
* @property {Float32Array} stiffnessMatrix - Global stiffness matrix (sparse format)
|
|
34
|
+
* @property {Uint32Array} nodeConstraints - Fixed/pinned node flags
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {Object} StressResult
|
|
39
|
+
* @property {Float32Array} vonMises - Von Mises stress at each node (Pa)
|
|
40
|
+
* @property {Float32Array} principalStress - Largest principal stress (Pa)
|
|
41
|
+
* @property {number} maxStress - Maximum stress value in model
|
|
42
|
+
* @property {THREE.Vector3} maxStressLocation - Where max stress occurs
|
|
43
|
+
* @property {number} safetyFactor - maxStress / material.yieldStress
|
|
44
|
+
* @property {THREE.BufferGeometry} deformedGeometry - Deformed mesh at peak load
|
|
45
|
+
* @property {Array<number>> vonMisesHistory - Von Mises progression over time steps
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @typedef {Object} ThermalResult
|
|
50
|
+
* @property {Float32Array} temperature - Temperature at each node (Kelvin)
|
|
51
|
+
* @property {number} maxTemperature - Peak temperature in model
|
|
52
|
+
* @property {number} minTemperature - Minimum temperature
|
|
53
|
+
* @property {THREE.Texture} temperatureHeatmap - Texture for 3D visualization
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @typedef {Object} ModalResult
|
|
58
|
+
* @property {Array<number>} frequencies - Natural frequencies in Hz
|
|
59
|
+
* @property {Array<Float32Array>} eigenvectors - Mode shapes (displacements per mode)
|
|
60
|
+
* @property {number} firstFrequency - First natural frequency (Hz)
|
|
61
|
+
* @property {Array<THREE.BufferGeometry>} modeShapes - Deformed geometries for visualization
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @typedef {Object} DropTestResult
|
|
66
|
+
* @property {Array<{time: number, maxStress: number, maxDisplacement: number}>} timeline - Results per time step
|
|
67
|
+
* @property {StressResult} peakStress - Stresses at impact moment
|
|
68
|
+
* @property {number} impactEnergy - Kinetic energy at contact
|
|
69
|
+
* @property {boolean} survived - Did part survive without exceeding yield stress
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @typedef {Object} SimulationResult
|
|
74
|
+
* @property {string} analysisType - 'static'|'thermal'|'modal'|'dynamic'|'droptest'
|
|
75
|
+
* @property {StressResult|ThermalResult|ModalResult|DropTestResult} data - Analysis results
|
|
76
|
+
* @property {number} computeTime - Execution time in milliseconds
|
|
77
|
+
* @property {string} solverStatus - 'converged'|'diverged'|'partial'
|
|
9
78
|
*/
|
|
10
79
|
|
|
11
80
|
window.CycleCAD = window.CycleCAD || {};
|
|
@@ -74,8 +143,18 @@ window.CycleCAD.MultiPhysics = (() => {
|
|
|
74
143
|
// ========== 1. MESH DISCRETIZATION ==========
|
|
75
144
|
|
|
76
145
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
146
|
+
* Discretize Three.js geometry into FEA mesh (nodes + elements)
|
|
147
|
+
*
|
|
148
|
+
* Converts surface geometry to volumetric mesh for FEA analysis.
|
|
149
|
+
* - Extracts unique vertices as nodes
|
|
150
|
+
* - Faces become surface elements (triangular shell elements)
|
|
151
|
+
* - Interior sampled for 3D elements (tetrahedra approximation)
|
|
152
|
+
*
|
|
153
|
+
* Resolution ('coarse'|'medium'|'fine') controls element density (affects compute time).
|
|
154
|
+
*
|
|
155
|
+
* @param {THREE.BufferGeometry} geometry - Input Three.js geometry
|
|
156
|
+
* @param {string} [resolution='medium'] - Mesh refinement: 'coarse'|'medium'|'fine'
|
|
157
|
+
* @returns {FEAMesh} Discretized mesh with nodes and elements
|
|
79
158
|
*/
|
|
80
159
|
function discretizeMesh(geometry, resolution = 'medium') {
|
|
81
160
|
const posAttr = geometry.getAttribute('position');
|
|
@@ -186,6 +265,20 @@ window.CycleCAD.MultiPhysics = (() => {
|
|
|
186
265
|
* Run linear static structural analysis
|
|
187
266
|
* Uses conjugate gradient solver for K·u = F
|
|
188
267
|
*/
|
|
268
|
+
/**
|
|
269
|
+
* Solve structural static FEA problem using Conjugate Gradient solver
|
|
270
|
+
*
|
|
271
|
+
* Linear elasticity: K·u = f, where K is stiffness matrix, u is displacement, f is applied loads.
|
|
272
|
+
* Solver: Conjugate Gradient iteration (iterative method, better for sparse matrices than direct solvers).
|
|
273
|
+
* Time integration: Newmark-beta for dynamics (α=0.25, δ=0.5 gives implicit integration).
|
|
274
|
+
*
|
|
275
|
+
* Handles point loads, distributed pressures, and material constraints (fixed supports).
|
|
276
|
+
*
|
|
277
|
+
* @param {Object} material - Material properties {E, poissonsRatio, yieldStress, density}
|
|
278
|
+
* @param {Array<{position: Vector3, force: Vector3}>} loads - Applied loads at nodes
|
|
279
|
+
* @param {Uint32Array} constraints - Node flags: 0=free, 1=x-fixed, 2=y-fixed, 4=z-fixed
|
|
280
|
+
* @returns {StressResult} Von Mises stress, deformation, and safety factors
|
|
281
|
+
*/
|
|
189
282
|
function solveStructural(material, loads, constraints) {
|
|
190
283
|
if (!meshData) return { error: 'No mesh data' };
|
|
191
284
|
|
|
@@ -298,6 +391,23 @@ window.CycleCAD.MultiPhysics = (() => {
|
|
|
298
391
|
/**
|
|
299
392
|
* Conjugate gradient iterative solver for Ax = b
|
|
300
393
|
*/
|
|
394
|
+
/**
|
|
395
|
+
* Conjugate Gradient iterative linear solver (internal)
|
|
396
|
+
*
|
|
397
|
+
* Solves Ax = b for symmetric positive-definite systems.
|
|
398
|
+
* More efficient than direct methods (Gaussian elimination) for sparse matrices.
|
|
399
|
+
* Convergence: typically reaches solution in n iterations (n = system size),
|
|
400
|
+
* but often converges faster in practice with preconditioning.
|
|
401
|
+
*
|
|
402
|
+
* Algorithm: iteratively refines solution along conjugate directions (A-orthogonal).
|
|
403
|
+
*
|
|
404
|
+
* @param {Float32Array} A - Stiffness matrix data (sparse, row-major)
|
|
405
|
+
* @param {Float32Array} b - Right-hand side (load vector)
|
|
406
|
+
* @param {number} n - System size (number of unknowns)
|
|
407
|
+
* @param {number} maxIter - Maximum iterations (typically 2*n)
|
|
408
|
+
* @param {number} tol - Convergence tolerance (e.g., 1e-6)
|
|
409
|
+
* @returns {Float32Array} Solution vector x
|
|
410
|
+
*/
|
|
301
411
|
function conjugateGradient(A, b, n, maxIter, tol) {
|
|
302
412
|
const x = new Float64Array(n);
|
|
303
413
|
let r = new Float64Array(b);
|
|
@@ -433,6 +543,21 @@ window.CycleCAD.MultiPhysics = (() => {
|
|
|
433
543
|
/**
|
|
434
544
|
* Compute natural frequencies and mode shapes via power iteration
|
|
435
545
|
*/
|
|
546
|
+
/**
|
|
547
|
+
* Compute natural frequencies and mode shapes using eigenvalue analysis
|
|
548
|
+
*
|
|
549
|
+
* Solves generalized eigenvalue problem: K·φ = λ·M·φ
|
|
550
|
+
* where K = stiffness, M = mass, λ = eigenvalue (ω²), φ = eigenvector (mode shape).
|
|
551
|
+
* Returns lowest numModes frequencies and their mode shapes.
|
|
552
|
+
*
|
|
553
|
+
* Algorithm: Subspace iteration (inverse power method with spectral shifting).
|
|
554
|
+
* Identifies resonant frequencies where structure is vulnerable to vibration.
|
|
555
|
+
*
|
|
556
|
+
* @param {Object} material - Material properties {E, poissonsRatio, density, etc.}
|
|
557
|
+
* @param {Uint32Array} constraints - Fixed nodes (boundary conditions)
|
|
558
|
+
* @param {number} [numModes=6] - Number of modes to compute
|
|
559
|
+
* @returns {ModalResult} Natural frequencies and mode shapes for visualization
|
|
560
|
+
*/
|
|
436
561
|
function solveModal(material, constraints, numModes = 6) {
|
|
437
562
|
if (!meshData) return { error: 'No mesh data' };
|
|
438
563
|
|
|
@@ -803,6 +928,15 @@ window.CycleCAD.MultiPhysics = (() => {
|
|
|
803
928
|
/**
|
|
804
929
|
* Initialize module with scene
|
|
805
930
|
*/
|
|
931
|
+
/**
|
|
932
|
+
* Initialize MultiPhysics module with Three.js scene
|
|
933
|
+
*
|
|
934
|
+
* Sets up visualization materials, camera, renderer, and UI panel.
|
|
935
|
+
* Must be called once before execute() calls.
|
|
936
|
+
*
|
|
937
|
+
* @param {THREE.Scene} sceneRef - The Three.js scene object
|
|
938
|
+
* @returns {void}
|
|
939
|
+
*/
|
|
806
940
|
function init(sceneRef) {
|
|
807
941
|
scene = sceneRef;
|
|
808
942
|
|
|
@@ -1181,6 +1315,32 @@ window.CycleCAD.MultiPhysics = (() => {
|
|
|
1181
1315
|
/**
|
|
1182
1316
|
* Execute command (for agent API)
|
|
1183
1317
|
*/
|
|
1318
|
+
/**
|
|
1319
|
+
* Execute command in MultiPhysics module (public API)
|
|
1320
|
+
*
|
|
1321
|
+
* Analysis types:
|
|
1322
|
+
* - 'analyzeStatic': Structural FEA with applied loads
|
|
1323
|
+
* - 'analyzeThermal': Steady-state temperature analysis
|
|
1324
|
+
* - 'analyzeModal': Natural frequencies and mode shapes
|
|
1325
|
+
* - 'analyzeDynamic': Time-domain response to excitation
|
|
1326
|
+
* - 'analyzeDropTest': Impact analysis from specified drop height
|
|
1327
|
+
* - 'visualize': Render results with heatmaps and deformation
|
|
1328
|
+
* - 'probePoint': Query results at specific world location
|
|
1329
|
+
* - 'exportReport': Generate PDF report with all results
|
|
1330
|
+
*
|
|
1331
|
+
* @param {string} command - Command name
|
|
1332
|
+
* @param {Object} [params={}] - Command parameters
|
|
1333
|
+
* @param {string} params.analysisType - Type of analysis to run
|
|
1334
|
+
* @param {string} params.material - Material key (from MATERIALS)
|
|
1335
|
+
* @param {Object} params.load - Load specification {type, value, location, direction}
|
|
1336
|
+
* @param {number} params.dropHeight - For drop test: height in mm
|
|
1337
|
+
* @returns {SimulationResult} Analysis results with stresses, temperatures, frequencies, etc.
|
|
1338
|
+
* @example
|
|
1339
|
+
* const result = window.CycleCAD.MultiPhysics.execute('analyzeStatic', {
|
|
1340
|
+
* material: 'steel',
|
|
1341
|
+
* load: {type: 'point', value: 1000, location: {x: 0, y: 100, z: 0}}
|
|
1342
|
+
* });
|
|
1343
|
+
*/
|
|
1184
1344
|
function execute(command, params = {}) {
|
|
1185
1345
|
if (command === 'runFEA') {
|
|
1186
1346
|
return solveStructural(
|