forgecad 0.10.2 → 0.10.4
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/README.md +7 -6
- package/dist/assets/{AdminPage-CHY6ZN-p.js → AdminPage-B3L3W1Uo.js} +1 -1
- package/dist/assets/{BenchmarkPage-BcRT5iGN.js → BenchmarkPage-DXKVXMrJ.js} +2 -2
- package/dist/assets/{BlogPage-BssBbnb-.js → BlogPage-B7BWxOCg.js} +1 -1
- package/dist/assets/{DocsPage-DsvdiRNK.js → DocsPage-BPGGwht1.js} +28 -48
- package/dist/assets/{EditorApp-Bfd3jbtC.js → EditorApp-BWUGCdD5.js} +183 -21
- package/dist/assets/{EditorApp-BpjZgzk0.css → EditorApp-C5f24ZN9.css} +8 -0
- package/dist/assets/{EmbedViewer-D5t8WamV.js → EmbedViewer-DygByZS2.js} +2 -2
- package/dist/assets/{LandingPageProofDriven-DbN7o-Be.js → LandingPageProofDriven-BoVE7JGY.js} +54 -36
- package/dist/assets/{LegalPage-DNGrrY0p.js → LegalPage-Din8wv8d.js} +2 -2
- package/dist/assets/{PricingPage-Nczr3pRz.js → PricingPage-C2PMzmDc.js} +2 -2
- package/dist/assets/{SettingsPage-DZlyu4d4.js → SettingsPage-BlJDCRe8.js} +1 -1
- package/dist/assets/{app-C9ct2hRD.js → app-BsRYSfxY.js} +2264 -6259
- package/dist/assets/{backendInit-ymjonyQp.js → backendInit-6C0DLgH0.js} +8290 -2136
- package/dist/assets/cli/{render-B_0lQwKU.js → render-XXol_ET7.js} +822 -105
- package/dist/assets/{constructionHistoryWorker-CZ42Dksy.js → constructionHistoryWorker-cTHWRJEi.js} +699 -284
- package/dist/assets/{evalWorker-C2pm8LHP.js → evalWorker-BssDYW9u.js} +2559 -1330
- package/dist/assets/{forgecad_geometry-BlMtqluF.js → forgecad_geometry-CZ_IfuvA.js} +1 -9
- package/dist/assets/{forgecad_geometry_bg-BllP_WiL.wasm → forgecad_geometry_bg-C3rQHfwg.wasm} +0 -0
- package/dist/assets/{inspectWorker-D5T5VbfK.js → inspectWorker-ymhBV4Ll.js} +6254 -671
- package/dist/assets/{jointPose-4r8ed8_5.js → jointPose-B0blBj9A.js} +1 -1
- package/dist/assets/{landing-proof-driven-ORyigZ6p.css → landing-proof-driven-Cpf-MIbI.css} +73 -13
- package/dist/assets/{manifold-5PP1eGLN.js → manifold-B_7QXpGB.js} +1 -1
- package/dist/assets/{manifold-DjBkyIc8.js → manifold-CNShmpEJ.js} +1 -1
- package/dist/assets/{manifold-C4r6B-XY.js → manifold-CYlIm-M6.js} +2 -2
- package/dist/assets/{reportWorker-CwenM7wB.js → reportWorker-Cb5eyM7D.js} +2485 -1275
- package/dist/cli/render.html +1 -1
- package/dist/docs/index.html +2 -2
- package/dist/docs-raw/AI/usage.md +17 -17
- package/dist/docs-raw/CLI.md +9 -7
- package/dist/docs-raw/README.md +1 -1
- package/dist/docs-raw/component-model.md +2 -2
- package/dist/docs-raw/generated/assembly.md +1 -1
- package/dist/docs-raw/generated/concepts.md +10 -4
- package/dist/docs-raw/generated/core.md +96 -1
- package/dist/docs-raw/generated/curves.md +8 -1
- package/dist/docs-raw/generated/output.md +0 -64
- package/dist/docs-raw/generated/runtime-names.md +6 -6
- package/dist/docs-raw/generated/viewport.md +3 -12
- package/dist/docs-raw/guides/inspection-bundles.md +1 -1
- package/dist/docs-raw/simulation-workflow.md +58 -0
- package/{dist-skill/website/skills/forgecad-make-a-model.md → dist/docs-raw/skills/forgecad-build-model.md} +18 -8
- package/dist/docs-raw/skills/forgecad-design-spec.md +145 -0
- package/dist/docs-raw/skills/{forgecad-model-grader.md → forgecad-grade-model.md} +8 -6
- package/{dist-skill/website/skills/forgecad-visual-spec.md → dist/docs-raw/skills/forgecad-image-prompt.md} +7 -7
- package/dist/docs-raw/skills/{forgecad-render-inspect.md → forgecad-inspect-model.md} +6 -6
- package/{dist-skill/website/skills/forgecad-project.md → dist/docs-raw/skills/forgecad-project-sync.md} +5 -5
- package/{dist-skill/website/skills/forgecad-3d-reconstruction.md → dist/docs-raw/skills/forgecad-reconstruct-cad-file.md} +7 -7
- package/dist/docs-raw/skills/{forgecad-image-replicator.md → forgecad-reconstruct-from-images.md} +12 -12
- package/dist/docs-raw/skills/forgecad-verify-mujoco.md +78 -0
- package/dist/docs-raw/skills/forgecad.md +24 -24
- package/dist/docs-raw/skills/index.md +9 -13
- package/dist/index.html +9 -9
- package/dist/llms.txt +7 -7
- package/dist/sitemap.xml +16 -16
- package/dist-cli/{check-compiler-SP7FAL7R.js → check-compiler-4RPB6SB5.js} +1 -1
- package/dist-cli/{check-query-propagation-BRLSHP22.js → check-query-propagation-KN3DFQTX.js} +1 -1
- package/dist-cli/{chunk-RQQ42YCP.js → chunk-UHBRMYA6.js} +30770 -29253
- package/dist-cli/forgecad.js +3277 -237
- package/dist-cli/{forgecad_geometry-7TVSNVUB.js → forgecad_geometry-2IMYCUWW.js} +0 -8
- package/dist-cli/forgecad_geometry_bg.wasm +0 -0
- package/dist-skill/CONTEXT.md +111 -73
- package/dist-skill/SKILL.md +1 -1
- package/dist-skill/docs/CLI.md +9 -7
- package/dist-skill/docs/generated/assembly.md +1 -1
- package/dist-skill/docs/generated/core.md +96 -1
- package/dist-skill/docs/generated/curves.md +8 -1
- package/dist-skill/docs/generated/output.md +0 -64
- package/dist-skill/docs/generated/runtime-names.md +6 -6
- package/dist-skill/docs/generated/viewport.md +3 -12
- package/dist-skill/docs/guides/inspection-bundles.md +1 -1
- package/dist-skill/library/README.md +9 -13
- package/dist-skill/library/{forgecad-make-a-model → forgecad-build-model}/SKILL.md +16 -6
- package/dist-skill/library/forgecad-design-spec/SKILL.md +132 -0
- package/dist-skill/library/{forgecad-prepare-prompt → forgecad-design-spec}/references/master-prompt.md +1 -1
- package/dist-skill/library/{forgecad-model-grader → forgecad-grade-model}/SKILL.md +6 -4
- package/dist-skill/library/forgecad-grade-model/agents/openai.yaml +4 -0
- package/dist-skill/library/{forgecad-visual-spec → forgecad-image-prompt}/SKILL.md +5 -5
- package/dist-skill/library/forgecad-image-prompt/agents/openai.yaml +4 -0
- package/dist-skill/library/{forgecad-render-inspect → forgecad-inspect-model}/SKILL.md +4 -4
- package/dist-skill/library/{forgecad-project → forgecad-project-sync}/SKILL.md +3 -3
- package/dist-skill/library/{forgecad-3d-reconstruction → forgecad-reconstruct-cad-file}/SKILL.md +5 -5
- package/dist-skill/library/forgecad-reconstruct-cad-file/agents/openai.yaml +4 -0
- package/dist-skill/library/{forgecad-image-replicator → forgecad-reconstruct-from-images}/SKILL.md +10 -10
- package/dist-skill/library/forgecad-reconstruct-from-images/agents/openai.yaml +4 -0
- package/dist-skill/library/forgecad-verify-mujoco/SKILL.md +66 -0
- package/dist-skill/library/forgecad-verify-mujoco/scripts/mujoco_verify.py +385 -0
- package/{dist/docs-raw/skills/forgecad-make-a-model.md → dist-skill/website/skills/forgecad-build-model.md} +18 -8
- package/dist-skill/website/skills/forgecad-design-spec.md +145 -0
- package/dist-skill/website/skills/{forgecad-model-grader.md → forgecad-grade-model.md} +8 -6
- package/{dist/docs-raw/skills/forgecad-visual-spec.md → dist-skill/website/skills/forgecad-image-prompt.md} +7 -7
- package/dist-skill/website/skills/{forgecad-render-inspect.md → forgecad-inspect-model.md} +6 -6
- package/{dist/docs-raw/skills/forgecad-project.md → dist-skill/website/skills/forgecad-project-sync.md} +5 -5
- package/{dist/docs-raw/skills/forgecad-3d-reconstruction.md → dist-skill/website/skills/forgecad-reconstruct-cad-file.md} +7 -7
- package/dist-skill/website/skills/{forgecad-image-replicator.md → forgecad-reconstruct-from-images.md} +12 -12
- package/dist-skill/website/skills/forgecad-verify-mujoco.md +78 -0
- package/dist-skill/website/skills/forgecad.md +24 -24
- package/dist-skill/website/skills/index.md +9 -13
- package/examples/analysis/clearance-fit.forge.js +31 -0
- package/examples/analysis/lever-arm-actuator.forge.js +43 -0
- package/examples/analysis/tipping-tripod.forge.js +35 -0
- package/examples/api/texture-projection.forge.js +75 -0
- package/examples/assets/uv-grid.png +0 -0
- package/examples/products/sportscar.forge.js +77 -0
- package/package.json +1 -3
- package/dist/docs-raw/skills/forgecad-blockout-model.md +0 -49
- package/dist/docs-raw/skills/forgecad-component-model.md +0 -53
- package/dist/docs-raw/skills/forgecad-high-level-spec.md +0 -101
- package/dist/docs-raw/skills/forgecad-lld.md +0 -41
- package/dist/docs-raw/skills/forgecad-prepare-prompt.md +0 -63
- package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +0 -60
- package/dist-skill/library/forgecad-3d-reconstruction/agents/openai.yaml +0 -4
- package/dist-skill/library/forgecad-blockout-model/SKILL.md +0 -42
- package/dist-skill/library/forgecad-component-model/SKILL.md +0 -46
- package/dist-skill/library/forgecad-high-level-spec/SKILL.md +0 -94
- package/dist-skill/library/forgecad-image-replicator/agents/openai.yaml +0 -4
- package/dist-skill/library/forgecad-lld/SKILL.md +0 -34
- package/dist-skill/library/forgecad-model-grader/agents/openai.yaml +0 -4
- package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +0 -50
- package/dist-skill/library/forgecad-reconstruction-benchmark/SKILL.md +0 -48
- package/dist-skill/library/forgecad-reconstruction-benchmark/agents/openai.yaml +0 -4
- package/dist-skill/library/forgecad-visual-spec/agents/openai.yaml +0 -4
- package/dist-skill/website/skills/forgecad-blockout-model.md +0 -49
- package/dist-skill/website/skills/forgecad-component-model.md +0 -53
- package/dist-skill/website/skills/forgecad-high-level-spec.md +0 -101
- package/dist-skill/website/skills/forgecad-lld.md +0 -41
- package/dist-skill/website/skills/forgecad-prepare-prompt.md +0 -63
- package/dist-skill/website/skills/forgecad-reconstruction-benchmark.md +0 -60
- /package/dist/assets/{landing-proof-driven-DiGqdtWa.js → landing-proof-driven-BxZZh5r5.js} +0 -0
- /package/dist-skill/library/{forgecad-prepare-prompt → forgecad-design-spec}/references/default-profiles.md +0 -0
- /package/dist-skill/library/{forgecad-render-inspect → forgecad-inspect-model}/summarize_manifest.py +0 -0
- /package/dist-skill/library/{forgecad-image-replicator → forgecad-reconstruct-from-images}/scripts/compare_images.py +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;
|
|
@@ -889,7 +882,6 @@ export {
|
|
|
889
882
|
geometry_boolean,
|
|
890
883
|
geometry_capabilities,
|
|
891
884
|
geometry_chamfer_edges,
|
|
892
|
-
geometry_clone,
|
|
893
885
|
geometry_create_box,
|
|
894
886
|
geometry_create_cylinder,
|
|
895
887
|
geometry_create_empty,
|
|
Binary file
|
package/dist-skill/CONTEXT.md
CHANGED
|
@@ -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,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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, Wrap
|
|
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,12 +176,17 @@ 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)
|
|
182
186
|
- [Points](#points)
|
|
183
187
|
- [connector](#connector)
|
|
184
188
|
- [Import](#import)
|
|
189
|
+
- [Wrap](#wrap)
|
|
185
190
|
|
|
186
191
|
## Functions
|
|
187
192
|
|
|
@@ -860,7 +865,7 @@ Supports transforms (translate, rotate, scale, mirror, transform, rotateAround,
|
|
|
860
865
|
|
|
861
866
|
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
867
|
|
|
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.
|
|
868
|
+
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
869
|
|
|
865
870
|
```js
|
|
866
871
|
box(50, 50, 50).material({ metalness: 0.9, roughness: 0.1 }); // polished metal
|
|
@@ -889,6 +894,7 @@ box(100, 100, 10).color('#gold').material({ metalness: 0.95, roughness: 0.05 }).
|
|
|
889
894
|
| `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
|
|
890
895
|
| `specularColor?` | `string` | Specular highlight tint. |
|
|
891
896
|
| `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
|
|
897
|
+
| `texture?` | `{ image: string; projection: UvProjectionSpec; ...` | Projected bitmap texture set by `Shape.wrapTexture`. `image` is a self-contained `data:` URI; `projection` maps each vertex's final world position to (u,v) in the shader, so the texture survives transforms and boolean cuts. `imageWidth`/`imageHeight` are the intrinsic pixel dimensions. |
|
|
892
898
|
|
|
893
899
|
**Face Topology**
|
|
894
900
|
|
|
@@ -1237,6 +1243,22 @@ Overloads:
|
|
|
1237
1243
|
|
|
1238
1244
|
**Other**
|
|
1239
1245
|
|
|
1246
|
+
#### `wrapTexture(image: ImageHandle, projection: UvProjectionSpec): Shape` — Wrap an imported bitmap image around this shape using a projection.
|
|
1247
|
+
|
|
1248
|
+
The `image` comes from `Import.image('path.png')`; the `projection` is one of the `Wrap.*` helpers — `Wrap.flat({ onto: 'top' })` lays it flat on a face, `Wrap.aroundCylinder({ axis: 'z' })` wraps it like a can label, `Wrap.onSphere()` maps it like a globe, and `Wrap.box()` cube-maps it onto the six sides.
|
|
1249
|
+
|
|
1250
|
+
By default the image **auto-fits** the shape — one copy across the relevant extent, so no `width`/`height`/`size` is needed (pass them only to override). The (u,v) is derived from each vertex's final world position, so the image stays glued to the surface through transforms and boolean cuts with no UV layout to maintain — apply `wrapTexture` *after* positioning the shape. Returns a new Shape; the original is unchanged.
|
|
1251
|
+
|
|
1252
|
+
```js
|
|
1253
|
+
const logo = Import.image('./logo.png');
|
|
1254
|
+
box(80, 80, 10).wrapTexture(logo, Wrap.flat({ onto: 'top' })); // auto-fits the face
|
|
1255
|
+
|
|
1256
|
+
const label = Import.image('./label.jpg');
|
|
1257
|
+
cylinder(60, 20).wrapTexture(label, Wrap.aroundCylinder({ axis: 'z' })); // wraps the side
|
|
1258
|
+
```
|
|
1259
|
+
|
|
1260
|
+
`ImageHandle`: `{ __forgeImage: true, dataUri: string, width: number, height: number, mimeType: string, byteLength: number }`
|
|
1261
|
+
|
|
1240
1262
|
#### `clone(): Shape` — Return a new Shape wrapper for explicit duplication in scripts.
|
|
1241
1263
|
|
|
1242
1264
|
#### `geometryInfo(): GeometryInfo` — Inspect which backend/representation produced this solid.
|
|
@@ -1485,6 +1507,71 @@ const bracket = group(
|
|
|
1485
1507
|
| `depth?` | `number` | Thread groove depth in millimeters. Default: 0.8. |
|
|
1486
1508
|
| `underScale?` | `number` | Relative height of the under-crossing thread. Default: 0.15. |
|
|
1487
1509
|
|
|
1510
|
+
### `Sheet`
|
|
1511
|
+
|
|
1512
|
+
A parametric open surface value (control grid + knots + analytic differential geometry).
|
|
1513
|
+
|
|
1514
|
+
**Properties:**
|
|
1515
|
+
|
|
1516
|
+
| Property | Type | Description |
|
|
1517
|
+
|----------|------|-------------|
|
|
1518
|
+
| `surface` | `BSplineSurface` | — |
|
|
1519
|
+
|
|
1520
|
+
**Methods:**
|
|
1521
|
+
|
|
1522
|
+
#### `get frontEdge(): SheetEdge` — Edge naming follows parameter direction (documented): front=v0, rear=v1, left=u0, right=u1.
|
|
1523
|
+
|
|
1524
|
+
#### `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).
|
|
1525
|
+
|
|
1526
|
+
#### `matchEdge(edge: SheetEdge): MatchEdgeBuilder` — Per-edge continuity match against a neighbor (returns a NEW Sheet).
|
|
1527
|
+
|
|
1528
|
+
**`SheetEdge`**
|
|
1529
|
+
- `fixed: "u" | "v"` — Which parameter is held fixed along this edge.
|
|
1530
|
+
- `value: 0 | 1` — The fixed value (0 or 1).
|
|
1531
|
+
- Also: `sheet: Sheet`.
|
|
1532
|
+
|
|
1533
|
+
- `get rearEdge(): SheetEdge`
|
|
1534
|
+
- `get leftEdge(): SheetEdge`
|
|
1535
|
+
- `get rightEdge(): SheetEdge`
|
|
1536
|
+
- `pointAt(u: number, v: number): Vec3`
|
|
1537
|
+
- `normalAt(u: number, v: number): Vec3`
|
|
1538
|
+
- `curvatureAt(u: number, v: number): SurfaceCurvature`
|
|
1539
|
+
|
|
1540
|
+
### `CurveNetBuilder`
|
|
1541
|
+
|
|
1542
|
+
#### `toSheet(): Sheet` — Build (once) and return the Sheet.
|
|
1543
|
+
|
|
1544
|
+
- `lengthwise(...curves: CurveInput[]): this`
|
|
1545
|
+
- `crosswise(...curves: CurveInput[]): this`
|
|
1546
|
+
- `alongRails(railA: CurveInput, railB: CurveInput): this`
|
|
1547
|
+
- `sections(...curves: CurveInput[]): this`
|
|
1548
|
+
- `cage(grid: Vec3[][]): this`
|
|
1549
|
+
- `degree(u: number, v: number): this`
|
|
1550
|
+
- `get frontEdge(): SheetEdge`
|
|
1551
|
+
- `get rearEdge(): SheetEdge`
|
|
1552
|
+
- `get leftEdge(): SheetEdge`
|
|
1553
|
+
- `get rightEdge(): SheetEdge`
|
|
1554
|
+
- `get surface(): BSplineSurface`
|
|
1555
|
+
- `pointAt(u: number, v: number): Vec3`
|
|
1556
|
+
- `normalAt(u: number, v: number): Vec3`
|
|
1557
|
+
- `curvatureAt(u: number, v: number): SurfaceCurvature`
|
|
1558
|
+
- `thicken(wall: number, options?: { resolution?: number; }): Shape`
|
|
1559
|
+
- `matchEdge(edge: SheetEdge): MatchEdgeBuilder`
|
|
1560
|
+
|
|
1561
|
+
### `MatchEdgeBuilder`
|
|
1562
|
+
|
|
1563
|
+
- `toG0(neighbor: SheetEdge): Sheet`
|
|
1564
|
+
- `toG1(neighbor: SheetEdge): Sheet`
|
|
1565
|
+
- `toG2(neighbor: SheetEdge): Sheet`
|
|
1566
|
+
|
|
1567
|
+
### `BridgeBuilder`
|
|
1568
|
+
|
|
1569
|
+
#### `bulge(a: number, b: number): this` — Tune the influence of each side (Rhino-style bulge).
|
|
1570
|
+
|
|
1571
|
+
- `g0(): Sheet`
|
|
1572
|
+
- `g1(): Sheet`
|
|
1573
|
+
- `g2(): Sheet`
|
|
1574
|
+
|
|
1488
1575
|
### `ShapeRef`
|
|
1489
1576
|
|
|
1490
1577
|
A first-class reference path over a shape's semantic faces and face relationships.
|
|
@@ -1577,6 +1664,14 @@ Namespaced file-format import helpers — the single vocabulary for bringing ext
|
|
|
1577
1664
|
const yUpPart = Import.mesh("./part.obj", { sourceFrame: { up: "+Y" } });
|
|
1578
1665
|
```
|
|
1579
1666
|
- `step(fileName: string, options?: StepImportOptions): Shape` — Import a STEP file (.step, .stp) as an exact OCCT-backed Shape. Preserves NURBS curves, B-spline surfaces, and exact topology. Requires running with the OCCT backend. Use `sourceFrame: { up: "+Y" }` to rotate Y-up source files into ForgeCAD's Z-up world.
|
|
1667
|
+
- `image(fileName: string): ImageHandle` — Import a bitmap image (PNG, JPEG, or WebP) as an ImageHandle for projected texturing. Reads the pixel dimensions from the file header and embeds the bytes as a data URI. Pass the result to `Shape.wrapTexture(image, projection)` with a `Wrap.*` projection.
|
|
1668
|
+
|
|
1669
|
+
### `Wrap`
|
|
1670
|
+
|
|
1671
|
+
- `flat(opts: FlatWrapOptions): UvProjectionSpec` — Project the image flat onto an axis-aligned face — `onto` is one of top/bottom/front/back/left/right. Auto-fits the face (no width/height needed).
|
|
1672
|
+
- `aroundCylinder(opts: CylinderWrapOptions): UvProjectionSpec` — Wrap the image around a cylinder like a can label — `axis` is 'x' | 'y' | 'z'. Auto-fits one wrap around and the full height.
|
|
1673
|
+
- `onSphere(opts?: SphereWrapOptions): UvProjectionSpec` — Map the image over a sphere like a globe (longitude/latitude). Auto-centers on the sphere.
|
|
1674
|
+
- `box(opts?: BoxWrapOptions): UvProjectionSpec` — Cube-map the image onto a box — one copy per face. Auto-fits the box (no size needed).
|
|
1580
1675
|
|
|
1581
1676
|
---
|
|
1582
1677
|
|
|
@@ -3025,7 +3120,11 @@ const outlet = route.port("outlet");
|
|
|
3025
3120
|
|
|
3026
3121
|
#### `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
3122
|
|
|
3028
|
-
#### `normalAt(u: number, v: number): Vec3` — Evaluate the surface normal at (u, v)
|
|
3123
|
+
#### `normalAt(u: number, v: number): Vec3` — Evaluate the surface unit normal at (u, v) from analytic first derivatives.
|
|
3124
|
+
|
|
3125
|
+
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.
|
|
3126
|
+
|
|
3127
|
+
#### `derivativesAt(u: number, v: number): { S: Vec3; Su: Vec3; Sv: Vec3; }` — Analytic first partial derivatives S_u, S_v (rational quotient rule).
|
|
3029
3128
|
|
|
3030
3129
|
#### `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
3130
|
|
|
@@ -3764,16 +3863,19 @@ Members (full entries under [Curves & Surfacing](#curves-surfacing)): `Curve.Ble
|
|
|
3764
3863
|
- `Trim(shape: Shape, tool: Shape | SurfacePlaneOp): Shape`
|
|
3765
3864
|
- `Split(shape: Shape, tool: Shape | SurfacePlaneOp): [ Shape, Shape ]`
|
|
3766
3865
|
- `Match(shape: Shape, options: { edge: "u0" | "u1" | "v0" | "v1"; target: EdgeRef; continuity?: SurfaceContinuity; }): Shape`
|
|
3866
|
+
- `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
3867
|
|
|
3768
3868
|
### `Blend`
|
|
3769
3869
|
|
|
3770
3870
|
- `Edge(options: BlendEdgeOptions): Shape`
|
|
3771
3871
|
- `Surface(options: BlendSurfaceOptions): Shape`
|
|
3872
|
+
- `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
3873
|
|
|
3773
3874
|
### `Analysis`
|
|
3774
3875
|
|
|
3775
3876
|
- `EdgeContinuity(shape: Shape, options?: EdgeContinuityThresholds): EdgeContinuityReport`
|
|
3776
3877
|
- `SurfaceContinuity(shape: Shape, options?: EdgeContinuityThresholds): EdgeContinuityReport`
|
|
3878
|
+
- `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
3879
|
- `CurvatureComb(input: NurbsCurve3D | EdgeRef, options?: { samples?: number; }): CurvatureSample[]`
|
|
3778
3880
|
- `SurfaceHealth(shape: Shape, options?: { tinyEdgeThreshold?: number; sliverThreshold?: number; }): SurfaceHealthReport`
|
|
3779
3881
|
- `BRepValidity(shape: Shape, options?: BRepValidityOptions): BRepValidityReport` — Validate B-rep/shell/solid structure and return closedness, manifoldness, orientation, and issue diagnostics.
|
|
@@ -4226,7 +4328,7 @@ return mech.solve({ theta: 45 });
|
|
|
4226
4328
|
|
|
4227
4329
|
#### `withSimulation(options: SimAssemblySimulationOptions): Assembly` — Attach the root simulation contract for this assembly.
|
|
4228
4330
|
|
|
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
|
|
4331
|
+
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
4332
|
|
|
4231
4333
|
`SimAssemblySimulationOptions`: `{ profile: SimProfileDef, rootPart?: string, controllers?: SimControllerDef[] }`
|
|
4232
4334
|
|
|
@@ -4498,70 +4600,6 @@ bom(tubeLen, "rectangular steel tube", {
|
|
|
4498
4600
|
| `notes?` | `string` | Free-form notes |
|
|
4499
4601
|
| `grain?` | `string` | Wood grain direction, e.g. "long", "cross" |
|
|
4500
4602
|
|
|
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
4603
|
#### `dim()` — Add a dimension annotation between two points, or along an entity.
|
|
4566
4604
|
|
|
4567
4605
|
Overloads:
|
package/dist-skill/SKILL.md
CHANGED
|
@@ -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,
|
|
68
|
+
Assembly graph, joint types, couplings, validation, and simulation export.
|
|
69
69
|
|
|
70
70
|
- `{{SKILL_DIR}}/docs/generated/assembly.md`
|
|
71
71
|
|
package/dist-skill/docs/CLI.md
CHANGED
|
@@ -265,7 +265,7 @@ forgecad render section model.forge.js --output out/section.svg --plane XZ --off
|
|
|
265
265
|
|
|
266
266
|
### Cross-cutting flags
|
|
267
267
|
|
|
268
|
-
These flags work across run
|
|
268
|
+
These flags work across script-backed run, render, export, capture, inspect, and check commands that evaluate `.forge.js` files. Use `--param Key=Value` for parameter overrides; repeat it for multiple parameters.
|
|
269
269
|
|
|
270
270
|
| Option | Description |
|
|
271
271
|
|--------|-------------|
|
|
@@ -306,39 +306,41 @@ Export to every format you need.
|
|
|
306
306
|
|
|
307
307
|
```bash
|
|
308
308
|
# Sheet material
|
|
309
|
-
forgecad cut-list shelf.forge.js
|
|
309
|
+
forgecad cut-list shelf.forge.js --param Material=plywood
|
|
310
310
|
forgecad export cutting-layout shelf.forge.js --sheet-width 420 --sheet-height 594 --kerf 3
|
|
311
311
|
forgecad export cutting-layout shelf.forge.js --output out/layout.dxf
|
|
312
312
|
|
|
313
313
|
# 3D printing
|
|
314
314
|
forgecad check print bracket.forge.js
|
|
315
|
-
forgecad export stl bracket.forge.js
|
|
315
|
+
forgecad export stl bracket.forge.js --param Width=42
|
|
316
316
|
forgecad export 3mf bracket.forge.js --quality high
|
|
317
317
|
|
|
318
318
|
# CAD interchange
|
|
319
|
-
forgecad export step bracket.forge.js
|
|
319
|
+
forgecad export step bracket.forge.js --param Width=42
|
|
320
320
|
|
|
321
321
|
# Technical drawings
|
|
322
322
|
forgecad export report bracket.forge.js --output out/report.pdf
|
|
323
323
|
|
|
324
324
|
# Robot simulation
|
|
325
325
|
forgecad export sdf rover.forge.js --output out/forge_scout
|
|
326
|
-
forgecad export mjcf rover.forge.js --output out/forge_scout_mjcf
|
|
326
|
+
forgecad export mjcf rover.forge.js --param Wheelbase=180 --output out/forge_scout_mjcf
|
|
327
327
|
forgecad export usd rover.forge.js --output out/forge_scout_usd
|
|
328
328
|
```
|
|
329
329
|
|
|
330
|
+
Script-backed exports accept repeatable `--param Key=Value` overrides before the model is evaluated. The MuJoCo/MJX package export command is `export mjcf`.
|
|
331
|
+
|
|
330
332
|
<details>
|
|
331
333
|
<summary>Export flags</summary>
|
|
332
334
|
|
|
333
335
|
| Option | Description |
|
|
334
336
|
|--------|-------------|
|
|
337
|
+
| `--param <Key=Value>` | Override a parameter value (Key=Value). Repeatable. |
|
|
338
|
+
| `-p <Key=Value>` | Shorthand for --param |
|
|
335
339
|
| `--joint <JointName=Value>` | Override a Motion tab joint value (JointName=Value). Repeatable. |
|
|
336
340
|
| `--output <path>` | Output SVG path for a single input |
|
|
337
341
|
| `--backend <occt\|truck>` | Exact BREP exporter: occt (default) or truck (native analytic kernel) |
|
|
338
342
|
| `--quality <default\|live\|high>` | Forge quality preset |
|
|
339
343
|
| `-o <path>` | Shorthand for --output |
|
|
340
|
-
| `--param <Key=Value>` | Override a parameter value (Key=Value). Repeatable. |
|
|
341
|
-
| `-p <Key=Value>` | Shorthand for --param |
|
|
342
344
|
| `--format <json\|webgpu-brick>` | Implicit artifact format |
|
|
343
345
|
| `-q <live\|default\|high>` | Shorthand for --quality |
|
|
344
346
|
| `--workgroup-size <x>x<y>x<z>` | WebGPU compute workgroup size |
|
|
@@ -356,7 +356,7 @@ return mech.solve({ theta: 45 });
|
|
|
356
356
|
|
|
357
357
|
#### `withSimulation(options: SimAssemblySimulationOptions): Assembly` — Attach the root simulation contract for this assembly.
|
|
358
358
|
|
|
359
|
-
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
|
|
359
|
+
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.
|
|
360
360
|
|
|
361
361
|
`SimAssemblySimulationOptions`: `{ profile: SimProfileDef, rootPart?: string, controllers?: SimControllerDef[] }`
|
|
362
362
|
|
|
@@ -24,12 +24,17 @@ skill-order: 100
|
|
|
24
24
|
- [SurfacePattern](#surfacepattern)
|
|
25
25
|
- [Pattern2D](#pattern2d)
|
|
26
26
|
- [Pattern2DBuilder](#pattern2dbuilder)
|
|
27
|
+
- [Sheet](#sheet)
|
|
28
|
+
- [CurveNetBuilder](#curvenetbuilder)
|
|
29
|
+
- [MatchEdgeBuilder](#matchedgebuilder)
|
|
30
|
+
- [BridgeBuilder](#bridgebuilder)
|
|
27
31
|
- [ShapeRef](#shaperef)
|
|
28
32
|
- [ANCHOR3D_NAMES](#anchor3d-names)
|
|
29
33
|
- [verify](#verify)
|
|
30
34
|
- [Points](#points)
|
|
31
35
|
- [connector](#connector)
|
|
32
36
|
- [Import](#import)
|
|
37
|
+
- [Wrap](#wrap)
|
|
33
38
|
|
|
34
39
|
## Functions
|
|
35
40
|
|
|
@@ -708,7 +713,7 @@ Supports transforms (translate, rotate, scale, mirror, transform, rotateAround,
|
|
|
708
713
|
|
|
709
714
|
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.
|
|
710
715
|
|
|
711
|
-
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.
|
|
716
|
+
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.
|
|
712
717
|
|
|
713
718
|
```js
|
|
714
719
|
box(50, 50, 50).material({ metalness: 0.9, roughness: 0.1 }); // polished metal
|
|
@@ -737,6 +742,7 @@ box(100, 100, 10).color('#gold').material({ metalness: 0.95, roughness: 0.05 }).
|
|
|
737
742
|
| `specularIntensity?` | `number` | Specular highlight intensity (0–1). |
|
|
738
743
|
| `specularColor?` | `string` | Specular highlight tint. |
|
|
739
744
|
| `reflectivity?` | `number` | Reflection strength for supported renderers (0–1). |
|
|
745
|
+
| `texture?` | `{ image: string; projection: UvProjectionSpec; ...` | Projected bitmap texture set by `Shape.wrapTexture`. `image` is a self-contained `data:` URI; `projection` maps each vertex's final world position to (u,v) in the shader, so the texture survives transforms and boolean cuts. `imageWidth`/`imageHeight` are the intrinsic pixel dimensions. |
|
|
740
746
|
|
|
741
747
|
**Face Topology**
|
|
742
748
|
|
|
@@ -1085,6 +1091,22 @@ Overloads:
|
|
|
1085
1091
|
|
|
1086
1092
|
**Other**
|
|
1087
1093
|
|
|
1094
|
+
#### `wrapTexture(image: ImageHandle, projection: UvProjectionSpec): Shape` — Wrap an imported bitmap image around this shape using a projection.
|
|
1095
|
+
|
|
1096
|
+
The `image` comes from `Import.image('path.png')`; the `projection` is one of the `Wrap.*` helpers — `Wrap.flat({ onto: 'top' })` lays it flat on a face, `Wrap.aroundCylinder({ axis: 'z' })` wraps it like a can label, `Wrap.onSphere()` maps it like a globe, and `Wrap.box()` cube-maps it onto the six sides.
|
|
1097
|
+
|
|
1098
|
+
By default the image **auto-fits** the shape — one copy across the relevant extent, so no `width`/`height`/`size` is needed (pass them only to override). The (u,v) is derived from each vertex's final world position, so the image stays glued to the surface through transforms and boolean cuts with no UV layout to maintain — apply `wrapTexture` *after* positioning the shape. Returns a new Shape; the original is unchanged.
|
|
1099
|
+
|
|
1100
|
+
```js
|
|
1101
|
+
const logo = Import.image('./logo.png');
|
|
1102
|
+
box(80, 80, 10).wrapTexture(logo, Wrap.flat({ onto: 'top' })); // auto-fits the face
|
|
1103
|
+
|
|
1104
|
+
const label = Import.image('./label.jpg');
|
|
1105
|
+
cylinder(60, 20).wrapTexture(label, Wrap.aroundCylinder({ axis: 'z' })); // wraps the side
|
|
1106
|
+
```
|
|
1107
|
+
|
|
1108
|
+
`ImageHandle`: `{ __forgeImage: true, dataUri: string, width: number, height: number, mimeType: string, byteLength: number }`
|
|
1109
|
+
|
|
1088
1110
|
#### `clone(): Shape` — Return a new Shape wrapper for explicit duplication in scripts.
|
|
1089
1111
|
|
|
1090
1112
|
#### `geometryInfo(): GeometryInfo` — Inspect which backend/representation produced this solid.
|
|
@@ -1333,6 +1355,71 @@ const bracket = group(
|
|
|
1333
1355
|
| `depth?` | `number` | Thread groove depth in millimeters. Default: 0.8. |
|
|
1334
1356
|
| `underScale?` | `number` | Relative height of the under-crossing thread. Default: 0.15. |
|
|
1335
1357
|
|
|
1358
|
+
### `Sheet`
|
|
1359
|
+
|
|
1360
|
+
A parametric open surface value (control grid + knots + analytic differential geometry).
|
|
1361
|
+
|
|
1362
|
+
**Properties:**
|
|
1363
|
+
|
|
1364
|
+
| Property | Type | Description |
|
|
1365
|
+
|----------|------|-------------|
|
|
1366
|
+
| `surface` | `BSplineSurface` | — |
|
|
1367
|
+
|
|
1368
|
+
**Methods:**
|
|
1369
|
+
|
|
1370
|
+
#### `get frontEdge(): SheetEdge` — Edge naming follows parameter direction (documented): front=v0, rear=v1, left=u0, right=u1.
|
|
1371
|
+
|
|
1372
|
+
#### `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).
|
|
1373
|
+
|
|
1374
|
+
#### `matchEdge(edge: SheetEdge): MatchEdgeBuilder` — Per-edge continuity match against a neighbor (returns a NEW Sheet).
|
|
1375
|
+
|
|
1376
|
+
**`SheetEdge`**
|
|
1377
|
+
- `fixed: "u" | "v"` — Which parameter is held fixed along this edge.
|
|
1378
|
+
- `value: 0 | 1` — The fixed value (0 or 1).
|
|
1379
|
+
- Also: `sheet: Sheet`.
|
|
1380
|
+
|
|
1381
|
+
- `get rearEdge(): SheetEdge`
|
|
1382
|
+
- `get leftEdge(): SheetEdge`
|
|
1383
|
+
- `get rightEdge(): SheetEdge`
|
|
1384
|
+
- `pointAt(u: number, v: number): Vec3`
|
|
1385
|
+
- `normalAt(u: number, v: number): Vec3`
|
|
1386
|
+
- `curvatureAt(u: number, v: number): SurfaceCurvature`
|
|
1387
|
+
|
|
1388
|
+
### `CurveNetBuilder`
|
|
1389
|
+
|
|
1390
|
+
#### `toSheet(): Sheet` — Build (once) and return the Sheet.
|
|
1391
|
+
|
|
1392
|
+
- `lengthwise(...curves: CurveInput[]): this`
|
|
1393
|
+
- `crosswise(...curves: CurveInput[]): this`
|
|
1394
|
+
- `alongRails(railA: CurveInput, railB: CurveInput): this`
|
|
1395
|
+
- `sections(...curves: CurveInput[]): this`
|
|
1396
|
+
- `cage(grid: Vec3[][]): this`
|
|
1397
|
+
- `degree(u: number, v: number): this`
|
|
1398
|
+
- `get frontEdge(): SheetEdge`
|
|
1399
|
+
- `get rearEdge(): SheetEdge`
|
|
1400
|
+
- `get leftEdge(): SheetEdge`
|
|
1401
|
+
- `get rightEdge(): SheetEdge`
|
|
1402
|
+
- `get surface(): BSplineSurface`
|
|
1403
|
+
- `pointAt(u: number, v: number): Vec3`
|
|
1404
|
+
- `normalAt(u: number, v: number): Vec3`
|
|
1405
|
+
- `curvatureAt(u: number, v: number): SurfaceCurvature`
|
|
1406
|
+
- `thicken(wall: number, options?: { resolution?: number; }): Shape`
|
|
1407
|
+
- `matchEdge(edge: SheetEdge): MatchEdgeBuilder`
|
|
1408
|
+
|
|
1409
|
+
### `MatchEdgeBuilder`
|
|
1410
|
+
|
|
1411
|
+
- `toG0(neighbor: SheetEdge): Sheet`
|
|
1412
|
+
- `toG1(neighbor: SheetEdge): Sheet`
|
|
1413
|
+
- `toG2(neighbor: SheetEdge): Sheet`
|
|
1414
|
+
|
|
1415
|
+
### `BridgeBuilder`
|
|
1416
|
+
|
|
1417
|
+
#### `bulge(a: number, b: number): this` — Tune the influence of each side (Rhino-style bulge).
|
|
1418
|
+
|
|
1419
|
+
- `g0(): Sheet`
|
|
1420
|
+
- `g1(): Sheet`
|
|
1421
|
+
- `g2(): Sheet`
|
|
1422
|
+
|
|
1336
1423
|
### `ShapeRef`
|
|
1337
1424
|
|
|
1338
1425
|
A first-class reference path over a shape's semantic faces and face relationships.
|
|
@@ -1425,3 +1512,11 @@ Namespaced file-format import helpers — the single vocabulary for bringing ext
|
|
|
1425
1512
|
const yUpPart = Import.mesh("./part.obj", { sourceFrame: { up: "+Y" } });
|
|
1426
1513
|
```
|
|
1427
1514
|
- `step(fileName: string, options?: StepImportOptions): Shape` — Import a STEP file (.step, .stp) as an exact OCCT-backed Shape. Preserves NURBS curves, B-spline surfaces, and exact topology. Requires running with the OCCT backend. Use `sourceFrame: { up: "+Y" }` to rotate Y-up source files into ForgeCAD's Z-up world.
|
|
1515
|
+
- `image(fileName: string): ImageHandle` — Import a bitmap image (PNG, JPEG, or WebP) as an ImageHandle for projected texturing. Reads the pixel dimensions from the file header and embeds the bytes as a data URI. Pass the result to `Shape.wrapTexture(image, projection)` with a `Wrap.*` projection.
|
|
1516
|
+
|
|
1517
|
+
### `Wrap`
|
|
1518
|
+
|
|
1519
|
+
- `flat(opts: FlatWrapOptions): UvProjectionSpec` — Project the image flat onto an axis-aligned face — `onto` is one of top/bottom/front/back/left/right. Auto-fits the face (no width/height needed).
|
|
1520
|
+
- `aroundCylinder(opts: CylinderWrapOptions): UvProjectionSpec` — Wrap the image around a cylinder like a can label — `axis` is 'x' | 'y' | 'z'. Auto-fits one wrap around and the full height.
|
|
1521
|
+
- `onSphere(opts?: SphereWrapOptions): UvProjectionSpec` — Map the image over a sphere like a globe (longitude/latitude). Auto-centers on the sphere.
|
|
1522
|
+
- `box(opts?: BoxWrapOptions): UvProjectionSpec` — Cube-map the image onto a box — one copy per face. Auto-fits the box (no size needed).
|
|
@@ -426,7 +426,11 @@ const outlet = route.port("outlet");
|
|
|
426
426
|
|
|
427
427
|
#### `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.
|
|
428
428
|
|
|
429
|
-
#### `normalAt(u: number, v: number): Vec3` — Evaluate the surface normal at (u, v)
|
|
429
|
+
#### `normalAt(u: number, v: number): Vec3` — Evaluate the surface unit normal at (u, v) from analytic first derivatives.
|
|
430
|
+
|
|
431
|
+
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.
|
|
432
|
+
|
|
433
|
+
#### `derivativesAt(u: number, v: number): { S: Vec3; Su: Vec3; Sv: Vec3; }` — Analytic first partial derivatives S_u, S_v (rational quotient rule).
|
|
430
434
|
|
|
431
435
|
#### `tessellate(resU?: number, resV?: number): { positions: Vec3[]; normals: Vec3[]; indices: number[]; }` — Tessellate the surface into a triangle mesh. Returns positions, normals, and triangle indices.
|
|
432
436
|
|
|
@@ -1165,16 +1169,19 @@ Members (full entries under [Curves & Surfacing](#curves-surfacing)): `Curve.Ble
|
|
|
1165
1169
|
- `Trim(shape: Shape, tool: Shape | SurfacePlaneOp): Shape`
|
|
1166
1170
|
- `Split(shape: Shape, tool: Shape | SurfacePlaneOp): [ Shape, Shape ]`
|
|
1167
1171
|
- `Match(shape: Shape, options: { edge: "u0" | "u1" | "v0" | "v1"; target: EdgeRef; continuity?: SurfaceContinuity; }): Shape`
|
|
1172
|
+
- `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.
|
|
1168
1173
|
|
|
1169
1174
|
### `Blend`
|
|
1170
1175
|
|
|
1171
1176
|
- `Edge(options: BlendEdgeOptions): Shape`
|
|
1172
1177
|
- `Surface(options: BlendSurfaceOptions): Shape`
|
|
1178
|
+
- `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`.
|
|
1173
1179
|
|
|
1174
1180
|
### `Analysis`
|
|
1175
1181
|
|
|
1176
1182
|
- `EdgeContinuity(shape: Shape, options?: EdgeContinuityThresholds): EdgeContinuityReport`
|
|
1177
1183
|
- `SurfaceContinuity(shape: Shape, options?: EdgeContinuityThresholds): EdgeContinuityReport`
|
|
1184
|
+
- `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.
|
|
1178
1185
|
- `CurvatureComb(input: NurbsCurve3D | EdgeRef, options?: { samples?: number; }): CurvatureSample[]`
|
|
1179
1186
|
- `SurfaceHealth(shape: Shape, options?: { tinyEdgeThreshold?: number; sliverThreshold?: number; }): SurfaceHealthReport`
|
|
1180
1187
|
- `BRepValidity(shape: Shape, options?: BRepValidityOptions): BRepValidityReport` — Validate B-rep/shell/solid structure and return closedness, manifoldness, orientation, and issue diagnostics.
|
|
@@ -58,70 +58,6 @@ bom(tubeLen, "rectangular steel tube", {
|
|
|
58
58
|
| `notes?` | `string` | Free-form notes |
|
|
59
59
|
| `grain?` | `string` | Wood grain direction, e.g. "long", "cross" |
|
|
60
60
|
|
|
61
|
-
#### `robotExport(options: RobotExportOptions): CollectedRobotExport` — Compatibility shim for SDF/URDF robot package metadata.
|
|
62
|
-
|
|
63
|
-
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.
|
|
64
|
-
|
|
65
|
-
`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:
|
|
66
|
-
|
|
67
|
-
- Mesh-based inertia tensors (full 6-component, not bounding-box approximations)
|
|
68
|
-
- Separate collision meshes
|
|
69
|
-
- Joint limits, effort/velocity/damping/friction metadata from assembly joints
|
|
70
|
-
|
|
71
|
-
**Collision mesh modes** (set per-link via `links["PartName"].collision`):
|
|
72
|
-
|
|
73
|
-
| Mode | Description | Default |
|
|
74
|
-
|------|-------------|---------|
|
|
75
|
-
| `'convex'` | Convex hull (separate `_collision.stl`) | Yes |
|
|
76
|
-
| `'box'` | AABB primitive — fastest physics | |
|
|
77
|
-
| `'visual'` | Same mesh as visual — exact but slow | |
|
|
78
|
-
| `'none'` | No collision geometry | |
|
|
79
|
-
|
|
80
|
-
**Unit conventions:**
|
|
81
|
-
|
|
82
|
-
- Revolute `velocity` is in degrees/second in Forge; exporters convert to rad/s.
|
|
83
|
-
- Prismatic distances are in mm in Forge; exported in meters.
|
|
84
|
-
- `massKg` is preferred; `densityKgM3` is used when mass is unknown.
|
|
85
|
-
- 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.
|
|
86
|
-
|
|
87
|
-
**Legacy example**
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
robotExport({
|
|
91
|
-
assembly: rover, // assembly() with parts + revolute wheel joints
|
|
92
|
-
modelName: "Scout",
|
|
93
|
-
links: { Chassis: { massKg: 10 }, "Left Wheel": { massKg: 0.8 } },
|
|
94
|
-
plugins: {
|
|
95
|
-
diffDrive: {
|
|
96
|
-
leftJoints: ["leftWheel"], rightJoints: ["rightWheel"],
|
|
97
|
-
wheelSeparationMm: 280, wheelRadiusMm: 60,
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
world: { generateDemoWorld: true },
|
|
101
|
-
});
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
**Preferred CLI usage**
|
|
105
|
-
|
|
106
|
-
```bash
|
|
107
|
-
forgecad export sdf model.forge.js # SDF package (Gazebo/Ignition)
|
|
108
|
-
forgecad export urdf model.forge.js # URDF package (ROS/PyBullet/MuJoCo)
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
**`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`
|
|
112
|
-
|
|
113
|
-
`RobotLinkExportOptions`: `{ massKg?: number, densityKgM3?: number, collision?: "visual" | "convex" | "box" | "none" }`
|
|
114
|
-
|
|
115
|
-
`RobotJointExportOptions`: `{ effort?: number, velocity?: number, damping?: number, friction?: number }`
|
|
116
|
-
|
|
117
|
-
**`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`
|
|
118
|
-
|
|
119
|
-
`RobotJointStatePublisherOptions`: `{ enabled?: boolean, joints?: string[], topic?: string, updateRate?: number }`
|
|
120
|
-
|
|
121
|
-
`RobotWorldOptions`: `{ name?: string, generateDemoWorld?: boolean, spawnPose?: RobotPose6, keyboardTeleop?: RobotWorldKeyboardTeleopOptions }`
|
|
122
|
-
|
|
123
|
-
`RobotWorldKeyboardTeleopOptions`: `{ enabled?: boolean, linearStep?: number, angularStep?: number }`
|
|
124
|
-
|
|
125
61
|
#### `dim()` — Add a dimension annotation between two points, or along an entity.
|
|
126
62
|
|
|
127
63
|
Overloads:
|
|
@@ -24,12 +24,12 @@ lib, Line2D, linearPattern, linearPattern2d, loadFont, loft, Loft, mirrorCopy
|
|
|
24
24
|
mock, ngon, NurbsCurve3D, NurbsSurface, offsetSolid, param, Param, path
|
|
25
25
|
Point2D, Points, polygon, polygonVertices, port, Product, ProductPanelBuilder, ProductRibbonBuilder
|
|
26
26
|
ProductSkin, ProductSkinBuilder, ProductStationBuilder, ProductSurfaceBuilder, ProductSurfaceRef, projectToPlane, queueMicrotask, rect
|
|
27
|
-
Rectangle2D,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
Rectangle2D, roundedRect, Route3D, scene, Sculpt, sdf, SdfShape, selectEdge
|
|
28
|
+
selectEdges, self, setActiveBackend, setImmediate, setInterval, setTimeout, Shape, ShapeGroup
|
|
29
|
+
sheetMetal, SheetMetalPart, sheetStock, Sim, Sketch, sketchToDxf, sketchToSvg, slot
|
|
30
|
+
SolvedAssembly, spec, sphere, spline2d, stroke, Surface, SurfaceBody, SurfaceMembers
|
|
31
|
+
sweep, text2d, textWidth, torus, toShape, Transform, union, union2d
|
|
32
|
+
variableSweep, verify, Viewport, window, Wood, Wrap
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
`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.
|