forgecad 0.10.1 → 0.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.
Files changed (113) hide show
  1. package/README.md +7 -6
  2. package/dist/assets/{AdminPage-DcCnj0qo.js → AdminPage-CK7ObBz3.js} +1 -1
  3. package/dist/assets/{BenchmarkPage-BVEpJSVk.js → BenchmarkPage-Ds7Z2doN.js} +1 -1
  4. package/dist/assets/{BlogPage-DHaGP50_.js → BlogPage-DlPbpt6A.js} +1 -1
  5. package/dist/assets/{DocsPage-CDoxHkz8.js → DocsPage-vZb3b3Y0.js} +9 -14
  6. package/dist/assets/{EditorApp-BpjZgzk0.css → EditorApp-C5f24ZN9.css} +8 -0
  7. package/dist/assets/{EditorApp-BJ0Dloyh.js → EditorApp-HLoKfe15.js} +152 -21
  8. package/dist/assets/{EmbedViewer-CRKZbY0y.js → EmbedViewer--KnqBKrJ.js} +3 -3
  9. package/dist/assets/{LandingPageProofDriven-BxHkYRE7.js → LandingPageProofDriven-C_LssmnA.js} +1 -1
  10. package/dist/assets/{LegalPage-B-u6FrVv.js → LegalPage-DGsyo4n1.js} +1 -1
  11. package/dist/assets/{PricingPage-CzpZ6-Ce.js → PricingPage-BOE27B-R.js} +1 -1
  12. package/dist/assets/{SettingsPage-CIZSSAd0.js → SettingsPage-f47cnk39.js} +1 -1
  13. package/dist/assets/{app-DaTMg3nH.js → app-D6ccu2Xx.js} +7826 -7559
  14. package/dist/assets/{scalar-sampling-budget-prBw_s8t.js → backendInit-DbTkQN9J.js} +87141 -78777
  15. package/dist/assets/cli/{render-DPf4AYJK.js → render-BsngirjC.js} +147 -186
  16. package/dist/assets/{constructionHistoryWorker-AwMMWSxg.js → constructionHistoryWorker-PCwXrTDB.js} +8419 -1447
  17. package/dist/assets/{evalWorker-CjZZWRWW.js → evalWorker-CS63PfZu.js} +25501 -17997
  18. package/dist/assets/{forgecad_geometry-Dgceylq9.js → forgecad_geometry-CZ_IfuvA.js} +120 -9
  19. package/dist/assets/forgecad_geometry_bg-C3rQHfwg.wasm +0 -0
  20. package/dist/assets/{inspectWorker-CZsCFtQT.js → inspectWorker-Y4cOzNyA.js} +37208 -34464
  21. package/dist/assets/{jointPose-DzQOViQH.js → jointPose-AMvCywzS.js} +1 -1
  22. package/dist/assets/{manifold-DgXo0T5P.js → manifold-CBry38ly.js} +2 -2
  23. package/dist/assets/{manifold-K1SkarlQ.js → manifold-Crd_F2qx.js} +1 -1
  24. package/dist/assets/{manifold-BYlzU521.js → manifold-k2kRcc85.js} +1 -1
  25. package/dist/assets/{reportWorker-B9nWwSrB.js → reportWorker-CWvn0CEv.js} +46635 -44646
  26. package/dist/cli/render.html +1 -1
  27. package/dist/docs/index.html +2 -2
  28. package/dist/docs-raw/AI/usage.md +2 -4
  29. package/dist/docs-raw/CLI.md +34 -20
  30. package/dist/docs-raw/README.md +1 -1
  31. package/dist/docs-raw/component-model.md +1 -1
  32. package/dist/docs-raw/generated/assembly.md +2 -2
  33. package/dist/docs-raw/generated/concepts.md +6 -4
  34. package/dist/docs-raw/generated/core.md +71 -2
  35. package/dist/docs-raw/generated/curves.md +8 -1
  36. package/dist/docs-raw/generated/lib.md +1 -1
  37. package/dist/docs-raw/generated/output.md +0 -64
  38. package/dist/docs-raw/generated/runtime-names.md +6 -6
  39. package/dist/docs-raw/generated/sdf.md +2 -2
  40. package/dist/docs-raw/generated/viewport.md +3 -12
  41. package/dist/docs-raw/guides/inspection-bundles.md +1 -1
  42. package/dist/docs-raw/guides/simready-quickstart.md +3 -1
  43. package/dist/docs-raw/simulation-workflow.md +58 -0
  44. package/dist/docs-raw/skills/forgecad-blockout-model.md +1 -1
  45. package/dist/docs-raw/skills/forgecad-image-replicator.md +2 -2
  46. package/dist/docs-raw/skills/forgecad-mujoco-verify.md +78 -0
  47. package/dist/docs-raw/skills/forgecad-spec-by-walking-through-it.md +145 -0
  48. package/dist/docs-raw/skills/forgecad-visual-spec.md +1 -1
  49. package/dist/docs-raw/skills/forgecad.md +24 -24
  50. package/dist/docs-raw/skills/index.md +2 -3
  51. package/dist/index.html +1 -1
  52. package/dist/sitemap.xml +15 -15
  53. package/dist-cli/{check-compiler-II7NLPAB.js → check-compiler-HPF2T2FS.js} +1 -1
  54. package/dist-cli/{check-query-propagation-7462TR3R.js → check-query-propagation-HYSLTXAB.js} +1 -1
  55. package/dist-cli/{chunk-UWTJCGXF.js → chunk-WLUKAW3H.js} +51134 -43247
  56. package/dist-cli/forgecad.js +5467 -1451
  57. package/dist-cli/{forgecad_geometry-QOQIIP53.js → forgecad_geometry-2IMYCUWW.js} +119 -8
  58. package/dist-cli/forgecad_geometry_bg.wasm +0 -0
  59. package/dist-skill/CONTEXT.md +98 -86
  60. package/dist-skill/SKILL.md +1 -1
  61. package/dist-skill/docs/API/core/concepts.md +1 -1
  62. package/dist-skill/docs/CLI.md +34 -20
  63. package/dist-skill/docs/generated/assembly.md +2 -2
  64. package/dist-skill/docs/generated/core.md +71 -2
  65. package/dist-skill/docs/generated/curves.md +8 -1
  66. package/dist-skill/docs/generated/lib.md +1 -1
  67. package/dist-skill/docs/generated/output.md +0 -64
  68. package/dist-skill/docs/generated/runtime-names.md +6 -6
  69. package/dist-skill/docs/generated/sdf.md +2 -2
  70. package/dist-skill/docs/generated/viewport.md +3 -12
  71. package/dist-skill/docs/guides/inspection-bundles.md +1 -1
  72. package/dist-skill/library/README.md +2 -3
  73. package/dist-skill/library/forgecad-blockout-model/SKILL.md +1 -1
  74. package/dist-skill/library/forgecad-image-replicator/SKILL.md +2 -2
  75. package/dist-skill/library/forgecad-mujoco-verify/SKILL.md +66 -0
  76. package/dist-skill/library/forgecad-mujoco-verify/scripts/mujoco_verify.py +385 -0
  77. package/dist-skill/library/forgecad-spec-by-walking-through-it/SKILL.md +132 -0
  78. package/dist-skill/library/forgecad-visual-spec/SKILL.md +1 -1
  79. package/dist-skill/website/skills/forgecad-blockout-model.md +1 -1
  80. package/dist-skill/website/skills/forgecad-image-replicator.md +2 -2
  81. package/dist-skill/website/skills/forgecad-mujoco-verify.md +78 -0
  82. package/dist-skill/website/skills/forgecad-spec-by-walking-through-it.md +145 -0
  83. package/dist-skill/website/skills/forgecad-visual-spec.md +1 -1
  84. package/dist-skill/website/skills/forgecad.md +24 -24
  85. package/dist-skill/website/skills/index.md +2 -3
  86. package/examples/analysis/clearance-fit.forge.js +31 -0
  87. package/examples/analysis/lever-arm-actuator.forge.js +43 -0
  88. package/examples/analysis/tipping-tripod.forge.js +35 -0
  89. package/examples/api/gyroid-voronoi-blend.forge.js +1 -1
  90. package/examples/api/organic-noise-sculpture.forge.js +1 -1
  91. package/examples/api/sdf-circular-array-knurling.forge.js +1 -1
  92. package/examples/api/{sdf-custom-raymarch.forge.js → sdf-custom-field-mesh-preview.forge.js} +3 -4
  93. package/examples/api/sdf-materialize-tree.forge.js +2 -2
  94. package/examples/api/sdf-plain-return.forge.js +3 -2
  95. package/examples/api/sdf-shapes.forge.js +2 -2
  96. package/examples/api/sdf-surface-basket-weave.forge.js +2 -2
  97. package/examples/generative/twisted-lattice-tower.forge.js +1 -1
  98. package/examples/generative/voronoi-lampshade.forge.js +1 -1
  99. package/examples/products/sportscar.forge.js +77 -0
  100. package/package.json +2 -4
  101. package/dist/assets/forgecad_geometry_bg-dD4RNQF1.wasm +0 -0
  102. package/dist/assets/manifold-CzYf_iub.js +0 -3023
  103. package/dist/docs-raw/skills/forgecad-high-level-spec.md +0 -101
  104. package/dist/docs-raw/skills/forgecad-lld.md +0 -41
  105. package/dist/docs-raw/skills/forgecad-prepare-prompt.md +0 -63
  106. package/dist-skill/library/forgecad-high-level-spec/SKILL.md +0 -94
  107. package/dist-skill/library/forgecad-lld/SKILL.md +0 -34
  108. package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +0 -50
  109. package/dist-skill/website/skills/forgecad-high-level-spec.md +0 -101
  110. package/dist-skill/website/skills/forgecad-lld.md +0 -41
  111. package/dist-skill/website/skills/forgecad-prepare-prompt.md +0 -63
  112. /package/dist-skill/library/{forgecad-prepare-prompt → forgecad-spec-by-walking-through-it}/references/default-profiles.md +0 -0
  113. /package/dist-skill/library/{forgecad-prepare-prompt → forgecad-spec-by-walking-through-it}/references/master-prompt.md +0 -0
