cyclecad 3.7.0 → 3.9.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/index.html +96 -0
- package/app/js/killer-features-help.json +310 -391
- package/app/js/modules/auto-assembly.js +1146 -0
- package/app/js/modules/digital-twin.js +1225 -0
- package/app/js/modules/engineering-notebook.js +1505 -0
- package/app/js/modules/generative-design.js +159 -6
- package/app/js/modules/machine-control.js +1270 -0
- package/app/js/modules/manufacturability.js +170 -3
- package/app/js/modules/multi-physics.js +167 -7
- package/app/js/modules/parametric-from-example.js +900 -0
- package/app/js/modules/photo-to-cad.js +200 -10
- package/app/js/modules/smart-assembly.js +1667 -0
- 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,15 +1,72 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Smart Parts Library with AI Search
|
|
2
|
+
* @fileoverview Smart Parts Library with AI Search
|
|
3
|
+
* @module CycleCAD/SmartParts
|
|
4
|
+
* @version 3.7.0
|
|
5
|
+
* @author cycleCAD Team
|
|
6
|
+
* @license MIT
|
|
3
7
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
9
|
-
* - Real-time pricing estimation
|
|
8
|
+
* @description
|
|
9
|
+
* Unified smart parts catalog with 200+ standard mechanical parts. Features AI-powered
|
|
10
|
+
* natural language search (fuzzy matching), 3D parametric geometry generation for all parts,
|
|
11
|
+
* supplier part number cross-reference (McMaster-Carr, MISUMI, Digi-Key), BOM management and export,
|
|
12
|
+
* real-time pricing from multiple suppliers, and smart consolidation (combines duplicate parts).
|
|
10
13
|
*
|
|
11
|
-
* @
|
|
12
|
-
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Search for parts using natural language
|
|
16
|
+
* const results = window.CycleCAD.SmartParts.execute('search', {query: 'm3 socket head cap screw'});
|
|
17
|
+
*
|
|
18
|
+
* // Add part to BOM
|
|
19
|
+
* window.CycleCAD.SmartParts.execute('addToBOM', {partId: 'fastener_shcs_m3_8', quantity: 10});
|
|
20
|
+
*
|
|
21
|
+
* // Generate 3D geometry for part
|
|
22
|
+
* const geometry = window.CycleCAD.SmartParts.execute('generateGeometry', {partId: 'fastener_shcs_m3_8'});
|
|
23
|
+
*
|
|
24
|
+
* @requires THREE (Three.js r170)
|
|
25
|
+
* @see {@link https://cyclecad.com/docs/killer-features|Killer Features Guide}
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @typedef {Object} CatalogPart
|
|
30
|
+
* @property {string} id - Unique part identifier
|
|
31
|
+
* @property {string} name - Human-readable part name
|
|
32
|
+
* @property {string} category - Part category (e.g., 'Fasteners', 'Bearings')
|
|
33
|
+
* @property {string} subcategory - Subcategory (e.g., 'Socket Head Cap Screws')
|
|
34
|
+
* @property {string} standard - Standard designation (e.g., 'ISO 4762', 'ANSI B18.3')
|
|
35
|
+
* @property {Object} dimensions - Parametric dimensions {dia, length, headDia, etc.}
|
|
36
|
+
* @property {string} material - Material designation
|
|
37
|
+
* @property {string} finish - Surface finish (e.g., 'Zinc Plated', 'Stainless')
|
|
38
|
+
* @property {number} weight - Weight in grams
|
|
39
|
+
* @property {Object} supplier - Supplier part numbers {mcmaster, misumi, digi, amazon}
|
|
40
|
+
* @property {Object} price - Pricing in different currencies {usd, eur, gbp}
|
|
41
|
+
* @property {Array<string>} tags - Search tags (for fuzzy matching)
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @typedef {Object} SearchResult
|
|
46
|
+
* @property {CatalogPart} part - The matched part
|
|
47
|
+
* @property {number} score - Match score 0-1 (1.0 = perfect match)
|
|
48
|
+
* @property {string} reason - Why this matched (e.g., 'tag match', 'description match')
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @typedef {Object} BOMEntry
|
|
53
|
+
* @property {string} partId - Reference to catalog part
|
|
54
|
+
* @property {CatalogPart} partData - Full part information
|
|
55
|
+
* @property {number} quantity - Number of units required
|
|
56
|
+
* @property {number} costPerUnit - Unit price in default currency
|
|
57
|
+
* @property {number} totalCost - quantity × costPerUnit
|
|
58
|
+
* @property {string} notes - User notes (e.g., "green anodized")
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @typedef {Object} SupplierInfo
|
|
63
|
+
* @property {string} supplier - Supplier name (e.g., 'McMaster', 'MISUMI')
|
|
64
|
+
* @property {string} partNumber - Supplier's part number
|
|
65
|
+
* @property {string} url - Direct link to part on supplier website
|
|
66
|
+
* @property {number} leadTime - Delivery time in days
|
|
67
|
+
* @property {number} minimumOrder - Minimum order quantity
|
|
68
|
+
* @property {number} unitPrice - Current unit price
|
|
69
|
+
* @property {number} stockLevel - Available inventory (-1 if unknown)
|
|
13
70
|
*/
|
|
14
71
|
|
|
15
72
|
window.CycleCAD = window.CycleCAD || {};
|
|
@@ -616,6 +673,15 @@ window.CycleCAD.SmartParts = (() => {
|
|
|
616
673
|
* @param {Object} dims - { dia, length, headDia, headHeight }
|
|
617
674
|
* @returns {THREE.Group}
|
|
618
675
|
*/
|
|
676
|
+
/**
|
|
677
|
+
* Generate 3D bolt/screw geometry from dimensions (internal helper)
|
|
678
|
+
*
|
|
679
|
+
* Parametric socket head cap screw geometry: cylindrical shank + hex socket head.
|
|
680
|
+
* Creates proper proportions per ISO 4762 standard. Head includes drive recess.
|
|
681
|
+
*
|
|
682
|
+
* @param {Object} dims - Bolt dimensions {dia, length, headDia, headHeight, socketSize}
|
|
683
|
+
* @returns {THREE.BufferGeometry} 3D bolt mesh
|
|
684
|
+
*/
|
|
619
685
|
function generateBolt(dims) {
|
|
620
686
|
const group = new THREE.Group();
|
|
621
687
|
|
|
@@ -963,6 +1029,15 @@ window.CycleCAD.SmartParts = (() => {
|
|
|
963
1029
|
* @param {Object} part - Part catalog entry
|
|
964
1030
|
* @returns {THREE.Group}
|
|
965
1031
|
*/
|
|
1032
|
+
/**
|
|
1033
|
+
* Dispatch parametric geometry generation for any part in catalog
|
|
1034
|
+
*
|
|
1035
|
+
* Routes to specialized generator function based on part category.
|
|
1036
|
+
* Caches geometry results for repeated access. Returns Three.js mesh ready for scene.
|
|
1037
|
+
*
|
|
1038
|
+
* @param {CatalogPart} part - Part from catalog
|
|
1039
|
+
* @returns {THREE.BufferGeometry} Generated 3D geometry
|
|
1040
|
+
*/
|
|
966
1041
|
function getPartGeometry(part) {
|
|
967
1042
|
if (geometryCache.has(part.id)) {
|
|
968
1043
|
return geometryCache.get(part.id).clone();
|
|
@@ -1022,6 +1097,15 @@ window.CycleCAD.SmartParts = (() => {
|
|
|
1022
1097
|
* @param {string} query
|
|
1023
1098
|
* @returns {string[]}
|
|
1024
1099
|
*/
|
|
1100
|
+
/**
|
|
1101
|
+
* Tokenize search query into words for matching (internal helper)
|
|
1102
|
+
*
|
|
1103
|
+
* Splits on whitespace, removes common words (stop words), converts to lowercase.
|
|
1104
|
+
* Expands abbreviations (e.g., "dia" → "diameter") before tokenization.
|
|
1105
|
+
*
|
|
1106
|
+
* @param {string} query - Natural language search query
|
|
1107
|
+
* @returns {Array<string>} Processed tokens
|
|
1108
|
+
*/
|
|
1025
1109
|
function tokenizeQuery(query) {
|
|
1026
1110
|
return query
|
|
1027
1111
|
.toLowerCase()
|
|
@@ -1036,6 +1120,17 @@ window.CycleCAD.SmartParts = (() => {
|
|
|
1036
1120
|
* @param {string} b
|
|
1037
1121
|
* @returns {number} 0-1
|
|
1038
1122
|
*/
|
|
1123
|
+
/**
|
|
1124
|
+
* Compute string similarity using Levenshtein edit distance (internal helper)
|
|
1125
|
+
*
|
|
1126
|
+
* Measures minimum edits (insert/delete/replace) needed to transform a→b.
|
|
1127
|
+
* Normalized 0-1: 1.0 = identical, 0.0 = completely different.
|
|
1128
|
+
* Used for typo tolerance in search (e.g., "dieameter" matches "diameter").
|
|
1129
|
+
*
|
|
1130
|
+
* @param {string} a - First string
|
|
1131
|
+
* @param {string} b - Second string
|
|
1132
|
+
* @returns {number} Similarity score 0-1
|
|
1133
|
+
*/
|
|
1039
1134
|
function stringSimilarity(a, b) {
|
|
1040
1135
|
a = a.toLowerCase();
|
|
1041
1136
|
b = b.toLowerCase();
|
|
@@ -1084,6 +1179,27 @@ window.CycleCAD.SmartParts = (() => {
|
|
|
1084
1179
|
* @param {Object} filters
|
|
1085
1180
|
* @returns {Array} Sorted results with scores
|
|
1086
1181
|
*/
|
|
1182
|
+
/**
|
|
1183
|
+
* Search parts catalog using natural language query with optional filters
|
|
1184
|
+
*
|
|
1185
|
+
* Implements multi-strategy fuzzy matching:
|
|
1186
|
+
* 1. Exact keyword match in tags (score 1.0)
|
|
1187
|
+
* 2. Substring match in name/description (score 0.9)
|
|
1188
|
+
* 3. Levenshtein edit distance for typo tolerance (score 0.7-0.8)
|
|
1189
|
+
* 4. Category/material filtering to narrow results
|
|
1190
|
+
*
|
|
1191
|
+
* Results sorted by score (highest first). Duplicate parts consolidated.
|
|
1192
|
+
*
|
|
1193
|
+
* @param {string} query - Natural language search query (e.g., "m3 socket head cap screw 10mm")
|
|
1194
|
+
* @param {Object} [filters={}] - Optional filters
|
|
1195
|
+
* @param {string} filters.category - Filter by category (e.g., 'Fasteners')
|
|
1196
|
+
* @param {string} filters.material - Filter by material (e.g., 'Steel')
|
|
1197
|
+
* @param {number} filters.maxPrice - Price ceiling in default currency
|
|
1198
|
+
* @returns {Array<SearchResult>} Ranked search results (best match first)
|
|
1199
|
+
* @example
|
|
1200
|
+
* const results = searchCatalog('iso 4762 m5 socket head cap screw 16mm', {material: 'Steel'});
|
|
1201
|
+
* // → [{part: {...}, score: 0.98, reason: 'tag match'}, ...]
|
|
1202
|
+
*/
|
|
1087
1203
|
function searchCatalog(query, filters = {}) {
|
|
1088
1204
|
if (!query || query.trim().length === 0) {
|
|
1089
1205
|
return Object.values(partCatalog).slice(0, 30);
|
|
@@ -1285,6 +1401,17 @@ window.CycleCAD.SmartParts = (() => {
|
|
|
1285
1401
|
* @param {Object} config - { quantity, size, material, finish }
|
|
1286
1402
|
* @returns {Object} { id, part, mesh, position }
|
|
1287
1403
|
*/
|
|
1404
|
+
/**
|
|
1405
|
+
* Insert part instance into 3D scene at specified position
|
|
1406
|
+
*
|
|
1407
|
+
* Generates geometry, creates THREE.Mesh, applies material and transform,
|
|
1408
|
+
* adds to scene. Optionally applies color, scale, and user-specified configurations.
|
|
1409
|
+
*
|
|
1410
|
+
* @param {CatalogPart} part - Part from catalog
|
|
1411
|
+
* @param {THREE.Vector3} [position] - World position for part placement
|
|
1412
|
+
* @param {Object} [config={}] - Configuration {color, scale, visible, castShadow, receiveShadow}
|
|
1413
|
+
* @returns {THREE.Mesh} Instance mesh added to scene
|
|
1414
|
+
*/
|
|
1288
1415
|
function insertPart(part, position = new THREE.Vector3(0, 0, 0), config = {}) {
|
|
1289
1416
|
const geometry = getPartGeometry(part);
|
|
1290
1417
|
const mesh = geometry.clone();
|
|
@@ -1586,6 +1713,15 @@ window.CycleCAD.SmartParts = (() => {
|
|
|
1586
1713
|
* Initialize module
|
|
1587
1714
|
* @param {THREE.Scene} sceneRef
|
|
1588
1715
|
*/
|
|
1716
|
+
/**
|
|
1717
|
+
* Initialize SmartParts module with Three.js scene
|
|
1718
|
+
*
|
|
1719
|
+
* Sets up UI panel, search bar, category filters, BOM viewer,
|
|
1720
|
+
* pricing display, and supplier links. Must be called once before execute() calls.
|
|
1721
|
+
*
|
|
1722
|
+
* @param {THREE.Scene} sceneRef - The Three.js scene for part insertion
|
|
1723
|
+
* @returns {void}
|
|
1724
|
+
*/
|
|
1589
1725
|
function init(sceneRef) {
|
|
1590
1726
|
scene = sceneRef;
|
|
1591
1727
|
console.log('[SmartParts] Initialized with', Object.keys(partCatalog).length, 'parts');
|
|
@@ -1665,6 +1801,40 @@ window.CycleCAD.SmartParts = (() => {
|
|
|
1665
1801
|
* @param {string} command
|
|
1666
1802
|
* @param {Object} params
|
|
1667
1803
|
*/
|
|
1804
|
+
/**
|
|
1805
|
+
* Execute command in SmartParts module (public API)
|
|
1806
|
+
*
|
|
1807
|
+
* Commands:
|
|
1808
|
+
* - 'search': Search parts catalog with natural language query
|
|
1809
|
+
* - 'getCatalog': Get full parts list (optionally filtered)
|
|
1810
|
+
* - 'generateGeometry': Get 3D geometry for a part
|
|
1811
|
+
* - 'insertPart': Add part instance to 3D scene
|
|
1812
|
+
* - 'addToBOM': Add part to Bill of Materials
|
|
1813
|
+
* - 'removeBOM': Remove part from BOM
|
|
1814
|
+
* - 'consolidateBOM': Merge duplicate parts in BOM
|
|
1815
|
+
* - 'exportBOM': Export BOM as CSV or Excel
|
|
1816
|
+
* - 'getSuppliersForPart': Get all supplier options for a part
|
|
1817
|
+
* - 'compareSuppliers': Compare pricing/lead time across suppliers
|
|
1818
|
+
* - 'getCategories': List all part categories
|
|
1819
|
+
* - 'getPricingHistory': Get historical pricing for a part
|
|
1820
|
+
*
|
|
1821
|
+
* @param {string} command - Command name
|
|
1822
|
+
* @param {Object} [params={}] - Command parameters (varies by command)
|
|
1823
|
+
* @param {string} params.query - For 'search': natural language query
|
|
1824
|
+
* @param {string} params.partId - For most commands: part identifier
|
|
1825
|
+
* @param {number} params.quantity - For 'addToBOM': quantity to add
|
|
1826
|
+
* @param {string} params.format - For 'exportBOM': 'csv'|'excel'|'json'
|
|
1827
|
+
* @returns {Object} Command result (varies by command)
|
|
1828
|
+
* @example
|
|
1829
|
+
* // Search for parts
|
|
1830
|
+
* const results = window.CycleCAD.SmartParts.execute('search', {query: 'm5 socket head cap screw'});
|
|
1831
|
+
*
|
|
1832
|
+
* // Add to BOM
|
|
1833
|
+
* window.CycleCAD.SmartParts.execute('addToBOM', {partId: results[0].part.id, quantity: 10});
|
|
1834
|
+
*
|
|
1835
|
+
* // Export BOM
|
|
1836
|
+
* const bomData = window.CycleCAD.SmartParts.execute('exportBOM', {format: 'excel'});
|
|
1837
|
+
*/
|
|
1668
1838
|
function execute(command, params = {}) {
|
|
1669
1839
|
switch (command) {
|
|
1670
1840
|
case 'search':
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* TextToCAD - Natural Language to 3D Geometry with Live Preview
|
|
2
|
+
* @fileoverview TextToCAD - Natural Language to 3D Geometry with Live Preview
|
|
3
|
+
* @module CycleCAD/TextToCAD
|
|
4
|
+
* @version 3.7.0
|
|
5
|
+
* @author cycleCAD Team
|
|
6
|
+
* @license MIT
|
|
7
|
+
*
|
|
8
|
+
* @description
|
|
3
9
|
* Converts English descriptions to parametric 3D CAD models in real-time.
|
|
10
|
+
* Features NLP parser for 50+ shape types, live ghost preview, multi-step builder with state awareness,
|
|
11
|
+
* Gemini Flash API integration with local fallback, 3D dimension annotations, undo/redo, variant generation,
|
|
12
|
+
* and production-ready error handling.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Initialize the module
|
|
16
|
+
* window.CycleCAD.TextToCAD.init(scene, renderer);
|
|
4
17
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
18
|
+
* // Parse natural language and generate geometry
|
|
19
|
+
* const result = window.CycleCAD.TextToCAD.execute('parseDescription', 'create a cylinder 50mm diameter 80mm tall');
|
|
7
20
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* - Live preview with ghost geometry as you type
|
|
11
|
-
* - Multi-step builder with state awareness
|
|
12
|
-
* - Gemini Flash API integration (with local fallback)
|
|
13
|
-
* - 3D dimension annotations
|
|
14
|
-
* - Undo/redo per step
|
|
15
|
-
* - Variant generation (3 alternatives)
|
|
16
|
-
* - Production-ready error handling
|
|
21
|
+
* @requires THREE (Three.js r170)
|
|
22
|
+
* @see {@link https://cyclecad.com/docs/killer-features|Killer Features Guide}
|
|
17
23
|
*/
|
|
18
24
|
|
|
19
25
|
(function initTextToCAD() {
|
|
@@ -35,7 +41,58 @@
|
|
|
35
41
|
lastAction: null
|
|
36
42
|
};
|
|
37
43
|
|
|
44
|
+
// ========== TYPEDEFS ==========
|
|
45
|
+
/**
|
|
46
|
+
* @typedef {Object} ParseResult
|
|
47
|
+
* @property {string} intent - User intent: 'create', 'add', 'modify', 'combine', 'pattern', 'export'
|
|
48
|
+
* @property {string} primaryShape - Primary shape type (e.g., 'cylinder', 'box')
|
|
49
|
+
* @property {Object} dimensions - Extracted numeric dimensions in mm
|
|
50
|
+
* @property {Array} features - Array of feature objects (holes, fillets, etc.)
|
|
51
|
+
* @property {Object} relationships - Spatial relationships between components
|
|
52
|
+
* @property {Object} parameters - Computed parameters for shape generation
|
|
53
|
+
* @property {number} confidence - Confidence score 0-1
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @typedef {Object} ShapeVocab
|
|
58
|
+
* @property {Array<string>} alias - Alternative names for the shape
|
|
59
|
+
* @property {Array<string>} params - Parameter names this shape accepts
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @typedef {Object} FeatureSpec
|
|
64
|
+
* @property {string} type - Feature type: 'hole', 'fillet', 'chamfer', 'pattern', 'counterbore', etc.
|
|
65
|
+
* @property {Object} params - Feature parameters
|
|
66
|
+
* @property {number} diameter - For hole features
|
|
67
|
+
* @property {number} depth - For counterbore/countersink
|
|
68
|
+
* @property {string} direction - For patterns: 'radial' or 'rectangular'
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @typedef {Object} BuildStep
|
|
73
|
+
* @property {number} index - Step number
|
|
74
|
+
* @property {string} description - User's natural language description
|
|
75
|
+
* @property {ParseResult} parsed - Parsed specification
|
|
76
|
+
* @property {THREE.Object3D} geometry - Generated 3D geometry
|
|
77
|
+
* @property {number} timestamp - Creation time
|
|
78
|
+
*/
|
|
79
|
+
|
|
38
80
|
// ========== SHAPE VOCABULARY & PATTERNS ==========
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Vocabulary of recognized shapes with aliases and parameter names
|
|
84
|
+
* @constant {Object.<string, ShapeVocab>}
|
|
85
|
+
* @property {ShapeVocab} cylinder - Cylindrical shape (aliases: cyl, tube, pipe)
|
|
86
|
+
* @property {ShapeVocab} box - Rectangular block (aliases: cube, block, rectangular)
|
|
87
|
+
* @property {ShapeVocab} sphere - Spherical shape (aliases: ball, round)
|
|
88
|
+
* @property {ShapeVocab} cone - Conical shape (aliases: taper)
|
|
89
|
+
* @property {ShapeVocab} torus - Toroidal shape (aliases: donut, ring, washer)
|
|
90
|
+
* @property {ShapeVocab} gear - Gear teeth (aliases: cog, sprocket)
|
|
91
|
+
* @property {ShapeVocab} flange - Cylindrical collar (aliases: rim, collar)
|
|
92
|
+
* @property {ShapeVocab} shaft - Rotating shaft (aliases: axle, spindle)
|
|
93
|
+
* @property {ShapeVocab} housing - Enclosure (aliases: enclosure, case, container)
|
|
94
|
+
* @property {ShapeVocab} keyway - Key slot (aliases: key-slot)
|
|
95
|
+
*/
|
|
39
96
|
const SHAPE_VOCAB = {
|
|
40
97
|
// Basic primitives
|
|
41
98
|
cylinder: { alias: ['cyl', 'tube', 'pipe'], params: ['diameter', 'radius', 'height', 'tall'] },
|
|
@@ -94,8 +151,17 @@
|
|
|
94
151
|
|
|
95
152
|
/**
|
|
96
153
|
* Parse natural language description into structured CAD commands
|
|
97
|
-
*
|
|
98
|
-
*
|
|
154
|
+
*
|
|
155
|
+
* Performs multi-stage NLP pipeline: intent detection → shape recognition → dimension extraction →
|
|
156
|
+
* feature identification → relationship analysis → parameter computation → confidence scoring.
|
|
157
|
+
* Uses regex patterns and statistical scoring for robustness with imperfect input.
|
|
158
|
+
*
|
|
159
|
+
* @param {string} input - English description of part to create
|
|
160
|
+
* @returns {ParseResult|null} Structured geometry specification or null if unparseable
|
|
161
|
+
* @throws {Error} If input contains invalid UTF-8 or is longer than 2000 characters
|
|
162
|
+
* @example
|
|
163
|
+
* const spec = parseDescription('create cylinder 50mm diameter 80mm tall with 10mm hole');
|
|
164
|
+
* // Returns: { intent: 'create', primaryShape: 'cylinder', dimensions: {...}, features: [...], confidence: 0.92 }
|
|
99
165
|
*/
|
|
100
166
|
function parseDescription(input) {
|
|
101
167
|
if (!input || input.trim().length === 0) {
|
|
@@ -128,9 +194,17 @@
|
|
|
128
194
|
}
|
|
129
195
|
|
|
130
196
|
/**
|
|
131
|
-
* Detect user intent from input
|
|
132
|
-
*
|
|
133
|
-
*
|
|
197
|
+
* Detect user intent (action) from natural language input
|
|
198
|
+
*
|
|
199
|
+
* Maps keywords and patterns to one of 6 primary intents. Uses priority-ordered regex matching
|
|
200
|
+
* to distinguish between creation, modification, combination, and export workflows.
|
|
201
|
+
*
|
|
202
|
+
* @param {string} input - Natural language description
|
|
203
|
+
* @returns {string} Intent type: 'create'|'add'|'modify'|'combine'|'pattern'|'export'
|
|
204
|
+
* @example
|
|
205
|
+
* detectIntent('make a cylinder') // → 'create'
|
|
206
|
+
* detectIntent('add a hole') // → 'add'
|
|
207
|
+
* detectIntent('fillet the edges') // → 'modify'
|
|
134
208
|
*/
|
|
135
209
|
function detectIntent(input) {
|
|
136
210
|
const lower = input.toLowerCase();
|
|
@@ -144,9 +218,18 @@
|
|
|
144
218
|
}
|
|
145
219
|
|
|
146
220
|
/**
|
|
147
|
-
* Detect primary shape from natural language
|
|
148
|
-
*
|
|
149
|
-
*
|
|
221
|
+
* Detect primary shape type from natural language input
|
|
222
|
+
*
|
|
223
|
+
* Uses vocabulary lookup followed by heuristic fallback. Checks all registered shapes and their aliases
|
|
224
|
+
* using case-insensitive word-boundary regex matching. Maintains a ranked preference order for
|
|
225
|
+
* common shapes (cylinder > box > sphere) when multiple matches exist.
|
|
226
|
+
*
|
|
227
|
+
* @param {string} input - Natural language description
|
|
228
|
+
* @returns {string|null} Shape type (e.g., 'cylinder', 'box', 'sphere') or null if no match
|
|
229
|
+
* @example
|
|
230
|
+
* detectShape('create a cylindrical tube') // → 'cylinder'
|
|
231
|
+
* detectShape('make a round ball') // → 'sphere'
|
|
232
|
+
* detectShape('totally ambiguous text') // → null
|
|
150
233
|
*/
|
|
151
234
|
function detectShape(input) {
|
|
152
235
|
const lower = input.toLowerCase();
|
|
@@ -167,9 +250,18 @@
|
|
|
167
250
|
}
|
|
168
251
|
|
|
169
252
|
/**
|
|
170
|
-
* Extract numerical dimensions
|
|
171
|
-
*
|
|
172
|
-
*
|
|
253
|
+
* Extract numerical dimensions and convert to millimeters
|
|
254
|
+
*
|
|
255
|
+
* Multi-pass extraction: first identifies all numbers with explicit units (mm/cm/in/m) using regex patterns,
|
|
256
|
+
* then performs context-aware labeling based on dimension order (diameter → height → width → depth).
|
|
257
|
+
* Supports explicit parameter names (e.g., "diameter 50mm", "height 80mm") and implicit positional inference.
|
|
258
|
+
* Handles ambiguous units by preferring explicit labels.
|
|
259
|
+
*
|
|
260
|
+
* @param {string} input - Natural language with measurements
|
|
261
|
+
* @returns {Object} Dimensions object with keys like {diameter, height, width, depth, etc.} all in mm
|
|
262
|
+
* @example
|
|
263
|
+
* extractDimensions('cylinder 50mm dia 80 tall') // → {diameter: 50, height: 80, radius: 25}
|
|
264
|
+
* extractDimensions('2 inch width and 3cm depth') // → {width: 50.8, depth: 30}
|
|
173
265
|
*/
|
|
174
266
|
function extractDimensions(input) {
|
|
175
267
|
const dimensions = {};
|
|
@@ -229,9 +321,16 @@
|
|
|
229
321
|
}
|
|
230
322
|
|
|
231
323
|
/**
|
|
232
|
-
* Extract features from
|
|
233
|
-
*
|
|
234
|
-
*
|
|
324
|
+
* Extract manufacturing features from natural language description
|
|
325
|
+
*
|
|
326
|
+
* Identifies hole, counterbore, countersink, thread, fillet, chamfer, pattern, and slot features
|
|
327
|
+
* using regex pattern matching. Returns array of feature specs with extracted parameters.
|
|
328
|
+
*
|
|
329
|
+
* @param {string} input - Natural language description
|
|
330
|
+
* @returns {Array<FeatureSpec>} Array of feature specifications
|
|
331
|
+
* @example
|
|
332
|
+
* extractFeatures('cylinder with 10mm hole, 5mm fillet, and 4x pattern')
|
|
333
|
+
* // → [{type: 'hole', diameter: 10}, {type: 'fillet', radius: 5}, {type: 'pattern', count: 4}]
|
|
235
334
|
*/
|
|
236
335
|
function extractFeatures(input) {
|
|
237
336
|
const features = [];
|
|
@@ -399,10 +498,17 @@
|
|
|
399
498
|
}
|
|
400
499
|
|
|
401
500
|
/**
|
|
402
|
-
* Convert value to millimeters
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
*
|
|
501
|
+
* Convert measurement value to millimeters (internal utility)
|
|
502
|
+
*
|
|
503
|
+
* Handles four common unit systems: metric (mm/cm/m) and imperial (inches).
|
|
504
|
+
* Used internally by extractDimensions for consistent unit handling.
|
|
505
|
+
*
|
|
506
|
+
* @param {number} value - Numeric value in source units
|
|
507
|
+
* @param {string} unit - Unit type: 'mm'|'cm'|'inch'|'m'
|
|
508
|
+
* @returns {number} Converted value in millimeters
|
|
509
|
+
* @example
|
|
510
|
+
* convertToMM(2, 'inch') // → 50.8
|
|
511
|
+
* convertToMM(5, 'cm') // → 50
|
|
406
512
|
*/
|
|
407
513
|
function convertToMM(value, unit) {
|
|
408
514
|
switch (unit) {
|
|
@@ -417,9 +523,18 @@
|
|
|
417
523
|
// ========== GEOMETRY GENERATION (~300 lines) ==========
|
|
418
524
|
|
|
419
525
|
/**
|
|
420
|
-
* Generate THREE.js geometry from parsed specification
|
|
421
|
-
*
|
|
422
|
-
*
|
|
526
|
+
* Generate THREE.js 3D geometry from parsed CAD specification
|
|
527
|
+
*
|
|
528
|
+
* Dispatcher function that creates appropriate Three.js primitives based on shape type.
|
|
529
|
+
* Applies features (holes, fillets, patterns) to base geometry. Returns composite group
|
|
530
|
+
* containing all geometry and feature visualizations.
|
|
531
|
+
*
|
|
532
|
+
* @param {ParseResult} spec - Parsed CAD specification with shape and parameters
|
|
533
|
+
* @returns {THREE.Group|null} Composite 3D geometry with all features applied, or null if invalid
|
|
534
|
+
* @example
|
|
535
|
+
* const spec = parseDescription('cylinder 50mm diameter 80mm tall with 10mm hole');
|
|
536
|
+
* const geometry = generateGeometry(spec);
|
|
537
|
+
* scene.add(geometry);
|
|
423
538
|
*/
|
|
424
539
|
function generateGeometry(spec) {
|
|
425
540
|
if (!spec || !spec.primaryShape) {
|
|
@@ -542,6 +657,17 @@
|
|
|
542
657
|
* @param {Object} params
|
|
543
658
|
* @returns {THREE.BufferGeometry}
|
|
544
659
|
*/
|
|
660
|
+
/**
|
|
661
|
+
* Create parametric spur gear geometry
|
|
662
|
+
*
|
|
663
|
+
* Generates involute gear profile with user-specified teeth count and module.
|
|
664
|
+
* Implements involute curve construction for smooth tooth engagement.
|
|
665
|
+
*
|
|
666
|
+
* @param {Object} params - Gear parameters
|
|
667
|
+
* @param {number} params.teeth - Number of teeth
|
|
668
|
+
* @param {number} params.module - Module (mm/tooth) - standard values: 0.5, 1.0, 1.5, 2.0, 3.0, 4.0
|
|
669
|
+
* @returns {THREE.BufferGeometry} Gear geometry
|
|
670
|
+
*/
|
|
545
671
|
function createGearGeometry(params) {
|
|
546
672
|
const teeth = params.teeth || 24;
|
|
547
673
|
const module = params.module || 2;
|
|
@@ -584,6 +710,18 @@
|
|
|
584
710
|
* @param {Object} params
|
|
585
711
|
* @returns {THREE.BufferGeometry}
|
|
586
712
|
*/
|
|
713
|
+
/**
|
|
714
|
+
* Create parametric angle bracket (L-shaped) geometry
|
|
715
|
+
*
|
|
716
|
+
* Constructs two perpendicular flange sheets with optional boss features.
|
|
717
|
+
* Common in mechanical assemblies for structural support.
|
|
718
|
+
*
|
|
719
|
+
* @param {Object} params - Bracket parameters
|
|
720
|
+
* @param {number} params.width - Horizontal width (mm)
|
|
721
|
+
* @param {number} params.height - Vertical height (mm)
|
|
722
|
+
* @param {number} params.thickness - Material thickness (mm)
|
|
723
|
+
* @returns {THREE.BufferGeometry} Bracket geometry
|
|
724
|
+
*/
|
|
587
725
|
function createBracketGeometry(params) {
|
|
588
726
|
const w = params.width || 60;
|
|
589
727
|
const h = params.height || 100;
|
|
@@ -723,6 +861,16 @@
|
|
|
723
861
|
* Update live preview as user types
|
|
724
862
|
* @param {string} input
|
|
725
863
|
*/
|
|
864
|
+
/**
|
|
865
|
+
* Update live preview geometry as user types (debounced)
|
|
866
|
+
*
|
|
867
|
+
* Implements 500ms debounce to avoid excessive parsing/rendering. Creates "ghost" geometry
|
|
868
|
+
* with semi-transparent material to show real-time feedback without committing to history.
|
|
869
|
+
* Updates confidence score display and dimension annotations.
|
|
870
|
+
*
|
|
871
|
+
* @param {string} input - Current user input text
|
|
872
|
+
* @returns {void}
|
|
873
|
+
*/
|
|
726
874
|
function updateLivePreview(input) {
|
|
727
875
|
// Clear existing debounce timer
|
|
728
876
|
if (state.parseDebounceTimer) {
|
|
@@ -771,6 +919,14 @@
|
|
|
771
919
|
/**
|
|
772
920
|
* Commit preview to actual geometry
|
|
773
921
|
*/
|
|
922
|
+
/**
|
|
923
|
+
* Commit current preview to history and make permanent
|
|
924
|
+
*
|
|
925
|
+
* Replaces ghost geometry with opaque final geometry, adds to feature tree,
|
|
926
|
+
* pushes to step history, enables undo/redo. Triggers event listeners.
|
|
927
|
+
*
|
|
928
|
+
* @returns {void}
|
|
929
|
+
*/
|
|
774
930
|
function commitPreview() {
|
|
775
931
|
if (!state.previewGeometry) return;
|
|
776
932
|
|
|
@@ -815,6 +971,14 @@
|
|
|
815
971
|
/**
|
|
816
972
|
* Undo to previous step
|
|
817
973
|
*/
|
|
974
|
+
/**
|
|
975
|
+
* Undo last step in feature history
|
|
976
|
+
*
|
|
977
|
+
* Moves currentStepIndex backward, restores previous geometry state,
|
|
978
|
+
* updates UI and 3D view. Does nothing if already at first step.
|
|
979
|
+
*
|
|
980
|
+
* @returns {BuildStep|null} Previous step or null if at beginning
|
|
981
|
+
*/
|
|
818
982
|
function undoStep() {
|
|
819
983
|
if (state.currentStepIndex > 0) {
|
|
820
984
|
state.currentStepIndex--;
|
|
@@ -837,6 +1001,14 @@
|
|
|
837
1001
|
/**
|
|
838
1002
|
* Redo to next step
|
|
839
1003
|
*/
|
|
1004
|
+
/**
|
|
1005
|
+
* Redo last undone step in feature history
|
|
1006
|
+
*
|
|
1007
|
+
* Moves currentStepIndex forward, restores next geometry state,
|
|
1008
|
+
* updates UI and 3D view. Does nothing if already at latest step.
|
|
1009
|
+
*
|
|
1010
|
+
* @returns {BuildStep|null} Next step or null if at end
|
|
1011
|
+
*/
|
|
840
1012
|
function redoStep() {
|
|
841
1013
|
if (state.currentStepIndex < state.steps.length - 1) {
|
|
842
1014
|
state.currentStepIndex++;
|
|
@@ -1273,6 +1445,17 @@
|
|
|
1273
1445
|
* @param {THREE.Scene} scene
|
|
1274
1446
|
* @param {Object} renderer
|
|
1275
1447
|
*/
|
|
1448
|
+
/**
|
|
1449
|
+
* Initialize TextToCAD module with Three.js scene and renderer
|
|
1450
|
+
*
|
|
1451
|
+
* Sets up event listeners, UI panel, material definitions, and camera controls.
|
|
1452
|
+
* Must be called once before any execute() calls. Safe to call multiple times.
|
|
1453
|
+
*
|
|
1454
|
+
* @param {THREE.Scene} scene - The Three.js scene object
|
|
1455
|
+
* @param {THREE.WebGLRenderer} renderer - The Three.js renderer for viewport updates
|
|
1456
|
+
* @returns {void}
|
|
1457
|
+
* @throws {Error} If scene is null or not a THREE.Scene instance
|
|
1458
|
+
*/
|
|
1276
1459
|
function init(scene, renderer) {
|
|
1277
1460
|
state.scene = scene;
|
|
1278
1461
|
state.renderer = renderer;
|
|
@@ -1367,6 +1550,32 @@
|
|
|
1367
1550
|
* @param {Object} params
|
|
1368
1551
|
* @returns {any}
|
|
1369
1552
|
*/
|
|
1553
|
+
/**
|
|
1554
|
+
* Execute command in TextToCAD module (public API)
|
|
1555
|
+
*
|
|
1556
|
+
* Main entry point for all text-to-CAD operations. Commands include:
|
|
1557
|
+
* - 'parse': Parse natural language and return structured spec
|
|
1558
|
+
* - 'generate': Generate and display geometry
|
|
1559
|
+
* - 'commit': Add to history
|
|
1560
|
+
* - 'undo'/'redo': Navigate history
|
|
1561
|
+
* - 'clear': Reset everything
|
|
1562
|
+
* - 'setVariant': Select one of 3 generated alternatives
|
|
1563
|
+
*
|
|
1564
|
+
* @param {string} command - Command name: 'parse'|'generate'|'commit'|'undo'|'redo'|'clear'|'setVariant'
|
|
1565
|
+
* @param {Object} [params={}] - Command parameters (varies by command)
|
|
1566
|
+
* @param {string} params.input - For 'parse' and 'generate': natural language text
|
|
1567
|
+
* @param {number} params.variantIndex - For 'setVariant': index 0-2
|
|
1568
|
+
* @returns {Object} Command result (structure varies by command)
|
|
1569
|
+
* @example
|
|
1570
|
+
* // Parse natural language
|
|
1571
|
+
* const spec = window.CycleCAD.TextToCAD.execute('parse', {input: 'cylinder 50mm dia 80mm tall'});
|
|
1572
|
+
*
|
|
1573
|
+
* // Generate geometry with preview
|
|
1574
|
+
* window.CycleCAD.TextToCAD.execute('generate', {input: 'cylinder 50mm dia 80mm tall'});
|
|
1575
|
+
*
|
|
1576
|
+
* // Commit to history
|
|
1577
|
+
* window.CycleCAD.TextToCAD.execute('commit');
|
|
1578
|
+
*/
|
|
1370
1579
|
function execute(command, params) {
|
|
1371
1580
|
switch (command) {
|
|
1372
1581
|
case 'parse':
|