forgecad 0.10.4 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{AdminPage-B3L3W1Uo.js → AdminPage-B1nIvqLS.js} +1 -1
- package/dist/assets/{BenchmarkPage-DXKVXMrJ.js → BenchmarkPage-YZJbw5nd.js} +2 -2
- package/dist/assets/{BlogPage-B7BWxOCg.js → BlogPage-DIWRApKS.js} +1 -1
- package/dist/assets/{DocsPage-BPGGwht1.js → DocsPage-ClL6X1hR.js} +8 -22
- package/dist/assets/EditorApp-CYBDvSyT.js +17067 -0
- package/dist/assets/{EmbedViewer-DygByZS2.js → EmbedViewer-Dmfu_LIw.js} +2 -2
- package/dist/assets/{LandingPageProofDriven-BoVE7JGY.js → LandingPageProofDriven-XYTiYxfM.js} +2 -2
- package/dist/assets/{LegalPage-Din8wv8d.js → LegalPage-D5Z3CscF.js} +2 -2
- package/dist/assets/{PricingPage-C2PMzmDc.js → PricingPage-BP4lIGio.js} +2 -2
- package/dist/assets/{SettingsPage-BlJDCRe8.js → SettingsPage-D3bcPBsC.js} +1 -1
- package/dist/assets/{app-BsRYSfxY.js → app-BKjogwIZ.js} +3288 -512
- package/dist/assets/{backendInit-6C0DLgH0.js → backendInit-6a9-ilom.js} +80498 -74979
- package/dist/assets/cli/{render-XXol_ET7.js → render-CMNudGb0.js} +1264 -113
- package/dist/assets/{constructionHistoryWorker-cTHWRJEi.js → constructionHistoryWorker-BuZgc606.js} +8369 -6839
- package/dist/assets/{evalWorker-BssDYW9u.js → evalWorker-DQ82ueGu.js} +45438 -39996
- package/dist/assets/{forgecad_geometry-CZ_IfuvA.js → forgecad_geometry-D8rWX7nQ.js} +1 -1
- package/dist/assets/{forgecad_geometry_bg-C3rQHfwg.wasm → forgecad_geometry_bg-ObqfqjJT.wasm} +0 -0
- package/dist/assets/{inspectWorker-ymhBV4Ll.js → inspectWorker-Cuby2qfT.js} +4899 -1303
- package/dist/assets/{jointPose-B0blBj9A.js → jointPose-CFql5I-u.js} +1 -1
- package/dist/assets/{landing-proof-driven-Cpf-MIbI.css → landing-proof-driven-_u4v_xQb.css} +2 -2
- package/dist/assets/{manifold-CYlIm-M6.js → manifold-02pmr7O7.js} +2 -2
- package/dist/assets/{manifold-B_7QXpGB.js → manifold-C6KU0oII.js} +1 -1
- package/dist/assets/{manifold-CNShmpEJ.js → manifold-P1yF3GKn.js} +1 -1
- package/dist/assets/{reportWorker-Cb5eyM7D.js → reportWorker-kg065BVL.js} +76583 -65731
- package/dist/cli/render.html +1 -1
- package/dist/docs/index.html +2 -2
- package/dist/docs-raw/AI/usage.md +6 -8
- package/dist/docs-raw/CLI.md +14 -12
- package/dist/docs-raw/component-model.md +28 -9
- package/dist/docs-raw/generated/assembly.md +76 -3
- package/dist/docs-raw/generated/concepts.md +43 -7
- package/dist/docs-raw/generated/core.md +399 -73
- package/dist/docs-raw/generated/curves.md +357 -6
- package/dist/docs-raw/generated/runtime-names.md +12 -12
- package/dist/docs-raw/generated/sketch.md +16 -3
- package/dist/docs-raw/guides/inspection-bundles.md +5 -3
- package/dist/docs-raw/guides/structural-fea.md +235 -0
- package/dist/docs-raw/skills/forgecad-build-model.md +70 -147
- package/dist/docs-raw/skills/forgecad-image-prompt.md +1 -1
- package/dist/docs-raw/skills/forgecad-project-sync.md +3 -3
- package/dist/docs-raw/skills/forgecad-reconstruct-cad-file.md +2 -2
- package/dist/docs-raw/skills/forgecad-reconstruct-from-images.md +4 -5
- package/dist/docs-raw/skills/forgecad.md +4 -1
- package/dist/docs-raw/skills/index.md +1 -5
- package/dist/docs-raw/welcome.md +3 -4
- package/dist/index.html +1 -1
- package/dist/llms.txt +1 -2
- package/dist/sitemap.xml +15 -15
- package/dist-cli/{check-compiler-4RPB6SB5.js → check-compiler-UJWUEIDC.js} +1 -1
- package/dist-cli/{check-query-propagation-KN3DFQTX.js → check-query-propagation-O2EPDJSY.js} +1 -1
- package/dist-cli/{chunk-UHBRMYA6.js → chunk-MNDROM7T.js} +78926 -73392
- package/dist-cli/forgecad.js +6306 -1061
- package/dist-cli/forgecad_geometry_bg.wasm +0 -0
- package/dist-skill/CONTEXT.md +1257 -110
- package/dist-skill/SKILL.md +4 -1
- package/dist-skill/docs/API/core/concepts.md +31 -4
- package/dist-skill/docs/CLI.md +14 -12
- package/dist-skill/docs/generated/assembly.md +73 -3
- package/dist-skill/docs/generated/core.md +395 -74
- package/dist-skill/docs/generated/curves.md +356 -6
- package/dist-skill/docs/generated/runtime-names.md +12 -12
- package/dist-skill/docs/generated/sketch.md +16 -3
- package/dist-skill/docs/guides/inspection-bundles.md +5 -3
- package/dist-skill/docs/guides/manual-parameters.md +130 -0
- package/dist-skill/docs/guides/structural-fea.md +235 -0
- package/dist-skill/library/README.md +0 -4
- package/dist-skill/library/forgecad-build-model/SKILL.md +57 -150
- package/dist-skill/library/forgecad-build-model/references/inspection-feedback.md +58 -0
- package/dist-skill/library/forgecad-build-model/references/module-contracts.md +53 -0
- package/dist-skill/library/forgecad-build-model/references/parameter-controls.md +22 -0
- package/dist-skill/library/forgecad-build-model/references/readiness-review.md +43 -0
- package/dist-skill/library/forgecad-build-model/references/simulation-feedback.md +49 -0
- package/dist-skill/library/forgecad-build-model/references/stage-1-design-intent.md +21 -0
- package/dist-skill/library/forgecad-build-model/references/stage-2-architecture-plan.md +23 -0
- package/dist-skill/library/forgecad-build-model/references/stage-3-build-slices.md +39 -0
- package/dist-skill/library/forgecad-build-model/references/stage-4-feedback-iteration.md +24 -0
- package/dist-skill/library/forgecad-build-model/references/stage-5-readiness-package.md +34 -0
- package/dist-skill/library/forgecad-image-prompt/SKILL.md +1 -1
- package/dist-skill/library/forgecad-project-sync/SKILL.md +3 -3
- package/dist-skill/library/forgecad-reconstruct-cad-file/SKILL.md +2 -2
- package/dist-skill/library/forgecad-reconstruct-from-images/SKILL.md +4 -5
- package/dist-skill/website/skills/forgecad-build-model.md +70 -147
- package/dist-skill/website/skills/forgecad-image-prompt.md +1 -1
- package/dist-skill/website/skills/forgecad-project-sync.md +3 -3
- package/dist-skill/website/skills/forgecad-reconstruct-cad-file.md +2 -2
- package/dist-skill/website/skills/forgecad-reconstruct-from-images.md +4 -5
- package/dist-skill/website/skills/forgecad.md +4 -1
- package/dist-skill/website/skills/index.md +1 -5
- package/examples/analysis/structural-stress-fea.forge.js +19 -0
- package/examples/api/blend-full-round.forge.js +37 -0
- package/examples/api/blend-variable-radius.forge.js +51 -0
- package/examples/api/curve-project-and-intersect.forge.js +59 -0
- package/examples/api/extrude-up-to-face.forge.js +47 -0
- package/examples/api/param-path2d.forge.js +65 -0
- package/examples/api/param-placement2d.forge.js +80 -0
- package/examples/api/param-spline2d-g-continuity.forge.js +57 -0
- package/examples/api/spoon-full-tang-handle.forge.js +188 -0
- package/examples/api/surface-boundarynet-dished-bowl.forge.js +63 -0
- package/examples/api/surface-fill-interior-constraints.forge.js +59 -0
- package/examples/api/surface-variable-thickness-panel.forge.js +62 -0
- package/examples/mechanical/airplane-propeller.forge.js +81 -28
- package/package.json +5 -2
- package/dist/assets/EditorApp-BWUGCdD5.js +0 -16610
- package/dist/docs-raw/skills/forgecad-design-spec.md +0 -145
- package/dist/docs-raw/skills/forgecad-grade-model.md +0 -84
- package/dist/docs-raw/skills/forgecad-inspect-model.md +0 -80
- package/dist/docs-raw/skills/forgecad-verify-mujoco.md +0 -78
- package/dist-skill/library/forgecad-design-spec/SKILL.md +0 -132
- package/dist-skill/library/forgecad-design-spec/references/default-profiles.md +0 -99
- package/dist-skill/library/forgecad-design-spec/references/master-prompt.md +0 -73
- package/dist-skill/library/forgecad-grade-model/SKILL.md +0 -72
- package/dist-skill/library/forgecad-grade-model/agents/openai.yaml +0 -4
- package/dist-skill/library/forgecad-inspect-model/SKILL.md +0 -68
- package/dist-skill/library/forgecad-verify-mujoco/SKILL.md +0 -66
- package/dist-skill/website/skills/forgecad-design-spec.md +0 -145
- package/dist-skill/website/skills/forgecad-grade-model.md +0 -84
- package/dist-skill/website/skills/forgecad-inspect-model.md +0 -80
- package/dist-skill/website/skills/forgecad-verify-mujoco.md +0 -78
- /package/dist/assets/{landing-proof-driven-BxZZh5r5.js → landing-proof-driven-DNPRKL_p.js} +0 -0
- /package/dist-skill/library/{forgecad-verify-mujoco → forgecad-build-model}/scripts/mujoco_verify.py +0 -0
- /package/dist-skill/library/{forgecad-inspect-model → forgecad-build-model/scripts}/summarize_manifest.py +0 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* n-sided filled surface pulled onto interior features with `Surface.Fill`.
|
|
3
|
+
*
|
|
4
|
+
* `Surface.Fill` already fills any closed loop of n >= 3 boundary curves
|
|
5
|
+
* (energy-minimizing constrained fill on the OCCT backend). Two optional fields
|
|
6
|
+
* shape the INTERIOR of that fill without changing the rim:
|
|
7
|
+
*
|
|
8
|
+
* - `through` — interior constraint curves the surface must pass through. They
|
|
9
|
+
* are NOT part of the boundary loop; they pull the fill onto an internal
|
|
10
|
+
* feature line (here, a raised diagonal spine/crease).
|
|
11
|
+
* - `points` — isolated interior points the surface must interpolate (here, a
|
|
12
|
+
* single pinned bump lifted above the rim plane).
|
|
13
|
+
*
|
|
14
|
+
* The result is an open sheet, so `.thicken()` turns it into a thin solid.
|
|
15
|
+
* (Interior constraints require the default OCCT exact backend.)
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
scene({
|
|
19
|
+
camera: { position: [120, -150, 110], target: [25, 25, 6], fov: 32 },
|
|
20
|
+
environment: { preset: 'studio' },
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// A near-planar pentagon rim at z = 0 (five corners, five exact edges).
|
|
24
|
+
const corners = [
|
|
25
|
+
[0, 0, 0],
|
|
26
|
+
[50, 0, 0],
|
|
27
|
+
[62, 38, 0],
|
|
28
|
+
[25, 60, 0],
|
|
29
|
+
[-12, 38, 0],
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
function edge(a, b) {
|
|
33
|
+
return Curve.Fit([corners[a], corners[b]]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const boundaries = [
|
|
37
|
+
{ name: 'a', curve: edge(0, 1) },
|
|
38
|
+
{ name: 'b', curve: edge(1, 2) },
|
|
39
|
+
{ name: 'c', curve: edge(2, 3) },
|
|
40
|
+
{ name: 'd', curve: edge(3, 4) },
|
|
41
|
+
{ name: 'e', curve: edge(4, 0) },
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
// Interior crease the fill must ride over: a raised diagonal spine.
|
|
45
|
+
const spine = Curve.Fit([
|
|
46
|
+
[8, 8, 3],
|
|
47
|
+
[28, 30, 7],
|
|
48
|
+
[50, 48, 3],
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
const skin = Surface.Fill({
|
|
52
|
+
boundaries,
|
|
53
|
+
through: [{ curve: spine }], // pull the fill onto the internal feature line
|
|
54
|
+
points: [[22, 14, 6]], // pin an interior bump above the rim plane
|
|
55
|
+
}).thicken(1.2);
|
|
56
|
+
|
|
57
|
+
skin.color('#bcd0d8');
|
|
58
|
+
|
|
59
|
+
return skin;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Variable-thickness surface panel.
|
|
3
|
+
*
|
|
4
|
+
* `Surface.Net()` builds the carrier sheet. `Thickness.grid()` defines a scalar
|
|
5
|
+
* UV wall field, so the panel can be thin at one edge, thicker through the load
|
|
6
|
+
* path, and locally reinforced near one corner without hand-offset geometry.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
scene({
|
|
10
|
+
background: { top: '#eef4f7', bottom: '#f9fbfd' },
|
|
11
|
+
camera: { position: [150, -190, 92], target: [0, 0, 8], fov: 34 },
|
|
12
|
+
environment: { preset: 'studio', intensity: 0.25, background: false },
|
|
13
|
+
ground: { visible: true, color: '#d6dde3', height: -5, receiveShadow: true },
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const panelWidth = param('Panel Width', 128);
|
|
17
|
+
const panelDepth = param('Panel Depth', 82);
|
|
18
|
+
const crownHeight = param('Crown Height', 15);
|
|
19
|
+
|
|
20
|
+
const uCount = 6;
|
|
21
|
+
const vCount = 5;
|
|
22
|
+
const panelCage = [];
|
|
23
|
+
|
|
24
|
+
for (let i = 0; i <= uCount; i++) {
|
|
25
|
+
const u = i / uCount;
|
|
26
|
+
const x = (u - 0.5) * panelWidth;
|
|
27
|
+
const row = [];
|
|
28
|
+
|
|
29
|
+
for (let j = 0; j <= vCount; j++) {
|
|
30
|
+
const v = j / vCount;
|
|
31
|
+
const y = (v - 0.5) * panelDepth;
|
|
32
|
+
const xProfile = 1 - (2 * u - 1) ** 2;
|
|
33
|
+
const yProfile = 1 - 0.42 * (2 * v - 1) ** 2;
|
|
34
|
+
const diagonalBias = 2.8 * u * (1 - v);
|
|
35
|
+
row.push([x, y, crownHeight * xProfile * yProfile + diagonalBias]);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
panelCage.push(row);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const panel = Surface.Net()
|
|
42
|
+
.cage(panelCage)
|
|
43
|
+
.degree(3, 3)
|
|
44
|
+
.thickenInsideBy(
|
|
45
|
+
Thickness.grid(
|
|
46
|
+
[
|
|
47
|
+
[1.1, 1.3, 1.5],
|
|
48
|
+
[1.8, 2.4, 2.9],
|
|
49
|
+
[2.8, 3.5, 4.2],
|
|
50
|
+
],
|
|
51
|
+
{ easing: 'easeInOut' },
|
|
52
|
+
),
|
|
53
|
+
{ resolution: 56 },
|
|
54
|
+
)
|
|
55
|
+
.color('#5c8fb5')
|
|
56
|
+
.material({ roughness: 0.62, metalness: 0.04, clearcoat: 0.12 });
|
|
57
|
+
|
|
58
|
+
verify.notEmpty('Variable-thickness panel produces solid geometry', panel);
|
|
59
|
+
verify.volumeApprox('Variable thickness stays in the expected volume range', panel, panelWidth * panelDepth * 2.55, 6000);
|
|
60
|
+
verify.physicalComponentCount('Variable-thickness panel is one connected component', 1);
|
|
61
|
+
|
|
62
|
+
return [{ name: 'Variable Thickness Panel', shape: panel }];
|
|
@@ -16,6 +16,13 @@
|
|
|
16
16
|
//
|
|
17
17
|
// Thickness: 24% at root (structural) → 6% at tip (aerodynamic)
|
|
18
18
|
// Camber: 4% at root → 1.5% at tip (Cl margin at low-speed root)
|
|
19
|
+
//
|
|
20
|
+
// Skin: The blade is lofted through the closed airfoil sections with
|
|
21
|
+
// Shape.fromSlices — an ordered slice loft that keeps a smooth
|
|
22
|
+
// section-to-section correspondence, so the blade reads class-A
|
|
23
|
+
// (no spanwise faceting) even on the default Manifold backend.
|
|
24
|
+
// Run with `--backend truck` (or occt) for an exact kernel-native
|
|
25
|
+
// NURBS solid — preferred for STEP export.
|
|
19
26
|
|
|
20
27
|
// ─── Design Parameters ──────────────────────────────────────────
|
|
21
28
|
const diameter = Param.number("Diameter", 1900, { min: 1200, max: 2600, unit: "mm" });
|
|
@@ -171,49 +178,98 @@ function camberAt(rNorm) {
|
|
|
171
178
|
// - Zero pitch → chord along tangential (Y in world)
|
|
172
179
|
// - Positive β → leading edge tilts toward thrust axis (+Z)
|
|
173
180
|
|
|
174
|
-
const NUM_STATIONS =
|
|
175
|
-
const NACA_PTS =
|
|
181
|
+
const NUM_STATIONS = 28; // a few more stations than the old loft for a smoother span
|
|
182
|
+
const NACA_PTS = 48; // points per airfoil surface (96 total outline)
|
|
176
183
|
const CAMBER_POS = 0.4; // max camber at 40% chord (standard for props)
|
|
177
184
|
const rRoot = rHub * 0.55; // blade shank starts inside the spinner
|
|
178
185
|
|
|
179
|
-
// Airfoil section
|
|
180
|
-
//
|
|
181
|
-
|
|
186
|
+
// Airfoil section as a 2D point list (before it becomes a Sketch), already
|
|
187
|
+
// rotated for twist. The buried shank can blend toward a fuller, rounder cuff:
|
|
188
|
+
// rNorm — normalized span for the aerodynamic distributions
|
|
189
|
+
// r — true radius (drives the BEMT twist)
|
|
190
|
+
// fatten — root-cuff blend 0..1: 0 = pure airfoil, 1 = fully rounded fat
|
|
191
|
+
// shank. Pulls each outline point toward an enclosing ellipse so the
|
|
192
|
+
// blade meets the spinner with a beefy, non-spindly junction instead
|
|
193
|
+
// of necking down to a thin stalk (the old root-quality defect).
|
|
194
|
+
function bladeSectionPoints(rNorm, r, fatten) {
|
|
182
195
|
const chord = chordAt(rNorm);
|
|
183
196
|
const thick = thicknessRatioAt(rNorm);
|
|
184
197
|
const camber = camberAt(rNorm);
|
|
185
198
|
const twist = twistAt(Math.max(r, rHub));
|
|
186
199
|
|
|
187
200
|
let pts = nacaPoints(camber, CAMBER_POS, thick, chord, NACA_PTS);
|
|
188
|
-
|
|
189
|
-
|
|
201
|
+
|
|
202
|
+
if (fatten > 0) {
|
|
203
|
+
// Blend toward an enclosing ellipse centered at the quarter-chord origin —
|
|
204
|
+
// fills the thin airfoil into a fuller shank without changing the point
|
|
205
|
+
// count or ordering, so the loft keeps a clean ordered correspondence.
|
|
206
|
+
const exA = chord * 0.34; // half-length along chord
|
|
207
|
+
const exB = Math.max(chord * thick * 0.62, chord * 0.16); // half-thickness, floored fat
|
|
208
|
+
pts = pts.map(([x, y]) => {
|
|
209
|
+
const ang = Math.atan2(y, x);
|
|
210
|
+
const ex = exA * Math.cos(ang);
|
|
211
|
+
const ey = exB * Math.sin(ang);
|
|
212
|
+
return [x + (ex - x) * fatten, y + (ey - y) * fatten];
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// 90° aligns chord with the tangential direction; +twist adds pitch.
|
|
217
|
+
return rotate2D(pts, 90 + twist);
|
|
190
218
|
}
|
|
191
219
|
|
|
192
|
-
|
|
193
|
-
|
|
220
|
+
function bladeSection(rNorm, r, fatten) {
|
|
221
|
+
return polygon(bladeSectionPoints(rNorm, r, fatten || 0));
|
|
222
|
+
}
|
|
194
223
|
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
224
|
+
// Ordered station list: span coordinate (world X, radial in the disk) + the
|
|
225
|
+
// closed airfoil section's points. Sections sit perpendicular to X, so the
|
|
226
|
+
// blade extends radially with no post-loft rotation.
|
|
227
|
+
const stationX = [];
|
|
228
|
+
const stationPoints = [];
|
|
229
|
+
|
|
230
|
+
// Two buried shank stations inside the spinner: the deepest is a fully round
|
|
231
|
+
// cuff, the next blends back toward the airfoil so the aero blade grows
|
|
232
|
+
// smoothly out of the shank instead of pinching at the hub.
|
|
233
|
+
const shankStations = [
|
|
234
|
+
{ x: rRoot, fatten: 1.0 },
|
|
235
|
+
{ x: rHub * 0.86, fatten: 0.55 },
|
|
236
|
+
];
|
|
237
|
+
for (const { x, fatten } of shankStations) {
|
|
238
|
+
stationX.push(x);
|
|
239
|
+
stationPoints.push(bladeSectionPoints(0, rHub, fatten));
|
|
200
240
|
}
|
|
201
241
|
|
|
202
242
|
// Aerodynamic stations from the hub surface to the tip. Cosine spacing
|
|
203
243
|
// clusters stations at the root (where the BEMT twist gradient is steepest)
|
|
204
|
-
// and at the tip (where the planform rounds off).
|
|
244
|
+
// and at the tip (where the planform rounds off). A light residual cuff on the
|
|
245
|
+
// first aero stations avoids a sudden chord/thickness step at the hub line.
|
|
205
246
|
for (let i = 0; i <= NUM_STATIONS; i++) {
|
|
206
|
-
const rNorm
|
|
207
|
-
const r
|
|
208
|
-
|
|
209
|
-
|
|
247
|
+
const rNorm = 0.5 - 0.5 * Math.cos(Math.PI * i / NUM_STATIONS);
|
|
248
|
+
const r = rHub + rNorm * (R - rHub);
|
|
249
|
+
const fatten = rNorm < 0.06 ? 0.25 * (1 - rNorm / 0.06) : 0;
|
|
250
|
+
stationX.push(r);
|
|
251
|
+
stationPoints.push(bladeSectionPoints(rNorm, r, fatten));
|
|
210
252
|
}
|
|
211
253
|
|
|
212
|
-
// Loft
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
//
|
|
216
|
-
const blade =
|
|
254
|
+
// Loft the closed sections into a smooth blade solid. Shape.fromSlices keeps an
|
|
255
|
+
// ordered, smooth section-to-section correspondence (no SDF faceting). On the
|
|
256
|
+
// default Manifold backend edgeLength tunes the mesh; the truck/occt kernel
|
|
257
|
+
// ignores it and builds an exact NURBS solid.
|
|
258
|
+
const blade = Shape.fromSlices(
|
|
259
|
+
stationX.map((x, i) => Shape.slicePerpendicularToX(x, polygon(stationPoints[i]))),
|
|
260
|
+
{ edgeLength: meshRes },
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
// Blade-shaped cutouts through the spinner: the same ordered sections grown
|
|
264
|
+
// ~5% for running clearance, lofted the same exact way so the cut tracks the
|
|
265
|
+
// blade skin (keeping the span direction exact).
|
|
266
|
+
const CLEARANCE = 1.05;
|
|
267
|
+
const bladeCutout = Shape.fromSlices(
|
|
268
|
+
stationX.map((x, i) => Shape.slicePerpendicularToX(
|
|
269
|
+
x, polygon(stationPoints[i].map(([px, py]) => [px * CLEARANCE, py * CLEARANCE])),
|
|
270
|
+
)),
|
|
271
|
+
{ edgeLength: meshRes },
|
|
272
|
+
);
|
|
217
273
|
|
|
218
274
|
// ─── Spinner / Hub ──────────────────────────────────────────────
|
|
219
275
|
//
|
|
@@ -269,10 +325,7 @@ const hubBarrel = cylinder(spinnerLen * 0.5, rHub * 0.62)
|
|
|
269
325
|
|
|
270
326
|
const bladeAssembly = union(allBlades, hubBarrel);
|
|
271
327
|
|
|
272
|
-
//
|
|
273
|
-
// clearance: the blade cross-section is grown in chord and thickness
|
|
274
|
-
// (x/y before the radial rotation), keeping the span direction exact.
|
|
275
|
-
const bladeCutout = bladeRaw.scale([1.04, 1.04, 1]).rotateY(90);
|
|
328
|
+
// Pattern the blade-shaped cutouts (defined with the blade above) around the disk.
|
|
276
329
|
const spinnerCutouts = circularPattern(bladeCutout, numBlades);
|
|
277
330
|
|
|
278
331
|
// ─── Optional: Airfoil Section Visualization ────────────────────
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forgecad",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Code-first parametric CAD for JavaScript/TypeScript, in the browser and CLI.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"homepage": "https://forgecad.io",
|
|
@@ -44,6 +44,9 @@
|
|
|
44
44
|
"export": {
|
|
45
45
|
"description": "Export Forge models to manufacturing, simulation, and exchange formats."
|
|
46
46
|
},
|
|
47
|
+
"fea": {
|
|
48
|
+
"description": "Run, inspect, render, compare, and check structural FEA studies."
|
|
49
|
+
},
|
|
47
50
|
"inspect": {
|
|
48
51
|
"description": "Inspect ForgeCAD models with targeted visual, physical, and manufacturing evidence."
|
|
49
52
|
},
|
|
@@ -112,7 +115,7 @@
|
|
|
112
115
|
"dev:cli": "npm run build:solver:if-missing && npm run build:geometry:if-missing && tsup cli/forgecad.ts --format esm --platform node --target node20 --out-dir dist-cli --sourcemap --external typescript && node scripts/copy-cli-assets.mjs dist-cli",
|
|
113
116
|
"build:cli": "npm run build:solver:if-missing && npm run build:geometry:if-missing && tsup cli/forgecad.ts --format esm --platform node --target node20 --out-dir dist-cli --clean --external typescript && node scripts/copy-cli-assets.mjs dist-cli",
|
|
114
117
|
"build:native-occt": "node scripts/build-native-occt.mjs",
|
|
115
|
-
"build:backend": "npm run build:native-occt && tsup apps/backend/src/server.ts apps/backend/src/nativeOcctWorker.ts --format esm --platform node --target node20 --out-dir dist-backend --clean --sourcemap",
|
|
118
|
+
"build:backend": "npm run build:geometry:if-missing && npm run build:native-occt && tsup apps/backend/src/server.ts apps/backend/src/nativeOcctWorker.ts --format esm --platform node --target node20 --out-dir dist-backend --clean --sourcemap && node scripts/copy-wasm-assets.mjs dist-backend",
|
|
116
119
|
"build:binary": "node scripts/build-binary.mjs",
|
|
117
120
|
"build:binary:all": "node scripts/build-binary.mjs --all",
|
|
118
121
|
"bundle:offline": "node scripts/build-install-bundle.mjs",
|