@@ -31,13 +31,6 @@ function geometry_chamfer_edges(handle, spec_json) {
31
31
  }
32
32
  return ret[0] >>> 0;
33
33
  }
34
- function geometry_clone(handle) {
35
- const ret = wasm.geometry_clone(handle);
36
- if (ret[2]) {
37
- throw takeFromExternrefTable0(ret[1]);
38
- }
39
- return ret[0] >>> 0;
40
- }
41
34
  function geometry_create_box(width, depth, height) {
42
35
  const ret = wasm.geometry_create_box(width, depth, height);
43
36
  return ret >>> 0;
@@ -154,6 +147,25 @@ function geometry_create_revolved_regions(regions_json, degrees, segments) {
154
147
  }
155
148
  return ret[0] >>> 0;
156
149
  }
150
+ function geometry_create_sdf_mesh(abi_version, opcodes, arg_a, arg_b, arg_c, constants, output, slot_count, options_json) {
151
+ const ptr0 = passArray8ToWasm0(opcodes, wasm.__wbindgen_malloc);
152
+ const len0 = WASM_VECTOR_LEN;
153
+ const ptr1 = passArray32ToWasm0(arg_a, wasm.__wbindgen_malloc);
154
+ const len1 = WASM_VECTOR_LEN;
155
+ const ptr2 = passArray32ToWasm0(arg_b, wasm.__wbindgen_malloc);
156
+ const len2 = WASM_VECTOR_LEN;
157
+ const ptr3 = passArray32ToWasm0(arg_c, wasm.__wbindgen_malloc);
158
+ const len3 = WASM_VECTOR_LEN;
159
+ const ptr4 = passArrayF64ToWasm0(constants, wasm.__wbindgen_malloc);
160
+ const len4 = WASM_VECTOR_LEN;
161
+ const ptr5 = passStringToWasm0(options_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
162
+ const len5 = WASM_VECTOR_LEN;
163
+ const ret = wasm.geometry_create_sdf_mesh(abi_version, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4, output, slot_count, ptr5, len5);
164
+ if (ret[2]) {
165
+ throw takeFromExternrefTable0(ret[1]);
166
+ }
167
+ return ret[0] >>> 0;
168
+ }
157
169
  function geometry_create_side_profile_cut(spec_json) {
158
170
  const ptr0 = passStringToWasm0(spec_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
159
171
  const len0 = WASM_VECTOR_LEN;
@@ -249,6 +261,9 @@ function geometry_delete_nurbs_curve(handle) {
249
261
  function geometry_delete_nurbs_surface(handle) {
250
262
  wasm.geometry_delete_nurbs_surface(handle);
251
263
  }
264
+ function geometry_delete_sdf_mesh(handle) {
265
+ wasm.geometry_delete_sdf_mesh(handle);
266
+ }
252
267
  function geometry_export_step(handle) {
253
268
  let deferred2_0;
254
269
  let deferred2_1;
@@ -509,6 +524,47 @@ function geometry_sample_nurbs_surface(handle, u_samples, v_samples) {
509
524
  wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
510
525
  }
511
526
  }
527
+ function geometry_sdf_mesh_metadata(handle) {
528
+ let deferred2_0;
529
+ let deferred2_1;
530
+ try {
531
+ const ret = wasm.geometry_sdf_mesh_metadata(handle);
532
+ var ptr1 = ret[0];
533
+ var len1 = ret[1];
534
+ if (ret[3]) {
535
+ ptr1 = 0;
536
+ len1 = 0;
537
+ throw takeFromExternrefTable0(ret[2]);
538
+ }
539
+ deferred2_0 = ptr1;
540
+ deferred2_1 = len1;
541
+ return getStringFromWasm0(ptr1, len1);
542
+ } finally {
543
+ wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
544
+ }
545
+ }
546
+ function geometry_sdf_mesh_tri_verts(handle) {
547
+ const ret = wasm.geometry_sdf_mesh_tri_verts(handle);
548
+ if (ret[3]) {
549
+ throw takeFromExternrefTable0(ret[2]);
550
+ }
551
+ var v1 = getArrayU32FromWasm0(ret[0], ret[1]).slice();
552
+ wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
553
+ return v1;
554
+ }
555
+ function geometry_sdf_mesh_vert_properties(handle) {
556
+ const ret = wasm.geometry_sdf_mesh_vert_properties(handle);
557
+ if (ret[3]) {
558
+ throw takeFromExternrefTable0(ret[2]);
559
+ }
560
+ var v1 = getArrayF32FromWasm0(ret[0], ret[1]).slice();
561
+ wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
562
+ return v1;
563
+ }
564
+ function geometry_sdf_mesher_abi_version() {
565
+ const ret = wasm.geometry_sdf_mesher_abi_version();
566
+ return ret >>> 0;
567
+ }
512
568
  function geometry_select_edges(handle, query_json) {
513
569
  let deferred3_0;
514
570
  let deferred3_1;
@@ -621,9 +677,38 @@ function __wbg_get_imports() {
621
677
  "./forgecad_geometry_bg.js": import0
622
678
  };
623
679
  }
680
+ function getArrayF32FromWasm0(ptr, len) {
681
+ ptr = ptr >>> 0;
682
+ return getFloat32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
683
+ }
684
+ function getArrayU32FromWasm0(ptr, len) {
685
+ ptr = ptr >>> 0;
686
+ return getUint32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
687
+ }
688
+ var cachedFloat32ArrayMemory0 = null;
689
+ function getFloat32ArrayMemory0() {
690
+ if (cachedFloat32ArrayMemory0 === null || cachedFloat32ArrayMemory0.byteLength === 0) {
691
+ cachedFloat32ArrayMemory0 = new Float32Array(wasm.memory.buffer);
692
+ }
693
+ return cachedFloat32ArrayMemory0;
694
+ }
695
+ var cachedFloat64ArrayMemory0 = null;
696
+ function getFloat64ArrayMemory0() {
697
+ if (cachedFloat64ArrayMemory0 === null || cachedFloat64ArrayMemory0.byteLength === 0) {
698
+ cachedFloat64ArrayMemory0 = new Float64Array(wasm.memory.buffer);
699
+ }
700
+ return cachedFloat64ArrayMemory0;
701
+ }
624
702
  function getStringFromWasm0(ptr, len) {
625
703
  return decodeText(ptr >>> 0, len);
626
704
  }
705
+ var cachedUint32ArrayMemory0 = null;
706
+ function getUint32ArrayMemory0() {
707
+ if (cachedUint32ArrayMemory0 === null || cachedUint32ArrayMemory0.byteLength === 0) {
708
+ cachedUint32ArrayMemory0 = new Uint32Array(wasm.memory.buffer);
709
+ }
710
+ return cachedUint32ArrayMemory0;
711
+ }
627
712
  var cachedUint8ArrayMemory0 = null;
628
713
  function getUint8ArrayMemory0() {
629
714
  if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
@@ -631,6 +716,24 @@ function getUint8ArrayMemory0() {
631
716
  }
632
717
  return cachedUint8ArrayMemory0;
633
718
  }
719
+ function passArray32ToWasm0(arg, malloc) {
720
+ const ptr = malloc(arg.length * 4, 4) >>> 0;
721
+ getUint32ArrayMemory0().set(arg, ptr / 4);
722
+ WASM_VECTOR_LEN = arg.length;
723
+ return ptr;
724
+ }
725
+ function passArray8ToWasm0(arg, malloc) {
726
+ const ptr = malloc(arg.length * 1, 1) >>> 0;
727
+ getUint8ArrayMemory0().set(arg, ptr / 1);
728
+ WASM_VECTOR_LEN = arg.length;
729
+ return ptr;
730
+ }
731
+ function passArrayF64ToWasm0(arg, malloc) {
732
+ const ptr = malloc(arg.length * 8, 8) >>> 0;
733
+ getFloat64ArrayMemory0().set(arg, ptr / 8);
734
+ WASM_VECTOR_LEN = arg.length;
735
+ return ptr;
736
+ }
634
737
  function passStringToWasm0(arg, malloc, realloc) {
635
738
  if (realloc === void 0) {
636
739
  const buf = cachedTextEncoder.encode(arg);
@@ -698,6 +801,9 @@ function __wbg_finalize_init(instance, module) {
698
801
  wasmInstance = instance;
699
802
  wasm = instance.exports;
700
803
  wasmModule = module;
804
+ cachedFloat32ArrayMemory0 = null;
805
+ cachedFloat64ArrayMemory0 = null;
806
+ cachedUint32ArrayMemory0 = null;
701
807
  cachedUint8ArrayMemory0 = null;
702
808
  wasm.__wbindgen_start();
703
809
  return wasm;
@@ -776,7 +882,6 @@ export {
776
882
  geometry_boolean,
777
883
  geometry_capabilities,
778
884
  geometry_chamfer_edges,
779
- geometry_clone,
780
885
  geometry_create_box,
781
886
  geometry_create_cylinder,
782
887
  geometry_create_empty,
@@ -791,6 +896,7 @@ export {
791
896
  geometry_create_nurbs_surface_handle,
792
897
  geometry_create_path_swept_regions,
793
898
  geometry_create_revolved_regions,
899
+ geometry_create_sdf_mesh,
794
900
  geometry_create_side_profile_cut,
795
901
  geometry_create_sphere,
796
902
  geometry_create_surface_grid,
@@ -804,6 +910,7 @@ export {
804
910
  geometry_delete,
805
911
  geometry_delete_nurbs_curve,
806
912
  geometry_delete_nurbs_surface,
913
+ geometry_delete_sdf_mesh,
807
914
  geometry_export_step,
808
915
  geometry_export_step_multi,
809
916
  geometry_fillet_edges,
@@ -818,6 +925,10 @@ export {
818
925
  geometry_nurbs_surface_tessellation,
819
926
  geometry_sample_nurbs_curve,
820
927
  geometry_sample_nurbs_surface,
928
+ geometry_sdf_mesh_metadata,
929
+ geometry_sdf_mesh_tri_verts,
930
+ geometry_sdf_mesh_vert_properties,
931
+ geometry_sdf_mesher_abi_version,
821
932
  geometry_select_edges,
822
933
  geometry_topology,
823
934
  geometry_transform,
Binary file
@@ -39,16 +39,16 @@ Author or modify ForgeCAD models, sketches, assemblies, and CLI workflows. Prefe
39
39
  ### Validation and export commands (ask the user to run these)
40
40
 
41
41
  ```bash
42
- forgecad run <file.forge.js> # geometry diagnostics, verify.* results — run after every edit
43
- forgecad run <file.forge.js> --debug-imports # trace import-chain failures
44
- forgecad check print <file.forge.js> --json # collisions, mesh health, walls, overhangs, bed contact
45
- forgecad render 3d <file.forge.js> # shaded PNG render
46
- forgecad render wireframe <file.forge.js> # edges only — internal geometry, edge flow
47
- forgecad render section <file.forge.js> --plane XZ # 2D cross-section (SVG/PNG)
48
- forgecad capture gif <file.forge.js> # animated orbit or joint-playback GIF
49
- forgecad export stl <file.forge.js> # mesh for 3D printing
50
- forgecad export 3mf <file.forge.js> # mesh + metadata for 3D printing
51
- forgecad export step <file.forge.js> # exact B-rep for CAD interchange
42
+ forgecad run <file.forge.js> [file ...] # geometry diagnostics, verify.* results — run after every edit
43
+ forgecad run <file.forge.js> --debug-imports # trace import-chain failures
44
+ forgecad check print <file.forge.js> [file ...] --json # collisions, mesh health, walls, overhangs, bed contact
45
+ forgecad render 3d <file.forge.js> [file ...] # shaded PNG render
46
+ forgecad render wireframe <file.forge.js> [file ...] # edges only — internal geometry, edge flow
47
+ forgecad render section <file.forge.js> [file ...] --plane XZ # 2D cross-section (SVG/PNG)
48
+ forgecad capture gif <file.forge.js> [file ...] # animated orbit or joint-playback GIF
49
+ forgecad export stl <file.forge.js> [file ...] # mesh for 3D printing
50
+ forgecad export 3mf <file.forge.js> [file ...] # mesh + metadata for 3D printing
51
+ forgecad export step <file.forge.js> [file ...] # exact B-rep for CAD interchange
52
52
  ```
53
53
 
54
54
  Add `--param Name=Value` to test a specific parameter value. Pick the export that matches the goal: STL/3MF for printing, STEP for exact CAD interchange.
@@ -114,7 +114,7 @@ Resolve labels with `.face(name)` or `.face(query)` — see the Shape class docs
114
114
 
115
115
  **No explanatory text inside CAD geometry.** Model the physical artifact; explain the design through names, comments, BOM entries, and docs. Use `text2d()` only when letters are part of the real object (engraving, branding, gauge ticks); use `Viewport.label()` only for temporary review/debug annotation — never to compensate for unclear geometry.
116
116
 
117
- **SDF shapes preview natively** when returned directly; call `.toShape()` only when mesh-backed CAD/export behavior is needed. See [SDF docs](../../generated/sdf.md).
117
+ **SDF shapes preview natively** when returned directly — including plain object/array trees of SDF leaves; call `.toShape()` only when mesh-backed CAD/export behavior is needed. See [SDF docs](../../generated/sdf.md).
118
118
 
119
119
  ---
120
120
 
@@ -141,12 +141,12 @@ lib, Line2D, linearPattern, linearPattern2d, loadFont, loft, Loft, mirrorCopy
141
141
  mock, ngon, NurbsCurve3D, NurbsSurface, offsetSolid, param, Param, path
142
142
  Point2D, Points, polygon, polygonVertices, port, Product, ProductPanelBuilder, ProductRibbonBuilder
143
143
  ProductSkin, ProductSkinBuilder, ProductStationBuilder, ProductSurfaceBuilder, ProductSurfaceRef, projectToPlane, queueMicrotask, rect
144
- Rectangle2D, robotExport, roundedRect, Route3D, scene, Sculpt, sdf, SdfShape
145
- selectEdge, selectEdges, self, setActiveBackend, setImmediate, setInterval, setTimeout, Shape
146
- ShapeGroup, sheetMetal, SheetMetalPart, sheetStock, Sim, Sketch, sketchToDxf, sketchToSvg
147
- slot, SolvedAssembly, spec, sphere, spline2d, stroke, Surface, SurfaceBody
148
- SurfaceMembers, sweep, text2d, textWidth, torus, toShape, Transform, union
149
- union2d, variableSweep, verify, Viewport, window, Wood
144
+ Rectangle2D, roundedRect, Route3D, scene, Sculpt, sdf, SdfShape, selectEdge
145
+ selectEdges, self, setActiveBackend, setImmediate, setInterval, setTimeout, Shape, ShapeGroup
146
+ sheetMetal, SheetMetalPart, sheetStock, Sim, Sketch, sketchToDxf, sketchToSvg, slot
147
+ SolvedAssembly, spec, sphere, spline2d, stroke, Surface, SurfaceBody, SurfaceMembers
148
+ sweep, text2d, textWidth, torus, toShape, Transform, union, union2d
149
+ variableSweep, verify, Viewport, window, Wood
150
150
  ```
151
151
 
152
152
  `showLabels` is also a runtime global, but it is not part of the top-level collision check. Avoid reusing it unless you intentionally want a local value with that name.
@@ -176,6 +176,10 @@ union2d, variableSweep, verify, Viewport, window, Wood
176
176
  - [SurfacePattern](#surfacepattern)
177
177
  - [Pattern2D](#pattern2d)
178
178
  - [Pattern2DBuilder](#pattern2dbuilder)
179
+ - [Sheet](#sheet)
180
+ - [CurveNetBuilder](#curvenetbuilder)
181
+ - [MatchEdgeBuilder](#matchedgebuilder)
182
+ - [BridgeBuilder](#bridgebuilder)
179
183
  - [ShapeRef](#shaperef)
180
184
  - [ANCHOR3D_NAMES](#anchor3d-names)
181
185
  - [verify](#verify)
@@ -307,7 +311,7 @@ chamfer(base, 3, base.edge('vert-br'))
307
311
 
308
312
  Adds a taper angle to the vertical faces of a solid so that it can be extracted from a mold. The neutral plane is the Z position where the draft angle is zero — faces above and below are tapered symmetrically. Typical values for injection molding are 1–5°.
309
313
 
310
- Truck supports vertical-prism solids with Z-axis pull directions. OCCT uses its native draft operation when available. Manifold throws.
314
+ SDF, Manifold, and Truck lower supported vertical-prism solids with Z-axis pull directions to a tapered loft. OCCT uses its native draft operation when available.
311
315
 
312
316
  ```ts
313
317
  // Add 3° draft to a box for injection molding
@@ -860,7 +864,7 @@ Supports transforms (translate, rotate, scale, mirror, transform, rotateAround,
860
864
 
861
865
  Returns a new Shape with the specified material properties merged on top of any previously set properties. All properties are optional — omitted keys retain their current value. Material properties survive transforms and boolean operations.
862
866
 
863
- Use `.color()` to set the base diffuse color; `.material()` controls how that color behaves under light (metalness, roughness, clearcoat) and can add emissive glow independent of lighting. Emissive glow pairs naturally with the `postProcessing.bloom` effect in [`scene()`](/docs/viewport#scene).
867
+ Use `.color()` to set the base diffuse color; `.material()` controls how that color behaves under light (metalness, roughness, clearcoat) and can add emissive glow independent of lighting.
864
868
 
865
869
  ```js
866
870
  box(50, 50, 50).material({ metalness: 0.9, roughness: 0.1 }); // polished metal
@@ -1485,6 +1489,71 @@ const bracket = group(
1485
1489
  | `depth?` | `number` | Thread groove depth in millimeters. Default: 0.8. |
1486
1490
  | `underScale?` | `number` | Relative height of the under-crossing thread. Default: 0.15. |
1487
1491
 
1492
+ ### `Sheet`
1493
+
1494
+ A parametric open surface value (control grid + knots + analytic differential geometry).
1495
+
1496
+ **Properties:**
1497
+
1498
+ | Property | Type | Description |
1499
+ |----------|------|-------------|
1500
+ | `surface` | `BSplineSurface` | — |
1501
+
1502
+ **Methods:**
1503
+
1504
+ #### `get frontEdge(): SheetEdge` — Edge naming follows parameter direction (documented): front=v0, rear=v1, left=u0, right=u1.
1505
+
1506
+ #### `thicken(wall: number, options?: { resolution?: number; }): Shape` — Offset the sheet along its analytic normals into a watertight solid shell of the given wall thickness. Throws if the wall would self-intersect on a concave region (no silent degenerate solid).
1507
+
1508
+ #### `matchEdge(edge: SheetEdge): MatchEdgeBuilder` — Per-edge continuity match against a neighbor (returns a NEW Sheet).
1509
+
1510
+ **`SheetEdge`**
1511
+ - `fixed: "u" | "v"` — Which parameter is held fixed along this edge.
1512
+ - `value: 0 | 1` — The fixed value (0 or 1).
1513
+ - Also: `sheet: Sheet`.
1514
+
1515
+ - `get rearEdge(): SheetEdge`
1516
+ - `get leftEdge(): SheetEdge`
1517
+ - `get rightEdge(): SheetEdge`
1518
+ - `pointAt(u: number, v: number): Vec3`
1519
+ - `normalAt(u: number, v: number): Vec3`
1520
+ - `curvatureAt(u: number, v: number): SurfaceCurvature`
1521
+
1522
+ ### `CurveNetBuilder`
1523
+
1524
+ #### `toSheet(): Sheet` — Build (once) and return the Sheet.
1525
+
1526
+ - `lengthwise(...curves: CurveInput[]): this`
1527
+ - `crosswise(...curves: CurveInput[]): this`
1528
+ - `alongRails(railA: CurveInput, railB: CurveInput): this`
1529
+ - `sections(...curves: CurveInput[]): this`
1530
+ - `cage(grid: Vec3[][]): this`
1531
+ - `degree(u: number, v: number): this`
1532
+ - `get frontEdge(): SheetEdge`
1533
+ - `get rearEdge(): SheetEdge`
1534
+ - `get leftEdge(): SheetEdge`
1535
+ - `get rightEdge(): SheetEdge`
1536
+ - `get surface(): BSplineSurface`
1537
+ - `pointAt(u: number, v: number): Vec3`
1538
+ - `normalAt(u: number, v: number): Vec3`
1539
+ - `curvatureAt(u: number, v: number): SurfaceCurvature`
1540
+ - `thicken(wall: number, options?: { resolution?: number; }): Shape`
1541
+ - `matchEdge(edge: SheetEdge): MatchEdgeBuilder`
1542
+
1543
+ ### `MatchEdgeBuilder`
1544
+
1545
+ - `toG0(neighbor: SheetEdge): Sheet`
1546
+ - `toG1(neighbor: SheetEdge): Sheet`
1547
+ - `toG2(neighbor: SheetEdge): Sheet`
1548
+
1549
+ ### `BridgeBuilder`
1550
+
1551
+ #### `bulge(a: number, b: number): this` — Tune the influence of each side (Rhino-style bulge).
1552
+
1553
+ - `g0(): Sheet`
1554
+ - `g1(): Sheet`
1555
+ - `g2(): Sheet`
1556
+
1488
1557
  ### `ShapeRef`
1489
1558
 
1490
1559
  A first-class reference path over a shape's semantic faces and face relationships.
@@ -3025,7 +3094,11 @@ const outlet = route.port("outlet");
3025
3094
 
3026
3095
  #### `pointAt(u: number, v: number): Vec3` — Evaluate the surface at parameters (u, v) ∈ [0, 1]². Uses tensor product evaluation: evaluate basis functions in U and V independently.
3027
3096
 
3028
- #### `normalAt(u: number, v: number): Vec3` — Evaluate the surface normal at (u, v) via cross product of partial derivatives.
3097
+ #### `normalAt(u: number, v: number): Vec3` — Evaluate the surface unit normal at (u, v) from analytic first derivatives.
3098
+
3099
+ Uses Algorithm A2.3 basis-function derivatives with the rational quotient rule, so the normal is exact (no finite-difference epsilon, no error near the boundary). Constant chain-rule factors from the parameter remap scale Su and Sv positively and cancel under normalization, so they are omitted.
3100
+
3101
+ #### `derivativesAt(u: number, v: number): { S: Vec3; Su: Vec3; Sv: Vec3; }` — Analytic first partial derivatives S_u, S_v (rational quotient rule).
3029
3102
 
3030
3103
  #### `tessellate(resU?: number, resV?: number): { positions: Vec3[]; normals: Vec3[]; indices: number[]; }` — Tessellate the surface into a triangle mesh. Returns positions, normals, and triangle indices.
3031
3104
 
@@ -3764,16 +3837,19 @@ Members (full entries under [Curves & Surfacing](#curves-surfacing)): `Curve.Ble
3764
3837
  - `Trim(shape: Shape, tool: Shape | SurfacePlaneOp): Shape`
3765
3838
  - `Split(shape: Shape, tool: Shape | SurfacePlaneOp): [ Shape, Shape ]`
3766
3839
  - `Match(shape: Shape, options: { edge: "u0" | "u1" | "v0" | "v1"; target: EdgeRef; continuity?: SurfaceContinuity; }): Shape`
3840
+ - `Net(): CurveNet` — Begin a curve-network (Gordon) surface — the class-A keystone. Chain `.lengthwise(...)/.crosswise(...)` (or `.alongRails(a,b).sections(...)`, or `.cage(grid)`), then `.thicken(wall)` to get a solid Shape. Returns a fluent [`Sheet`](/docs/core#sheet) builder with analytic point/normal/curvature queries and named edges.
3767
3841
 
3768
3842
  ### `Blend`
3769
3843
 
3770
3844
  - `Edge(options: BlendEdgeOptions): Shape`
3771
3845
  - `Surface(options: BlendSurfaceOptions): Shape`
3846
+ - `Bridge(edgeA: SheetEdge, edgeB: SheetEdge): BridgeBuilder` — Build a transition strip between two `Surface.Net` sheet edges. Chain `.bulge(a, b)` then `.g0()/.g1()/.g2()` for the continuity order. Returns a [`Sheet`](/docs/core#sheet); verify the seam with `Analysis.EdgeMatch`.
3772
3847
 
3773
3848
  ### `Analysis`
3774
3849
 
3775
3850
  - `EdgeContinuity(shape: Shape, options?: EdgeContinuityThresholds): EdgeContinuityReport`
3776
3851
  - `SurfaceContinuity(shape: Shape, options?: EdgeContinuityThresholds): EdgeContinuityReport`
3852
+ - `EdgeMatch(edgeA: SheetEdge, edgeB: SheetEdge, options?: { samples?: number; }): ContinuityReport` — Measure G0/G1/G2 agreement between two `Surface.Net` sheet edges: worst position gap, cross-boundary tangent angle (0 = G1), and normal-curvature mismatch (0 = G2). The reflection/fairness check for matched panel seams.
3777
3853
  - `CurvatureComb(input: NurbsCurve3D | EdgeRef, options?: { samples?: number; }): CurvatureSample[]`
3778
3854
  - `SurfaceHealth(shape: Shape, options?: { tinyEdgeThreshold?: number; sliverThreshold?: number; }): SurfaceHealthReport`
3779
3855
  - `BRepValidity(shape: Shape, options?: BRepValidityOptions): BRepValidityReport` — Validate B-rep/shell/solid structure and return closedness, manifoldness, orientation, and issue diagnostics.
@@ -4226,7 +4302,7 @@ return mech.solve({ theta: 45 });
4226
4302
 
4227
4303
  #### `withSimulation(options: SimAssemblySimulationOptions): Assembly` — Attach the root simulation contract for this assembly.
4228
4304
 
4229
- Use this after adding physical parts and joints. Robot-body profiles require `rootPart`; asset profiles can describe one-part or multi-part physical assets. URDF/SDF exporters and `forgecad check simready` read this contract directly, so model files no longer need a separate `robotExport(...)` side effect.
4305
+ Use this after adding physical parts and joints. Robot-body profiles require `rootPart`; asset profiles can describe one-part or multi-part physical assets. URDF/SDF/MJCF/USD exporters and `forgecad check simready` read this contract directly from the returned assembly.
4230
4306
 
4231
4307
  `SimAssemblySimulationOptions`: `{ profile: SimProfileDef, rootPart?: string, controllers?: SimControllerDef[] }`
4232
4308
 
@@ -4437,7 +4513,7 @@ console.log("Collisions", solved.collisionReport());
4437
4513
 
4438
4514
  #### `minClearance(partA: string, partB: string, searchLength?: number): number` — Compute the minimum gap (clearance) between two parts in this solved pose.
4439
4515
 
4440
- Returns `0` if the parts are touching or overlapping. Requires the Manifold backend. `searchLength` bounds the search radius in mm — increase it for widely separated parts.
4516
+ Returns `0` if the parts are touching or overlapping. Manifold-backed parts use the exact Manifold gap query. SDF-backed parts use a mesh-derived sampled gap. `searchLength` bounds the Manifold search radius in mm — increase it for widely separated Manifold parts.
4441
4517
 
4442
4518
  ---
4443
4519
 
@@ -4498,70 +4574,6 @@ bom(tubeLen, "rectangular steel tube", {
4498
4574
  | `notes?` | `string` | Free-form notes |
4499
4575
  | `grain?` | `string` | Wood grain direction, e.g. "long", "cross" |
4500
4576
 
4501
- #### `robotExport(options: RobotExportOptions): CollectedRobotExport` — Compatibility shim for SDF/URDF robot package metadata.
4502
-
4503
- Prefer returning `assembly(...).withSimulation(...)` with `Sim.body(...)`, `Sim.drive.*(...)`, and `Sim.controller.*(...)` metadata. The CLI commands `forgecad export sdf` and `forgecad export urdf` now read that assembly simulation contract directly.
4504
-
4505
- `robotExport()` remains available for one compatibility window. It converts the legacy descriptor into the same internal simulation model used by source-authored `Sim` metadata and produces a robot package with:
4506
-
4507
- - Mesh-based inertia tensors (full 6-component, not bounding-box approximations)
4508
- - Separate collision meshes
4509
- - Joint limits, effort/velocity/damping/friction metadata from assembly joints
4510
-
4511
- **Collision mesh modes** (set per-link via `links["PartName"].collision`):
4512
-
4513
- | Mode | Description | Default |
4514
- |------|-------------|---------|
4515
- | `'convex'` | Convex hull (separate `_collision.stl`) | Yes |
4516
- | `'box'` | AABB primitive — fastest physics | |
4517
- | `'visual'` | Same mesh as visual — exact but slow | |
4518
- | `'none'` | No collision geometry | |
4519
-
4520
- **Unit conventions:**
4521
-
4522
- - Revolute `velocity` is in degrees/second in Forge; exporters convert to rad/s.
4523
- - Prismatic distances are in mm in Forge; exported in meters.
4524
- - `massKg` is preferred; `densityKgM3` is used when mass is unknown.
4525
- - Compatibility coupling metadata, when present, maps only the primary term (largest ratio) to `<mimic>` — SDF/URDF support single-leader mimic only. Dropped terms emit a warning.
4526
-
4527
- **Legacy example**
4528
-
4529
- ```ts
4530
- robotExport({
4531
- assembly: rover, // assembly() with parts + revolute wheel joints
4532
- modelName: "Scout",
4533
- links: { Chassis: { massKg: 10 }, "Left Wheel": { massKg: 0.8 } },
4534
- plugins: {
4535
- diffDrive: {
4536
- leftJoints: ["leftWheel"], rightJoints: ["rightWheel"],
4537
- wheelSeparationMm: 280, wheelRadiusMm: 60,
4538
- },
4539
- },
4540
- world: { generateDemoWorld: true },
4541
- });
4542
- ```
4543
-
4544
- **Preferred CLI usage**
4545
-
4546
- ```bash
4547
- forgecad export sdf model.forge.js # SDF package (Gazebo/Ignition)
4548
- forgecad export urdf model.forge.js # URDF package (ROS/PyBullet/MuJoCo)
4549
- ```
4550
-
4551
- **`RobotExportOptions`**: `assembly: Assembly`, `modelName?: string`, `state?: JointState`, `static?: boolean`, `selfCollide?: boolean`, `allowAutoDisable?: boolean`, `links?: Record<string, RobotLinkExportOptions>`, `joints?: Record<string, RobotJointExportOptions>`, `plugins?: { diffDrive?: RobotDiffDrivePluginOptions; jointStatePublisher?: RobotJointStatePublisherOptions; }`, `world?: RobotWorldOptions`
4552
-
4553
- `RobotLinkExportOptions`: `{ massKg?: number, densityKgM3?: number, collision?: "visual" | "convex" | "box" | "none" }`
4554
-
4555
- `RobotJointExportOptions`: `{ effort?: number, velocity?: number, damping?: number, friction?: number }`
4556
-
4557
- **`RobotDiffDrivePluginOptions`**: `leftJoints: string[]`, `rightJoints: string[]`, `wheelSeparationMm: number`, `wheelRadiusMm: number`, `topic?: string`, `odomTopic?: string`, `tfTopic?: string`, `frameId?: string`, `odomFrameId?: string`, `maxLinearVelocity?: number`, `maxAngularVelocity?: number`, `linearAcceleration?: number`, `angularAcceleration?: number`
4558
-
4559
- `RobotJointStatePublisherOptions`: `{ enabled?: boolean, joints?: string[], topic?: string, updateRate?: number }`
4560
-
4561
- `RobotWorldOptions`: `{ name?: string, generateDemoWorld?: boolean, spawnPose?: RobotPose6, keyboardTeleop?: RobotWorldKeyboardTeleopOptions }`
4562
-
4563
- `RobotWorldKeyboardTeleopOptions`: `{ enabled?: boolean, linearStep?: number, angularStep?: number }`
4564
-
4565
4577
  #### `dim()` — Add a dimension annotation between two points, or along an entity.
4566
4578
 
4567
4579
  Overloads:
@@ -65,7 +65,7 @@ Smooth curves, Hermite splines, lofted and swept solids. For straps, inlays, gua
65
65
 
66
66
  ### 5. Assemblies and Mechanisms (for joints or kinematics)
67
67
 
68
- Assembly graph, joint types, couplings, validation, robot export.
68
+ Assembly graph, joint types, couplings, validation, and simulation export.
69
69
 
70
70
  - `{{SKILL_DIR}}/docs/generated/assembly.md`
71
71
 
@@ -48,4 +48,4 @@ Resolve labels with `.face(name)` or `.face(query)` — see the Shape class docs
48
48
 
49
49
  **No explanatory text inside CAD geometry.** Model the physical artifact; explain the design through names, comments, BOM entries, and docs. Use `text2d()` only when letters are part of the real object (engraving, branding, gauge ticks); use `Viewport.label()` only for temporary review/debug annotation — never to compensate for unclear geometry.
50
50
 
51
- **SDF shapes preview natively** when returned directly; call `.toShape()` only when mesh-backed CAD/export behavior is needed. See [SDF docs](../../generated/sdf.md).
51
+ **SDF shapes preview natively** when returned directly — including plain object/array trees of SDF leaves; call `.toShape()` only when mesh-backed CAD/export behavior is needed. See [SDF docs](../../generated/sdf.md).