cyclecad 3.10.2 → 3.10.3

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/index.html CHANGED
@@ -1538,7 +1538,7 @@ window._dismissSplash = function(action) {
1538
1538
 
1539
1539
  <!-- Killer Feature Modules -->
1540
1540
  <script src="/app/js/agent-api.js?v=a41b98a5"></script>
1541
- <script src="/app/js/modules/ai-copilot.js?v=407987b9"></script>
1541
+ <script src="/app/js/modules/ai-copilot.js?v=14e5d5d7"></script>
1542
1542
  <script src="/app/js/modules/text-to-cad.js"></script>
1543
1543
  <script src="/app/js/modules/photo-to-cad.js"></script>
1544
1544
  <script src="/app/js/modules/manufacturability.js"></script>
@@ -390,7 +390,105 @@
390
390
  {method:'view.fit', params:{}}
391
391
  ];
392
392
  }
393
- // L-bracket with holes
393
+ // DIN 125 washer (M3-M12)
394
+ const washerM = p.match(/\bm(\d+)\s*washer|washer\s+m(\d+)|din\s*125\s*m?(\d+)/);
395
+ if (washerM) {
396
+ const size = parseInt(washerM[1]||washerM[2]||washerM[3]);
397
+ const outerR = ({3:3.5, 4:4.5, 5:5.3, 6:6.4, 8:8.4, 10:10.5, 12:13})[size] || size*1.2;
398
+ const thick = ({3:0.5, 4:0.8, 5:1, 6:1.6, 8:1.6, 10:2, 12:2.5})[size] || size*0.2;
399
+ const holeR = (size + 0.4) / 2;
400
+ return [
401
+ {method:'sketch.start', params:{plane:'XY'}},
402
+ {method:'sketch.circle', params:{radius: outerR}},
403
+ {method:'ops.extrude', params:{depth: thick, position:[0,0,0]}, note:'DIN 125 M'+size+' washer'},
404
+ {method:'ops.hole', params:{position:[0, thick, 0], radius: holeR, depth: thick+2}, note:'M'+size+' hole'},
405
+ {method:'view.set', params:{view:'iso'}},
406
+ {method:'view.fit', params:{}}
407
+ ];
408
+ }
409
+ // Flange with bolt circle
410
+ const flangeM = p.match(/flange/);
411
+ if (flangeM) {
412
+ const odM = p.match(/(\d+)\s*mm/);
413
+ const od = odM ? parseInt(odM[1]) : 80;
414
+ const nM = p.match(/(\d+)\s*(?:bolt\s*)?holes?/);
415
+ const nHoles = nM ? parseInt(nM[1]) : 4;
416
+ const pcdM = p.match(/pcd\s*(\d+)|bolt\s*circle\s*(\d+)/);
417
+ const pcd = pcdM ? parseInt(pcdM[1]||pcdM[2]) : Math.round(od*0.7);
418
+ const thick = 8;
419
+ const plan = [
420
+ {method:'sketch.start', params:{plane:'XY'}},
421
+ {method:'sketch.circle', params:{radius: od/2}},
422
+ {method:'ops.extrude', params:{depth: thick, position:[0,0,0]}, note:'flange body Ø'+od},
423
+ {method:'ops.hole', params:{position:[0, thick, 0], radius: Math.max(5, od/8), depth: thick+2}, note:'center bore'}
424
+ ];
425
+ for (let i = 0; i < nHoles; i++) {
426
+ const a = (i / nHoles) * Math.PI * 2;
427
+ const x = Math.cos(a) * pcd/2, z = Math.sin(a) * pcd/2;
428
+ plan.push({method:'ops.hole', params:{position:[x, thick/2, z], radius: 3, depth: thick+2}, note:'bolt hole '+(i+1)+'/'+nHoles});
429
+ }
430
+ plan.push({method:'view.set', params:{view:'iso'}});
431
+ plan.push({method:'view.fit', params:{}});
432
+ return plan;
433
+ }
434
+ // Threaded rod / stud
435
+ const rodM = p.match(/threaded\s*rod|m(\d+)\s*rod|m(\d+)\s*stud|studding/);
436
+ if (rodM) {
437
+ const sM = p.match(/m(\d+)/);
438
+ const size = sM ? parseInt(sM[1]) : 8;
439
+ const lM = p.match(/(\d+)\s*mm/);
440
+ const len = lM ? parseInt(lM[1]) : 100;
441
+ return [
442
+ {method:'sketch.start', params:{plane:'XY'}},
443
+ {method:'sketch.circle', params:{radius: size/2}},
444
+ {method:'ops.extrude', params:{depth: len, position:[0,0,0]}, note:'M'+size+' threaded rod, '+len+'mm long'},
445
+ {method:'view.set', params:{view:'iso'}},
446
+ {method:'view.fit', params:{}}
447
+ ];
448
+ }
449
+ // Mounting plate
450
+ const plateM = p.match(/mounting\s*plate|base\s*plate|flat\s*plate/);
451
+ if (plateM) {
452
+ const dimM = p.match(/(\d+)\s*x\s*(\d+)/);
453
+ const w = dimM ? parseInt(dimM[1]) : 120;
454
+ const h = dimM ? parseInt(dimM[2]) : 80;
455
+ const thick = 6;
456
+ const nM = p.match(/(\d+)\s*holes?/);
457
+ const nHoles = nM ? parseInt(nM[1]) : 4;
458
+ const plan = [
459
+ {method:'sketch.start', params:{plane:'XY'}},
460
+ {method:'sketch.rect', params:{width: w, height: h}},
461
+ {method:'ops.extrude', params:{depth: thick, position:[0,0,0]}, note: w+'x'+h+'x'+thick+' mounting plate'}
462
+ ];
463
+ if (nHoles === 4) {
464
+ const mx = w/2 - 10, mz = h/2 - 10;
465
+ [[-mx,-mz],[mx,-mz],[-mx,mz],[mx,mz]].forEach((pp,i) => {
466
+ plan.push({method:'ops.hole', params:{position:[pp[0], thick/2, pp[1]], radius:3, depth:thick+2}, note:'corner hole '+(i+1)});
467
+ });
468
+ } else {
469
+ for (let i = 0; i < nHoles; i++) {
470
+ const x = -w/2 + 10 + (i/(nHoles-1)) * (w-20);
471
+ plan.push({method:'ops.hole', params:{position:[x, thick/2, 0], radius:3, depth:thick+2}, note:'hole '+(i+1)});
472
+ }
473
+ }
474
+ plan.push({method:'view.set', params:{view:'iso'}});
475
+ plan.push({method:'view.fit', params:{}});
476
+ return plan;
477
+ }
478
+ // Generic box NxNxN with optional fillet
479
+ const boxM = p.match(/\bbox\b|\bblock\b|\bcube\b|\bcuboid\b/);
480
+ const boxDim = p.match(/(\d+)\s*[x×]\s*(\d+)\s*[x×]\s*(\d+)/);
481
+ if (boxM && boxDim) {
482
+ const w = parseInt(boxDim[1]), h = parseInt(boxDim[2]), d = parseInt(boxDim[3]);
483
+ return [
484
+ {method:'sketch.start', params:{plane:'XY'}},
485
+ {method:'sketch.rect', params:{width: w, height: d}},
486
+ {method:'ops.extrude', params:{depth: h, position:[0,0,0]}, note: w+'x'+h+'x'+d+' box'},
487
+ {method:'view.set', params:{view:'iso'}},
488
+ {method:'view.fit', params:{}}
489
+ ];
490
+ }
491
+ // L-bracket with holes
394
492
  if (/l-?bracket|mounting\s*bracket|angle\s*bracket/.test(p)) {
395
493
  const lenM = p.match(/(\d+)\s*mm/);
396
494
  const length = lenM ? parseInt(lenM[1]) : 100;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyclecad",
3
- "version": "3.10.2",
3
+ "version": "3.10.3",
4
4
  "description": "Browser-based parametric 3D CAD modeler with AI-powered tools, native Inventor file parsing, and smart assembly management. No install required.",
5
5
  "main": "index.html",
6
6
  "bin": {