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.
@@ -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
- * Provides access to 200+ standard parts with:
5
- * - AI-powered natural language search
6
- * - 3D parametric geometry generation
7
- * - Supplier part number cross-reference
8
- * - BOM management and export
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
- * @namespace CycleCAD.SmartParts
12
- * @requires THREE.js
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
- * @module TextToCAD
6
- * @version 1.0.0
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
- * Features:
9
- * - NLP parser for 50+ shape types and features
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
- * @param {string} input - English description
98
- * @returns {Object} Structured geometry specification
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
- * @param {string} input
133
- * @returns {string} Intent type
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
- * @param {string} input
149
- * @returns {string|null} Shape type
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 with unit conversion
171
- * @param {string} input
172
- * @returns {Object} Dimensions in mm
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 input
233
- * @param {string} input
234
- * @returns {Array} Feature specifications
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
- * @param {number} value
404
- * @param {string} unit
405
- * @returns {number} Value in mm
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
- * @param {Object} spec - Parsed CAD specification
422
- * @returns {THREE.Group} Composite 3D geometry
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':