forgecad 0.1.1 → 0.1.2
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/dist/assets/{evalWorker-DuS4V-H5.js → evalWorker-1m873KWd.js} +107 -107
- package/dist/assets/{index-d60dJDhX.js → index-Dvz3nSDc.js} +342 -326
- package/dist/assets/{manifold-DEOPQqeC.js → manifold-C38sUiKu.js} +1 -1
- package/dist/assets/{manifold-cL7A7HeM.js → manifold-Dk2u-lhj.js} +1 -1
- package/dist/assets/{manifold-DbvY5u9x.js → manifold-rOWQW9fU.js} +1 -1
- package/dist/assets/{reportWorker-GZVKtf9S.js → reportWorker-Cj587shw.js} +129 -129
- package/dist/index.html +1 -1
- package/dist-cli/forgecad.js +204 -19
- package/dist-skill/SKILL.md +31 -4561
- package/dist-skill/docs/API/README.md +24 -0
- package/dist-skill/docs/API/guides/modeling-recipes.md +246 -0
- package/dist-skill/docs/API/internals/compiler.md +300 -0
- package/dist-skill/docs/API/internals/manifold.md +7 -0
- package/dist-skill/docs/API/model-building/README.md +31 -0
- package/dist-skill/docs/API/model-building/assembly.md +205 -0
- package/dist-skill/docs/API/model-building/coordinate-system.md +43 -0
- package/dist-skill/docs/API/model-building/entities.md +282 -0
- package/dist-skill/docs/API/model-building/geometry-conventions.md +104 -0
- package/dist-skill/docs/API/model-building/positioning.md +170 -0
- package/dist-skill/docs/API/model-building/reference.md +1936 -0
- package/dist-skill/docs/API/model-building/sheet-metal.md +180 -0
- package/dist-skill/docs/API/model-building/sketch-anchor.md +32 -0
- package/dist-skill/docs/API/model-building/sketch-booleans.md +101 -0
- package/dist-skill/docs/API/model-building/sketch-core.md +68 -0
- package/dist-skill/docs/API/model-building/sketch-extrude.md +57 -0
- package/dist-skill/docs/API/model-building/sketch-on-face.md +98 -0
- package/dist-skill/docs/API/model-building/sketch-operations.md +92 -0
- package/dist-skill/docs/API/model-building/sketch-path.md +70 -0
- package/dist-skill/docs/API/model-building/sketch-primitives.md +104 -0
- package/dist-skill/docs/API/model-building/sketch-transforms.md +60 -0
- package/dist-skill/docs/API/output/bom.md +53 -0
- package/dist-skill/docs/API/output/brep-export.md +82 -0
- package/dist-skill/docs/API/output/dimensions.md +62 -0
- package/dist-skill/docs/API/runtime/viewport.md +229 -0
- package/dist-skill/docs/CLI.md +672 -0
- package/dist-skill/docs/CODING.md +345 -0
- package/dist-skill/docs/PROGRAM-LEAD.md +180 -0
- package/dist-skill/docs/VISION.md +77 -0
- package/examples/api/import-group-assembly.forge.js +34 -0
- package/examples/api/import-group-source.forge.js +35 -0
- package/package.json +1 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# ForgeCAD API Docs
|
|
2
|
+
|
|
3
|
+
This folder is split by purpose so model-building guidance stays separate from adjacent runtime, output, and internal material.
|
|
4
|
+
|
|
5
|
+
## Canonical Read Path for Model Building
|
|
6
|
+
|
|
7
|
+
If an AI agent or contributor needs everything required to write or modify ForgeCAD models, read:
|
|
8
|
+
|
|
9
|
+
1. [model-building/README.md](model-building/README.md)
|
|
10
|
+
2. Every file listed there, in order
|
|
11
|
+
3. Relevant runnable examples in `examples/api/`
|
|
12
|
+
|
|
13
|
+
That `model-building/` set is the complete script-authoring surface for geometry and assemblies.
|
|
14
|
+
|
|
15
|
+
## Adjacent API Areas
|
|
16
|
+
|
|
17
|
+
- [runtime/viewport.md](runtime/viewport.md): viewport-only controls such as cut planes, exploded-view overrides, runtime joints, and helper overlays
|
|
18
|
+
- [output/bom.md](output/bom.md): BOM/report metadata APIs
|
|
19
|
+
- [output/dimensions.md](output/dimensions.md): dimension annotations for viewport/report output
|
|
20
|
+
- [output/brep-export.md](output/brep-export.md): exact STEP/BREP export parity matrix
|
|
21
|
+
- [guides/modeling-recipes.md](guides/modeling-recipes.md): patterns, best practices, debugging, and example snippets
|
|
22
|
+
- [internals/manifold.md](internals/manifold.md): implementation notes about the current geometry backend
|
|
23
|
+
|
|
24
|
+
Read those only when the task explicitly involves that area.
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# Modeling Recipes
|
|
2
|
+
|
|
3
|
+
This file collects patterns, best practices, debugging tips, and example snippets that are useful once you already know the model-building API.
|
|
4
|
+
|
|
5
|
+
## Iteration Bias
|
|
6
|
+
|
|
7
|
+
- For unfamiliar or high-risk geometry work, start in a notebook and keep setup, experiments, and validation in separate cells until the structure is obvious.
|
|
8
|
+
- Default to a buildable first pass instead of a long proposal when the user clearly wants geometry changed.
|
|
9
|
+
- Replace a broken or incoherent model wholesale when that is faster and cleaner than incremental patching.
|
|
10
|
+
- Keep printed hardware structurally honest: use it for guides, spacers, retainers, and moderate-load mechanisms; use wood or metal for primary strength.
|
|
11
|
+
- Validate early with `forgecad run <file>` and refine from the actual runtime result.
|
|
12
|
+
- Prefer a few clean part files over one giant script once a design has repeated hardware or a small mechanism.
|
|
13
|
+
|
|
14
|
+
Notebook helpers worth using during iteration:
|
|
15
|
+
|
|
16
|
+
- `show(...)` pins the current intermediate geometry in the viewport
|
|
17
|
+
- `forgecad notebook view <file> preview` prints the preview cell with stored outputs in the terminal
|
|
18
|
+
- `forgecad run <file>.forge-notebook.json` validates the preview cell and runs the usual spatial analysis
|
|
19
|
+
|
|
20
|
+
## Common Patterns
|
|
21
|
+
|
|
22
|
+
### Parametric Box with Holes
|
|
23
|
+
```javascript
|
|
24
|
+
const w = param("Width", 80, { min: 40, max: 150, unit: "mm" });
|
|
25
|
+
const h = param("Height", 60, { min: 30, max: 100, unit: "mm" });
|
|
26
|
+
const t = param("Thickness", 5, { min: 2, max: 10, unit: "mm" });
|
|
27
|
+
const holeD = param("Hole Diameter", 8, { min: 4, max: 20, unit: "mm" });
|
|
28
|
+
|
|
29
|
+
const base = box(w, h, t);
|
|
30
|
+
const hole = cylinder(t + 2, holeD / 2).translate(w / 2, h / 2, -1);
|
|
31
|
+
|
|
32
|
+
return base.subtract(hole);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Hollow Shell (Wall Thickness)
|
|
36
|
+
```javascript
|
|
37
|
+
const outer = param("Outer Size", 50, { min: 20, max: 100, unit: "mm" });
|
|
38
|
+
const wall = param("Wall", 3, { min: 1, max: 10, unit: "mm" });
|
|
39
|
+
|
|
40
|
+
const outerBox = box(outer, outer, outer, true);
|
|
41
|
+
const innerBox = box(outer - 2 * wall, outer - 2 * wall, outer - 2 * wall, true);
|
|
42
|
+
|
|
43
|
+
return outerBox.subtract(innerBox);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Array/Pattern
|
|
47
|
+
```javascript
|
|
48
|
+
const count = param("Count", 5, { min: 2, max: 10 });
|
|
49
|
+
const spacing = param("Spacing", 15, { min: 5, max: 30, unit: "mm" });
|
|
50
|
+
|
|
51
|
+
let shapes = [];
|
|
52
|
+
for (let i = 0; i < count; i++) {
|
|
53
|
+
shapes.push(cylinder(10, 5).translate(i * spacing, 0, 0));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return union(...shapes);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Sketch-Based Design
|
|
60
|
+
```javascript
|
|
61
|
+
const sides = param("Sides", 6, { min: 3, max: 12 });
|
|
62
|
+
const radius = param("Radius", 25, { min: 10, max: 50, unit: "mm" });
|
|
63
|
+
const height = param("Height", 60, { min: 20, max: 120, unit: "mm" });
|
|
64
|
+
const wall = param("Wall", 3, { min: 1, max: 8, unit: "mm" });
|
|
65
|
+
|
|
66
|
+
const outer = ngon(sides, radius);
|
|
67
|
+
const inner = ngon(sides, radius - wall);
|
|
68
|
+
const profile = outer.subtract(inner);
|
|
69
|
+
|
|
70
|
+
return profile.extrude(height, { twist: 45, divisions: 32 });
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Rounded Profiles
|
|
74
|
+
```javascript
|
|
75
|
+
const base = rect(50, 30).offset(-3, 'Round').offset(3, 'Round');
|
|
76
|
+
return base.extrude(10);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Use that pattern when every convex corner should round. For mixed sharp-and-rounded outlines, fillet only the intended vertices instead:
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
const roofPoints = [
|
|
83
|
+
[0, 0],
|
|
84
|
+
[90, 0],
|
|
85
|
+
[90, 44],
|
|
86
|
+
[66, 74],
|
|
87
|
+
[45, 86],
|
|
88
|
+
[24, 74],
|
|
89
|
+
[0, 44],
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
const roof = filletCorners(roofPoints, [
|
|
93
|
+
{ index: 3, radius: 19 },
|
|
94
|
+
{ index: 4, radius: 19 },
|
|
95
|
+
{ index: 5, radius: 19 },
|
|
96
|
+
]);
|
|
97
|
+
|
|
98
|
+
return roof.extrude(12);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Chamfers and Fillets
|
|
102
|
+
```javascript
|
|
103
|
+
const part = box(50, 50, 20);
|
|
104
|
+
const chamfer = box(10, 60, 10)
|
|
105
|
+
.rotate(0, 45, 0)
|
|
106
|
+
.translate(50, -5, 15);
|
|
107
|
+
|
|
108
|
+
return part.subtract(chamfer);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Choosing the right sketch-rounding tool
|
|
112
|
+
|
|
113
|
+
- `offset(-r).offset(+r)` for rounding every convex corner of a closed outline
|
|
114
|
+
- `stroke(points, width, 'Round')` for centerline-based geometry such as ribs or traces
|
|
115
|
+
- `hull2d()` of circles for a blended cap/capsule silhouette
|
|
116
|
+
- `filletCorners(points, ...)` for selective true-corner fillets on mixed profiles
|
|
117
|
+
|
|
118
|
+
## Best Practices
|
|
119
|
+
|
|
120
|
+
### Performance
|
|
121
|
+
- Boolean operations are expensive; minimize them
|
|
122
|
+
- Use parameters for values that might change
|
|
123
|
+
- Avoid deep nesting of operations in loops
|
|
124
|
+
|
|
125
|
+
### Readability
|
|
126
|
+
```javascript
|
|
127
|
+
const base = box(100, 100, 10);
|
|
128
|
+
const hole = cylinder(12, 8);
|
|
129
|
+
const result = base.subtract(hole.translate(50, 50, 0));
|
|
130
|
+
return result;
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Prefer named intermediate values over deeply nested one-liners.
|
|
134
|
+
|
|
135
|
+
### Units
|
|
136
|
+
- All dimensions are millimeters by default
|
|
137
|
+
- Angles are degrees
|
|
138
|
+
- Use the `unit` parameter option when it helps the reader
|
|
139
|
+
|
|
140
|
+
### Centering
|
|
141
|
+
```javascript
|
|
142
|
+
const centered = box(50, 50, 50, true).translate(x, y, z);
|
|
143
|
+
const corner = box(50, 50, 50).translate(x - 25, y - 25, z - 25);
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Centered primitives are usually easier to position.
|
|
147
|
+
|
|
148
|
+
## Debugging
|
|
149
|
+
|
|
150
|
+
### Console Output
|
|
151
|
+
```javascript
|
|
152
|
+
console.log("Width:", width);
|
|
153
|
+
console.log("Volume:", shape.volume());
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Incremental Building
|
|
157
|
+
```javascript
|
|
158
|
+
const base = box(50, 50, 10);
|
|
159
|
+
// return base;
|
|
160
|
+
|
|
161
|
+
const withHole = base.subtract(cylinder(12, 5).translate(25, 25, 0));
|
|
162
|
+
// return withHole;
|
|
163
|
+
|
|
164
|
+
return withHole.add(cylinder(20, 3).translate(25, 25, 10));
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
For sketch-heavy work, compare the raw profile and the rounded profile before extruding:
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
const raw = polygon(roofPoints);
|
|
171
|
+
const rounded = filletCorners(roofPoints, [
|
|
172
|
+
{ index: 3, radius: 19 },
|
|
173
|
+
{ index: 4, radius: 19 },
|
|
174
|
+
{ index: 5, radius: 19 },
|
|
175
|
+
]);
|
|
176
|
+
|
|
177
|
+
return [
|
|
178
|
+
{ name: "Raw", sketch: raw },
|
|
179
|
+
{ name: "Rounded", sketch: rounded.translate(120, 0) },
|
|
180
|
+
];
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Error Handling
|
|
184
|
+
|
|
185
|
+
Common errors:
|
|
186
|
+
- `"Kernel not initialized"` - internal/runtime issue, reload the app
|
|
187
|
+
- `"Cannot read property of undefined"` - usually a bad variable name or missing declaration
|
|
188
|
+
- invalid geometry - commonly caused by zero dimensions or self-intersecting sketches
|
|
189
|
+
- script execution error - inspect the JS error in console output
|
|
190
|
+
|
|
191
|
+
## Example Snippets
|
|
192
|
+
|
|
193
|
+
### Parametric Phone Stand
|
|
194
|
+
```javascript
|
|
195
|
+
const width = param("Width", 80, { min: 40, max: 150, unit: "mm" });
|
|
196
|
+
const depth = param("Depth", 60, { min: 30, max: 100, unit: "mm" });
|
|
197
|
+
const thick = param("Thickness", 5, { min: 2, max: 15, unit: "mm" });
|
|
198
|
+
const backH = param("Back Height", 40, { min: 20, max: 80, unit: "mm" });
|
|
199
|
+
const cableD = param("Cable Hole", 8, { min: 4, max: 15, unit: "mm" });
|
|
200
|
+
|
|
201
|
+
const base = box(width, depth, thick);
|
|
202
|
+
const back = box(width, thick, backH).translate(0, depth - thick, thick);
|
|
203
|
+
const lip = box(width, 10, 8).translate(0, 0, thick);
|
|
204
|
+
const hole = cylinder(thick + 2, cableD / 2)
|
|
205
|
+
.rotate(90, 0, 0)
|
|
206
|
+
.translate(width / 2, depth / 2, -1);
|
|
207
|
+
|
|
208
|
+
return union(base, back, lip).subtract(hole);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Multi-Object Scene with Colors
|
|
212
|
+
```javascript
|
|
213
|
+
const base = box(100, 100, 5).color('#888888');
|
|
214
|
+
const col1 = cylinder(40, 5).translate(20, 20, 5).color('#cc4444');
|
|
215
|
+
const col2 = cylinder(40, 5).translate(80, 20, 5).color('#4444cc');
|
|
216
|
+
const col3 = cylinder(40, 5).translate(50, 80, 5).color('#44cc44');
|
|
217
|
+
const top = box(100, 100, 3).translate(0, 0, 45).color('#888888');
|
|
218
|
+
|
|
219
|
+
return [
|
|
220
|
+
{ name: "Base", shape: base },
|
|
221
|
+
{ name: "Column A", shape: col1 },
|
|
222
|
+
{ name: "Column B", shape: col2 },
|
|
223
|
+
{ name: "Column C", shape: col3 },
|
|
224
|
+
{ name: "Top", shape: top },
|
|
225
|
+
];
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Entity-Based Design with Topology
|
|
229
|
+
```javascript
|
|
230
|
+
const baseRect = rectangle(0, 0, 80, 60);
|
|
231
|
+
const base = baseRect.extrude(20);
|
|
232
|
+
|
|
233
|
+
const result = filletEdge(base.toShape(), base.edge('vert-br'), 8, [-1, -1])
|
|
234
|
+
.hole(base.face('top'), { diameter: 6, u: -16, v: 10, depth: 8 });
|
|
235
|
+
|
|
236
|
+
const holes = circularPattern(
|
|
237
|
+
cylinder(25, 4).translate(40, 30, -1),
|
|
238
|
+
4, 40, 30,
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
return result.subtract(holes);
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Use the original tracked body (`base`) when you need semantic faces after edge finishing, and keep using its untouched sibling vertical tracked edges if you apply another supported fillet/chamfer later. Those sibling edges can now also survive a later supported union when the compiler still records one preserved propagated edge lineage for them. The currently selected finished edge is still recorded as a merged descendant set, so Forge does not claim a new durable tracked edge for that rewritten corner yet.
|
|
245
|
+
|
|
246
|
+
For larger runnable examples, read `examples/api/`.
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# Forge Compiler Architecture
|
|
2
|
+
|
|
3
|
+
This is the durable architecture record for ForgeCAD's multi-backend modeling system.
|
|
4
|
+
|
|
5
|
+
If you add or refactor geometry features, read this first.
|
|
6
|
+
|
|
7
|
+
## Core Position
|
|
8
|
+
|
|
9
|
+
Forge should not invent a new CAD language or a new geometry kernel.
|
|
10
|
+
|
|
11
|
+
Forge should:
|
|
12
|
+
|
|
13
|
+
- keep JS/TS as the host language
|
|
14
|
+
- keep Forge's semantic feature model as the source of truth
|
|
15
|
+
- lower that model into different geometry backends intentionally
|
|
16
|
+
- make capability gaps explicit in diagnostics and tests
|
|
17
|
+
|
|
18
|
+
The unique thing to protect is not backend code. It is Forge's code-first modeling layer:
|
|
19
|
+
|
|
20
|
+
- browser-first iteration
|
|
21
|
+
- parametric code as the authoring format
|
|
22
|
+
- composable multi-file projects
|
|
23
|
+
- AI-writable design code
|
|
24
|
+
- explicit provenance and backend visibility
|
|
25
|
+
|
|
26
|
+
## What To Steal
|
|
27
|
+
|
|
28
|
+
We should steal proven ideas aggressively.
|
|
29
|
+
|
|
30
|
+
Steal from Fusion 360 / Onshape / FeatureScript:
|
|
31
|
+
|
|
32
|
+
- semantic feature graphs
|
|
33
|
+
- workplanes and sketch planes as first-class modeling context
|
|
34
|
+
- query/reference systems for faces, edges, bodies, and feature results
|
|
35
|
+
- feature definitions that lower into kernels instead of directly calling them from UI/API code
|
|
36
|
+
|
|
37
|
+
Steal from CadQuery / build123d / replicad:
|
|
38
|
+
|
|
39
|
+
- OCCT execution patterns
|
|
40
|
+
- exact solid feature expectations
|
|
41
|
+
- practical scripting ergonomics around sketches, planes, and feature builders
|
|
42
|
+
|
|
43
|
+
Steal from OCAF-style document systems:
|
|
44
|
+
|
|
45
|
+
- durable reference identity
|
|
46
|
+
- explicit ownership of topology/reference propagation
|
|
47
|
+
|
|
48
|
+
Do not steal:
|
|
49
|
+
|
|
50
|
+
- a separate Forge DSL
|
|
51
|
+
- backend object models as the user-facing API
|
|
52
|
+
- exporter-only side systems that bypass the compiler
|
|
53
|
+
|
|
54
|
+
## The Make-Or-Break Layer
|
|
55
|
+
|
|
56
|
+
This is where Forge will likely succeed or fail:
|
|
57
|
+
|
|
58
|
+
- the semantic feature graph
|
|
59
|
+
- the compiled-scene routing layer
|
|
60
|
+
- the reference / workplane / query system
|
|
61
|
+
|
|
62
|
+
Why:
|
|
63
|
+
|
|
64
|
+
- primitives, booleans, extrudes, and revolves are not the hard part
|
|
65
|
+
- real mechanical design depends on downstream face- and edge-driven features
|
|
66
|
+
- those features only stay usable if references survive feature chains predictably
|
|
67
|
+
|
|
68
|
+
If this layer is weak, the repo will accumulate:
|
|
69
|
+
|
|
70
|
+
- backend-specific feature code at callsites
|
|
71
|
+
- export-only implementations
|
|
72
|
+
- brittle face-name assumptions
|
|
73
|
+
- features that work in demos but collapse in real parts
|
|
74
|
+
|
|
75
|
+
If this layer is strong, future features stay additive.
|
|
76
|
+
|
|
77
|
+
## Success Criteria
|
|
78
|
+
|
|
79
|
+
We are succeeding only if all of these are true:
|
|
80
|
+
|
|
81
|
+
1. Forge compile intent is the source of truth for mainstream part-design features.
|
|
82
|
+
2. Scene-level routing is centralized, inspectable, and reused by export/debug/test flows.
|
|
83
|
+
3. New features do not need ad hoc backend decisions at callsites.
|
|
84
|
+
4. Workplane/reference/query semantics are stable enough for ordinary downstream feature chains.
|
|
85
|
+
5. Most normal Design-workspace features can be added by extending one semantic node family and two lowerers.
|
|
86
|
+
6. Tests catch plan drift, routing drift, and backend-output drift before release.
|
|
87
|
+
|
|
88
|
+
We are failing if any of these become normal:
|
|
89
|
+
|
|
90
|
+
- "this feature only works in export"
|
|
91
|
+
- "this feature only works in Manifold"
|
|
92
|
+
- "this feature only works if you know the right face name"
|
|
93
|
+
- "just add one more backend escape hatch"
|
|
94
|
+
- "the snapshot changed, probably fine"
|
|
95
|
+
|
|
96
|
+
## Contributor Contract
|
|
97
|
+
|
|
98
|
+
When adding a geometry feature:
|
|
99
|
+
|
|
100
|
+
1. Define the Forge semantic intent first.
|
|
101
|
+
2. Decide which domain owns it.
|
|
102
|
+
3. Add or extend the compile node.
|
|
103
|
+
4. Lower it through Manifold.
|
|
104
|
+
5. Lower it through CadQuery/OCCT, or add explicit unsupported diagnostics.
|
|
105
|
+
6. Route it through the scene compiler.
|
|
106
|
+
7. Add invariants and snapshot coverage.
|
|
107
|
+
8. Update permanent docs and the living mission tracker.
|
|
108
|
+
|
|
109
|
+
Do not:
|
|
110
|
+
|
|
111
|
+
- call Manifold or CadQuery directly from user-facing feature APIs unless that code is the backend lowerer itself
|
|
112
|
+
- add exporter-only feature behavior that is invisible to the compiler
|
|
113
|
+
- silently widen or narrow exact coverage
|
|
114
|
+
|
|
115
|
+
## Implementation Path
|
|
116
|
+
|
|
117
|
+
### Phase 1: Compiler Ownership
|
|
118
|
+
|
|
119
|
+
Goal:
|
|
120
|
+
|
|
121
|
+
- every supported feature records Forge intent
|
|
122
|
+
- lowerers consume that intent
|
|
123
|
+
- scene routing is centralized
|
|
124
|
+
|
|
125
|
+
Deliverables:
|
|
126
|
+
|
|
127
|
+
- backend-neutral compile nodes
|
|
128
|
+
- compiled-scene routing and diagnostics
|
|
129
|
+
- snapshot and invariant coverage
|
|
130
|
+
|
|
131
|
+
### Phase 2: Reference / Workplane / Query Model
|
|
132
|
+
|
|
133
|
+
Goal:
|
|
134
|
+
|
|
135
|
+
- face-, edge-, and plane-driven features stop depending on brittle synthetic naming
|
|
136
|
+
|
|
137
|
+
Deliverables:
|
|
138
|
+
|
|
139
|
+
- first-class workplane representation
|
|
140
|
+
- query/reference API for "what this feature means"
|
|
141
|
+
- propagation rules for downstream feature ownership
|
|
142
|
+
|
|
143
|
+
This is the highest-leverage next layer. Without it, `shell`, fillet/chamfer, holes, projection, and sheet-metal-style features will all stay fragile.
|
|
144
|
+
|
|
145
|
+
Initial slice:
|
|
146
|
+
|
|
147
|
+
- sketches placed with `onFace()` should carry semantic workplane/query metadata, not just a resolved 4x4 matrix
|
|
148
|
+
- downstream feature code should be able to ask "which workplane/query produced this?" without reverse-engineering transforms
|
|
149
|
+
|
|
150
|
+
Current progress:
|
|
151
|
+
|
|
152
|
+
- `onFace()` placements now record semantic workplane models on sketches
|
|
153
|
+
- `extrude()` and `revolve()` now preserve that intent in the shape compile graph as a first-class workplane-placement transform instead of collapsing it to an anonymous rigid transform
|
|
154
|
+
- downstream compiler-aware code can now inspect that preserved workplane placement directly
|
|
155
|
+
- that compiler-visible workplane placement now propagates through later shape transforms, so provenance inspection stays aligned with the current transformed feature state
|
|
156
|
+
- both lowerers now execute that preserved workplane-placement intent, and exact export regression tests exercise the CadQuery/OCCT path end-to-end
|
|
157
|
+
- compile-covered feature results now carry compiler-owned query-owner lineage, so parent-body ownership is no longer implicit runtime state
|
|
158
|
+
- `src/forge/queryModel.ts` now defines the shared query/reference contract for face provenance instead of letting workplane and topology code drift separately
|
|
159
|
+
- workplane sources and `FaceRef` values now share that face-query contract when compiler-owned provenance exists
|
|
160
|
+
- `src/forge/queryModel.ts` now also defines the shared edge-query contract for tracked edges and direct edge refs, including selector semantics for whole-edge vs. `start` / `end` / `midpoint` references
|
|
161
|
+
- tracked-topology flows now preserve that edge-query metadata through clone/translate/workplane-placement transforms, and placement invariants assert that tracked edge selectors stay aligned with the actual transformed edge geometry
|
|
162
|
+
- booleans, shell, split/trim flows, and downstream workplane-driven features now preserve that owner lineage through the compile graph instead of erasing it at each feature boundary
|
|
163
|
+
- mirrored results plus `linearPattern()` / `circularPattern()` helper copies now get fresh compiler-owned repeated-result owners when their source shapes stay compile-covered
|
|
164
|
+
- placement and exact-export invariants now check that owner lineage survives ordinary shell-plus-cut-plus-boolean style part workflows
|
|
165
|
+
- topology-changing compile nodes now also carry an explicit backend-neutral `queryPropagation` contract for preserved/created query meaning instead of leaving post-rewrite semantics implicit
|
|
166
|
+
- that shared propagation contract now models propagated face/edge queries, feature-created query slots, and explicit ambiguity/unsupported diagnostics on rewrite-producing results
|
|
167
|
+
- trim/split-by-plane, shell, hole, cut, boolean, and edge-finish rewrites now also declare descendant contracts on top of that propagation kernel
|
|
168
|
+
- the shared descendant-resolution layer turns those lineage inputs into defended singles, face regions/sets, edge chains, or explicit unsupported results instead of making each caller reverse-engineer rewrite heuristics
|
|
169
|
+
- trim/split-by-plane now expose their plane-cap face plus descendant-region contracts for preserved source surfaces, while hole/cut host-face splits and supported boolean difference/intersection descendants stay reviewable as defended regions instead of disappearing behind one generic ambiguity bucket
|
|
170
|
+
- boolean rewrites now consume that same contract: supported unions still preserve operand canonical-face/query lineage when the source owners stay distinct, and coplanar/multi-member descendants can now surface as defended face sets instead of only masked name conflicts
|
|
171
|
+
- shell, hole, and cut now layer defended created-face slots plus defended descendant regions on top of that propagation kernel instead of leaving all post-rewrite face meaning as placeholders
|
|
172
|
+
- compile-covered `Shape.face(name)` resolution now reads from the compile graph plus the descendant layer, so supported shell inner walls, blind-hole floors, cut-created walls, split host faces, and defended boolean face sets can produce real `FaceRef` values after topology rewrites
|
|
173
|
+
- non-canonical `onFace(shape, 'inner-side-right', ...)` placement now routes through that same compiler-owned face resolver, while direct `FaceRef` placements preserve created-face/propagated-face provenance instead of collapsing everything back to anonymous refs
|
|
174
|
+
- `src/forge/kernel.ts` and the compiler inspection surface now expose collected topology-rewrite propagation plus descendant contracts directly, and the placement/compiler invariants assert that those contracts stay inspectable and deterministic through later transforms
|
|
175
|
+
- `forgecad check query-propagation` now snapshots both the propagation surface and the descendant contracts directly, so defended plane-cap faces, split-face regions, face sets, merged-edge chains, and explicit unsupported rewrite boundaries stay reviewable without wading through the full compiler-scene baseline
|
|
176
|
+
|
|
177
|
+
Still missing:
|
|
178
|
+
|
|
179
|
+
- universal durable face/edge identity across topology-changing operations
|
|
180
|
+
- mesh/SDF rewrite families still need their own explicit descendant contracts instead of borrowed BREP-style assumptions
|
|
181
|
+
- shared edge-query selectors exist for tracked topology, but topology-changing features still do not produce new single-edge ownership for most rewritten/created edges beyond today's defended preserved-edge and edge-chain subset
|
|
182
|
+
- stable downstream face/edge references beyond today's defended single/region/set/chain subset still need the follow-on work in tasks 180, 190, and 195
|
|
183
|
+
|
|
184
|
+
### Phase 3: Mainstream Feature Families
|
|
185
|
+
|
|
186
|
+
Goal:
|
|
187
|
+
|
|
188
|
+
- dual-lower the ordinary part-design stack
|
|
189
|
+
|
|
190
|
+
Priority order:
|
|
191
|
+
|
|
192
|
+
- `shell`
|
|
193
|
+
- fillet / chamfer
|
|
194
|
+
- holes / patterned cuts
|
|
195
|
+
- projection and sketch-on-face refinement
|
|
196
|
+
- mirror / pattern workflows driven by semantic references
|
|
197
|
+
|
|
198
|
+
Current progress:
|
|
199
|
+
|
|
200
|
+
- `shell()` is now compiler-owned as the first mainstream exact feature-family slice instead of being left for exporter-only logic
|
|
201
|
+
- both lowerers consume the same semantic `shell` node and rewrite supported cases into backend-native boolean/extrude/cylinder plans
|
|
202
|
+
- `shape.hole()` and `shape.cutout()` now form a compiler-owned hole/cut workflow slice anchored to the shared face-query/workplane model
|
|
203
|
+
- through holes, blind holes, counterbores, countersinks, and planar `upToFace` hole/cut extents now lower through both Manifold and CadQuery/OCCT from that shared semantic node family
|
|
204
|
+
- shell, hole, and cut now expose defended named created-face subsets on top of the topology-rewrite kernel, so downstream features can target inner shell walls, blind-hole floors, and supported cut walls/floors without falling back to anonymous runtime placement
|
|
205
|
+
- richer hole variants now also expose defended `counterbore-floor`, `counterbore-wall`, and `countersink-wall` created-face slots where Forge can model them directly
|
|
206
|
+
- `filletEdge()` and `chamferEdge()` now form a first compiler-owned tracked-edge finishing slice for supported vertical edges on compile-covered `box()` and `rectangle(...).extrude(...)` bodies
|
|
207
|
+
- the post-rewrite edge-query layer now also defends untouched sibling vertical edges after those supported edge-finish rewrites, plus later supported boolean-union descendants when one preserved propagated-edge lineage stays explicit
|
|
208
|
+
- regression coverage now includes compiler snapshots plus exact-export invariants for `shell()`
|
|
209
|
+
- regression coverage now also includes exact/runtime/export checks for the supported hole/cut workflow subset
|
|
210
|
+
- regression coverage now also includes API, placement-owner, query-propagation, compiler-snapshot, exact-plan, corpus, and end-to-end export checks for the broadened tracked-edge fillet/chamfer subset
|
|
211
|
+
- the regression suite now also includes a file-backed ordinary-parts corpus under `examples/compiler-corpus/`, so shell, richer hole/cut workflows, projection replay, trim-created faces, repeated descendants, and finishing flows are exercised together instead of only as isolated unit slices
|
|
212
|
+
- the MLP closeout review surface now lives in that corpus plus `forgecad check compiler`, `forgecad check query-propagation`, and `forgecad check brep`, so the defended subset is reviewable from the repo instead of from tribal knowledge
|
|
213
|
+
- mirrored downstream features and helper-driven linear/circular repetition now preserve repeated-result ownership on top of the shared face-query backbone
|
|
214
|
+
- supported boolean unions now also preserve owner-scoped canonical face queries from repeated descendants, and compiler regressions cover both explicit duplicate-owner merge ambiguity and later boolean chains that inherit those propagated queries
|
|
215
|
+
- exact export regression coverage now includes a repeated-feature part where a mirrored descendant drives a downstream workplane feature inside a boolean chain
|
|
216
|
+
- `projectToPlane()` sketches now keep an explicit projection node in the compiler graph instead of collapsing immediately to anonymous runtime geometry
|
|
217
|
+
- compile-covered `Sketch.onFace(shape, name)` resolution now prefers the defended face-query table on `Shape` targets, so supported boolean-preserved names and explicit repeated-descendant `FaceRef`s stay visible to later features instead of falling back to anonymous canonical heuristics
|
|
218
|
+
- the supported exact subset can now replay projection-driven follow-on features when the source reduces to one defended planar projection basis: placed straight extrusions, compatible shell/hole/cut descendants, and boolean unions of compatible projected operands all stay aligned on matching parallel target planes
|
|
219
|
+
|
|
220
|
+
Current limits:
|
|
221
|
+
|
|
222
|
+
- `shell()` v1 only covers compile-covered `box()`, `cylinder()`, and straight `extrude()` bases with optional `top` / `bottom` openings, while defended named created faces currently cover the exact profile families Forge can model directly (`rect`, `roundedRect`, `circle`)
|
|
223
|
+
- `shape.hole()` still only covers circular holes, and `shape.cutout()` still only covers sketches already placed with `onFace(...)`
|
|
224
|
+
- `filletEdge()` / `chamferEdge()` v1 cover tracked vertical edges on compile-covered `box()` and `rectangle(...).extrude(...)` bodies plus preserved propagated sibling edges through supported edge-finish and boolean-union chains; the selected rewritten edge now resolves as an explicit descendant edge-chain for inspection/debug, but not yet as a new single finishable edge target
|
|
225
|
+
- two-sided extents, tapered cutouts, and thread metadata are now supported; combined counterbore+countersink heads, modeled helical threads, and broader durable identity beyond today's defended shell/hole/cut created-face subset are still missing
|
|
226
|
+
- `upToFace` currently requires a planar termination face parallel to the feature direction, but defended split termination faces can now stay queryable as descendant regions where Forge still owns the source plane
|
|
227
|
+
- boolean/pattern propagation currently defends owner-scoped canonical face lineage through supported unions, and the descendant layer can now expose some post-merge/post-difference results as face sets/regions, but broader durable per-face ownership after arbitrary merged topology changes is still incomplete
|
|
228
|
+
- repeated-feature ownership currently tracks repeated bodies and mirrored descendants, not durable per-face identity after merged pattern topology changes
|
|
229
|
+
- shell, hole/cut, tracked-edge finishing, and repeated-feature workflows now preserve parent-body ownership lineage, but stable downstream face/edge ownership after topology-changing edits is still not solved, which is why richer boolean-difference/intersection targets and broader fillet/chamfer workflows remain harder next layers
|
|
230
|
+
- projection replay still rejects boolean difference/intersection sources, trim/fillet/chamfer silhouette changes, and non-parallel projection bases with explicit compiler diagnostics instead of silently pretending those paths are exact-safe
|
|
231
|
+
|
|
232
|
+
### Phase 4: Higher-Order Workflows
|
|
233
|
+
|
|
234
|
+
Goal:
|
|
235
|
+
|
|
236
|
+
- features like sheet metal, advanced library helpers, and richer manufacturing flows build on the same semantic core
|
|
237
|
+
|
|
238
|
+
Current progress:
|
|
239
|
+
|
|
240
|
+
- `sheetMetal()` now exists as the first dedicated higher-order semantic family on top of the descendant-resolution layer
|
|
241
|
+
- one sheet-metal model now lowers to both a folded solid and a flat pattern instead of splitting folded/export logic across backend-specific codepaths
|
|
242
|
+
- named `panel`, `flange-*`, and `bend-*` descendants now flow through the shared face-descendant machinery, so downstream cutouts can still expose honest region/set semantics after topology rewrites
|
|
243
|
+
- the maintained `folded-service-panel-cover` proof part now lives in the API examples, compiler corpus, query-propagation snapshots, API invariants, and exact BREP checks
|
|
244
|
+
|
|
245
|
+
These higher-order families should keep arriving only after the shared reference/workplane/query layer is credible enough to defend them honestly.
|
|
246
|
+
|
|
247
|
+
## Current Architectural Boundary
|
|
248
|
+
|
|
249
|
+
Today, the intended compiler boundary is:
|
|
250
|
+
|
|
251
|
+
```text
|
|
252
|
+
Forge scripts
|
|
253
|
+
-> Forge semantic feature graph
|
|
254
|
+
-> compiled scene + capability routing
|
|
255
|
+
-> Manifold lowerer / CadQuery-OCCT lowerer / faceted fallback
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Future feature work should strengthen this boundary, not route around it.
|
|
259
|
+
|
|
260
|
+
## Next Achievable CAD Families
|
|
261
|
+
|
|
262
|
+
Once the descendant-resolution layer is in place, the next credible expansion lanes are:
|
|
263
|
+
|
|
264
|
+
- richer hole and cut variants
|
|
265
|
+
- broader shell workflows
|
|
266
|
+
- broader fillet/chamfer workflows
|
|
267
|
+
- stronger projection and sketch-on-face flows
|
|
268
|
+
- richer sheet-metal corner and detail workflows on top of the new semantic family
|
|
269
|
+
- manufacturing outputs such as flat patterns and DXF/SVG profile export
|
|
270
|
+
- toolbox and library feature families
|
|
271
|
+
- stronger assembly metadata and exact/faceted route visibility
|
|
272
|
+
|
|
273
|
+
These are all good fits for the compiler architecture because they can be expressed as Forge-owned semantic intent and lowered intentionally into both backends.
|
|
274
|
+
|
|
275
|
+
## Bigger Leap Areas
|
|
276
|
+
|
|
277
|
+
Some CAD-adjacent areas are still important, but they are a bigger leap than the current compiler program:
|
|
278
|
+
|
|
279
|
+
- arbitrary direct editing over imported or heavily rewritten BReps
|
|
280
|
+
- advanced surfacing or subD/T-spline workflows
|
|
281
|
+
- CAM
|
|
282
|
+
- simulation / FEA
|
|
283
|
+
- full enterprise document/PDM systems
|
|
284
|
+
- full large-assembly and mate-solver parity with major desktop CAD tools
|
|
285
|
+
|
|
286
|
+
Keep these visible, but do not plan them as if they were just another feature module on the current part-design stack.
|
|
287
|
+
|
|
288
|
+
## Legacy Cleanup Rule
|
|
289
|
+
|
|
290
|
+
Yes, the old architecture needs cleanup.
|
|
291
|
+
|
|
292
|
+
No, that should not happen as a single flag-day rewrite.
|
|
293
|
+
|
|
294
|
+
The rule is:
|
|
295
|
+
|
|
296
|
+
1. add compiler-owned replacements first
|
|
297
|
+
2. fence old bypass paths so new work cannot extend them
|
|
298
|
+
3. retire legacy shims once supported features and examples no longer need them
|
|
299
|
+
|
|
300
|
+
That keeps the repo honest without destabilizing active work.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Underneath ForgeCAD currently uses Manifold for browser-time geometry work.
|
|
2
|
+
|
|
3
|
+
Implementation note:
|
|
4
|
+
- Manifold is Y-up internally
|
|
5
|
+
- ForgeCAD is Z-up externally
|
|
6
|
+
|
|
7
|
+
If a kernel-facing operation behaves as if axes are swapped, check whether a Manifold call is still assuming Y-up semantics.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Model-Building Docs
|
|
2
|
+
|
|
3
|
+
This folder is partitioned so each API surface has one primary owner file. Avoid reading everything by default; load only what the current task needs.
|
|
4
|
+
|
|
5
|
+
## Ownership
|
|
6
|
+
|
|
7
|
+
- [reference.md](reference.md): core script contract, 3D primitives/transforms, booleans, imports, library helpers, return formats, and curves/surfacing APIs.
|
|
8
|
+
- [coordinate-system.md](coordinate-system.md), [geometry-conventions.md](geometry-conventions.md), [positioning.md](positioning.md): orientation rules, winding/transform conventions, and placement strategy.
|
|
9
|
+
- [sketch-core.md](sketch-core.md), [sketch-primitives.md](sketch-primitives.md), [sketch-path.md](sketch-path.md), [sketch-transforms.md](sketch-transforms.md), [sketch-booleans.md](sketch-booleans.md), [sketch-operations.md](sketch-operations.md), [sketch-on-face.md](sketch-on-face.md), [sketch-extrude.md](sketch-extrude.md), [sketch-anchor.md](sketch-anchor.md): detailed 2D sketch APIs.
|
|
10
|
+
- [entities.md](entities.md): named entities, tracked topology, constrained sketches, patterns, and fillet/chamfer utilities.
|
|
11
|
+
- [sheet-metal.md](sheet-metal.md): compiler-owned sheet-metal modeling, folded outputs, flat patterns, and defended region names.
|
|
12
|
+
- [assembly.md](assembly.md): assembly graph, joints, couplings, validation, and robot export behavior.
|
|
13
|
+
|
|
14
|
+
## Read Plan
|
|
15
|
+
|
|
16
|
+
1. Start with [reference.md](reference.md) plus [coordinate-system.md](coordinate-system.md), [geometry-conventions.md](geometry-conventions.md), and [positioning.md](positioning.md).
|
|
17
|
+
2. If the task is exploratory, unfamiliar, or likely to need debugging, use a `.forge-notebook.json` during the first iteration instead of jumping straight to a final script layout.
|
|
18
|
+
3. Add sketch docs only when the task is sketch-heavy.
|
|
19
|
+
4. Add [entities.md](entities.md) for topology-aware edits, constraints, or pattern helpers.
|
|
20
|
+
5. Add [sheet-metal.md](sheet-metal.md) when the task is about folded covers, brackets, flat patterns, or named panel/flange/bend descendants.
|
|
21
|
+
6. Add [assembly.md](assembly.md) only for joint/coupling/mechanism work.
|
|
22
|
+
7. Pull in guides and CLI docs when you need recipes, notebook workflow guidance, troubleshooting, or command usage.
|
|
23
|
+
|
|
24
|
+
## Intentionally Excluded
|
|
25
|
+
|
|
26
|
+
These files are still part of the ForgeCAD API, but they are not required for baseline model building:
|
|
27
|
+
|
|
28
|
+
- `../runtime/` for viewport-only behavior
|
|
29
|
+
- `../output/` for reporting/export behavior
|
|
30
|
+
- `../guides/` for recipes and troubleshooting
|
|
31
|
+
- `../internals/` for engine notes
|