forgecad 0.9.15 → 0.10.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.
Files changed (166) hide show
  1. package/dist/assets/{AdminPage-CDyGUinA.js → AdminPage-DwYHz72L.js} +1 -1
  2. package/dist/assets/{BenchmarkPage-DfPMY_-d.js → BenchmarkPage-a9_f-1US.js} +1 -1
  3. package/dist/assets/{BlogPage-kF0fkdJT.js → BlogPage-DodHpvmf.js} +1 -1
  4. package/dist/assets/{DocsPage-B954L3YN.js → DocsPage-B5LePEuj.js} +8 -858
  5. package/dist/assets/{EditorApp-CuDLxKqL.css → EditorApp-BpjZgzk0.css} +148 -0
  6. package/dist/assets/EditorApp-QXsAISLR.js +16307 -0
  7. package/dist/assets/{EmbedViewer-C77B-TrF.js → EmbedViewer-DdEHGUMU.js} +2 -2
  8. package/dist/assets/{LandingPageProofDriven-Cr6fXMDj.js → LandingPageProofDriven-yhhOodbf.js} +2 -2
  9. package/dist/assets/{LegalPage-Dzklqmmg.js → LegalPage-5RbKRGYK.js} +1 -1
  10. package/dist/assets/{PricingPage-zWXkvlwl.js → PricingPage-E3Rma7aV.js} +1 -1
  11. package/dist/assets/{SettingsPage-Bz0of4KQ.js → SettingsPage-BJZcM97j.js} +1 -1
  12. package/dist/assets/{app-D3kDkggg.js → app-DSYrDg0V.js} +1846 -352
  13. package/dist/assets/cli/{render-DSY3mMQa.js → render-ZMHR9HkV.js} +161 -70
  14. package/dist/assets/{constructionHistoryWorker-gpDo-uH2.js → constructionHistoryWorker-AwMMWSxg.js} +1104 -349
  15. package/dist/assets/{evalWorker-CU0Ke6DP.js → evalWorker-DbNs7Dkp.js} +5155 -3772
  16. package/dist/assets/{inspectWorker-COyp8XXA.js → inspectWorker-CZsCFtQT.js} +1415 -439
  17. package/dist/assets/{targets-B9sGB5nB.js → jointPose-DO6mnXn_.js} +71 -3
  18. package/dist/assets/{manifold-DNkrUWpA.js → manifold-BGlQBBH9.js} +1 -1
  19. package/dist/assets/{manifold-BRI5prcH.js → manifold-BU-tJwQh.js} +1 -1
  20. package/dist/assets/{manifold-C-3h2M7p.js → manifold-fy2MV7K1.js} +2 -2
  21. package/dist/assets/{reportWorker-CdBz5bNg.js → reportWorker-DO6hcQbh.js} +8474 -4549
  22. package/dist/assets/{scalar-sampling-budget-wJF98aY9.js → scalar-sampling-budget-o90NSNmF.js} +5347 -3906
  23. package/dist/assets/{scanProxyWorker-B-9VbLIs.js → scanProxyWorker-2GtDLk-R.js} +19 -6
  24. package/dist/assets/{javascript-1kQXfVaz.js → typescript-DBQ6RN5l.js} +874 -22
  25. package/dist/cli/render.html +1 -1
  26. package/dist/docs/index.html +3 -3
  27. package/dist/docs-raw/AI/usage.md +3 -1
  28. package/dist/docs-raw/CLI.md +65 -239
  29. package/dist/docs-raw/README.md +6 -0
  30. package/dist/docs-raw/component-model.md +17 -150
  31. package/dist/docs-raw/generated/assembly.md +159 -520
  32. package/dist/docs-raw/generated/concepts.md +245 -3491
  33. package/dist/docs-raw/generated/core.md +277 -1251
  34. package/dist/docs-raw/generated/curves.md +387 -1608
  35. package/dist/docs-raw/generated/legacy.md +162 -0
  36. package/dist/docs-raw/generated/lib.md +238 -112
  37. package/dist/docs-raw/generated/output.md +51 -76
  38. package/dist/docs-raw/generated/runtime-names.md +30 -22
  39. package/dist/docs-raw/generated/sdf.md +68 -284
  40. package/dist/docs-raw/generated/sheet-metal.md +68 -335
  41. package/dist/docs-raw/generated/sketch.md +240 -1161
  42. package/dist/docs-raw/generated/viewport.md +75 -316
  43. package/dist/docs-raw/generated/wood.md +21 -49
  44. package/dist/docs-raw/guides/coordinate-system.md +4 -42
  45. package/dist/docs-raw/guides/inspection-bundles.md +44 -442
  46. package/dist/docs-raw/guides/joint-design.md +18 -79
  47. package/dist/docs-raw/guides/positioning.md +21 -143
  48. package/dist/docs-raw/guides/scene-presentation.md +89 -0
  49. package/dist/docs-raw/skills/forgecad-3d-reconstruction.md +25 -111
  50. package/dist/docs-raw/skills/forgecad-blockout-model.md +20 -117
  51. package/dist/docs-raw/skills/forgecad-component-model.md +23 -107
  52. package/dist/docs-raw/skills/forgecad-high-level-spec.md +47 -155
  53. package/dist/docs-raw/skills/forgecad-image-replicator.md +26 -143
  54. package/dist/docs-raw/skills/forgecad-lld.md +19 -113
  55. package/dist/docs-raw/skills/forgecad-make-a-model.md +113 -532
  56. package/dist/docs-raw/skills/forgecad-model-grader.md +38 -108
  57. package/dist/docs-raw/skills/forgecad-prepare-prompt.md +24 -211
  58. package/dist/docs-raw/skills/forgecad-project.md +13 -129
  59. package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +42 -134
  60. package/dist/docs-raw/skills/forgecad-render-inspect.md +27 -174
  61. package/dist/docs-raw/skills/forgecad-visual-spec.md +32 -112
  62. package/dist/docs-raw/skills/forgecad.md +19 -18
  63. package/dist/docs-raw/skills/index.md +2 -0
  64. package/dist/docs-raw/welcome.md +4 -2
  65. package/dist/index.html +1 -1
  66. package/dist/llms.txt +1 -2
  67. package/dist/sitemap.xml +13 -13
  68. package/dist-cli/{check-compiler-SDX5QIXI.js → check-compiler-JTVBITCR.js} +1 -1
  69. package/dist-cli/{check-query-propagation-EAYEFT77.js → check-query-propagation-3FFLSMVN.js} +1 -1
  70. package/dist-cli/{chunk-N4O47JLF.js → chunk-OAN5T4XD.js} +5722 -4287
  71. package/dist-cli/forgecad.js +2195 -656
  72. package/dist-skill/CONTEXT.md +1778 -7912
  73. package/dist-skill/SKILL.md +15 -15
  74. package/dist-skill/docs/API/core/concepts.md +27 -157
  75. package/dist-skill/docs/CLI.md +65 -239
  76. package/dist-skill/docs/generated/assembly.md +160 -493
  77. package/dist-skill/docs/generated/core.md +277 -1251
  78. package/dist-skill/docs/generated/curves.md +387 -1609
  79. package/dist-skill/docs/generated/lib.md +238 -112
  80. package/dist-skill/docs/generated/output.md +51 -76
  81. package/dist-skill/docs/generated/runtime-names.md +16 -22
  82. package/dist-skill/docs/generated/sdf.md +68 -284
  83. package/dist-skill/docs/generated/sheet-metal.md +68 -335
  84. package/dist-skill/docs/generated/sketch.md +240 -1160
  85. package/dist-skill/docs/generated/viewport.md +75 -223
  86. package/dist-skill/docs/generated/wood.md +21 -49
  87. package/dist-skill/docs/guides/coordinate-system.md +4 -42
  88. package/dist-skill/docs/guides/inspection-bundles.md +44 -442
  89. package/dist-skill/docs/guides/joint-design.md +18 -79
  90. package/dist-skill/docs/guides/positioning.md +21 -143
  91. package/dist-skill/docs/guides/scene-presentation.md +89 -0
  92. package/dist-skill/docs/guides/surface-members.md +26 -0
  93. package/dist-skill/library/forgecad-3d-reconstruction/SKILL.md +23 -111
  94. package/dist-skill/library/forgecad-blockout-model/SKILL.md +18 -117
  95. package/dist-skill/library/forgecad-component-model/SKILL.md +21 -107
  96. package/dist-skill/library/forgecad-high-level-spec/SKILL.md +45 -155
  97. package/dist-skill/library/forgecad-image-replicator/SKILL.md +24 -143
  98. package/dist-skill/library/forgecad-lld/SKILL.md +17 -113
  99. package/dist-skill/library/forgecad-make-a-model/SKILL.md +111 -532
  100. package/dist-skill/library/forgecad-model-grader/SKILL.md +36 -108
  101. package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +35 -224
  102. package/dist-skill/library/forgecad-prepare-prompt/references/default-profiles.md +43 -271
  103. package/dist-skill/library/forgecad-prepare-prompt/references/master-prompt.md +30 -99
  104. package/dist-skill/library/forgecad-project/SKILL.md +13 -131
  105. package/dist-skill/library/forgecad-reconstruction-benchmark/SKILL.md +29 -123
  106. package/dist-skill/library/forgecad-render-inspect/SKILL.md +25 -174
  107. package/dist-skill/library/forgecad-visual-spec/SKILL.md +30 -111
  108. package/dist-skill/website/skills/forgecad-3d-reconstruction.md +58 -0
  109. package/dist-skill/website/skills/forgecad-blockout-model.md +49 -0
  110. package/dist-skill/website/skills/forgecad-component-model.md +53 -0
  111. package/dist-skill/website/skills/forgecad-high-level-spec.md +101 -0
  112. package/dist-skill/website/skills/forgecad-image-replicator.md +63 -0
  113. package/dist-skill/website/skills/forgecad-lld.md +41 -0
  114. package/dist-skill/website/skills/forgecad-make-a-model.md +186 -0
  115. package/dist-skill/website/skills/forgecad-model-grader.md +82 -0
  116. package/dist-skill/website/skills/forgecad-prepare-prompt.md +63 -0
  117. package/dist-skill/website/skills/forgecad-project.md +26 -0
  118. package/dist-skill/website/skills/forgecad-reconstruction-benchmark.md +60 -0
  119. package/dist-skill/website/skills/forgecad-render-inspect.md +80 -0
  120. package/dist-skill/website/skills/forgecad-visual-spec.md +71 -0
  121. package/dist-skill/website/skills/forgecad.md +122 -0
  122. package/dist-skill/website/skills/index.md +26 -0
  123. package/examples/api/comparison-imported-sphere-candidate.forge.js +1 -1
  124. package/examples/api/conformal-product-ribbon.forge.js +1 -1
  125. package/examples/api/exact-sheet-shell-assembly.forge.js +1 -1
  126. package/examples/api/extrude-options.forge.js +4 -2
  127. package/examples/api/field-loft-drive-tip.forge.js +40 -0
  128. package/examples/api/guided-loft-olive-oil-bottle.forge.js +1 -1
  129. package/examples/api/helix-basics.forge.js +2 -2
  130. package/examples/api/highlight-debug.forge.js +10 -10
  131. package/examples/api/mesh-import-slats.forge.js +1 -1
  132. package/examples/api/real-product-curves.forge.js +1 -1
  133. package/examples/api/route3d-elbow.forge.js +3 -0
  134. package/examples/api/sculpt-box-circle-booleans.forge.js +1 -1
  135. package/examples/api/sdf-shapes.forge.js +2 -5
  136. package/examples/api/sketch-rounding-strategies.forge.js +6 -6
  137. package/examples/api/surface-member-bottle-cage.forge.js +3 -3
  138. package/examples/api/surface-member-conformal-product-ribbon.forge.js +3 -3
  139. package/examples/api/surface-member-razor-inlay.forge.js +1 -1
  140. package/examples/api/variable-sweep-test.forge.js +4 -2
  141. package/examples/mechanical/airplane-propeller.forge.js +74 -39
  142. package/examples/nurbs-surface.forge.js +1 -1
  143. package/examples/products/iphone.forge.js +1 -1
  144. package/package.json +4 -1
  145. package/dist/assets/EditorApp-Beb-IZ0y.js +0 -14014
  146. package/dist/docs-raw/guides/geometry-conventions.md +0 -52
  147. package/dist/docs-raw/guides/modeling-recipes.md +0 -78
  148. package/dist-skill/docs/guides/geometry-conventions.md +0 -52
  149. package/dist-skill/docs/guides/modeling-recipes.md +0 -78
  150. package/dist-skill/library/forgecad-visual-spec/references/prompt-template.md +0 -79
  151. package/examples/api/bolted-service-cover.forge.js +0 -17
  152. package/examples/api/cable-gland-anchor.forge.js +0 -14
  153. package/examples/api/captured-cartridge-guide.forge.js +0 -14
  154. package/examples/api/captured-linear-slide.forge.js +0 -13
  155. package/examples/api/clevis-pin-joint.forge.js +0 -13
  156. package/examples/api/datum-enclosure.forge.js +0 -16
  157. package/examples/api/hose-barb-port.forge.js +0 -14
  158. package/examples/api/knuckled-hinge-assembly.forge.js +0 -15
  159. package/examples/api/living-hinge-cover.forge.js +0 -14
  160. package/examples/api/pcb-terminal-block.forge.js +0 -22
  161. package/examples/api/pinned-lever-pivot-stack.forge.js +0 -14
  162. package/examples/api/retained-shaft-knob-stack.forge.js +0 -15
  163. package/examples/api/routed-tube-clip.forge.js +0 -15
  164. package/examples/api/seated-bearing-stack.forge.js +0 -30
  165. package/examples/api/snap-latch-cover.forge.js +0 -14
  166. package/examples/api/thumb-screw-clamp.forge.js +0 -15
@@ -121,20 +121,28 @@ function twistAt(r) {
121
121
  return Math.atan(Math.tan(pitchAngle * DEG) * 0.75 * R / r) / DEG;
122
122
  }
123
123
 
124
- // Chord: GA propeller distribution — structural root + Betz-optimal taper.
125
- // Peaks near 25% span, maintains width at root for structural attachment,
126
- // smooth cosine taper to tip.
124
+ // Chord: GA propeller distribution — structural root + Betz-optimal taper,
125
+ // closed by an elliptical rounded tip. Peaks near 25% span, maintains width
126
+ // at root for structural attachment, cosine taper to 92% span, then an
127
+ // elliptical arc rounds the tip in planform (real propellers never taper to
128
+ // a razor point — the tip cap needs finite chord to close cleanly).
129
+ const TIP_ROUND_START = 0.92;
130
+
127
131
  function chordAt(rNorm) {
128
- const r = rNorm;
132
+ const r = Math.min(rNorm, TIP_ROUND_START);
129
133
  // Root: rises from 55% at hub to 100% at ~25% span
130
134
  const rootRise = r < 0.25
131
135
  ? 0.55 + 0.45 * Math.pow(r / 0.25, 0.7)
132
136
  : 1.0;
133
- // Cosine taper from peak to tip (exponent < 1 for fuller planform)
137
+ // Cosine taper from peak to the start of the tip round
134
138
  const tipTaper = r < 0.25
135
139
  ? 1.0
136
140
  : Math.pow(Math.cos(Math.PI / 2 * ((r - 0.25) / 0.75)), 0.5);
137
- return maxChord * rootRise * tipTaper;
141
+ const base = maxChord * rootRise * tipTaper;
142
+ if (rNorm <= TIP_ROUND_START) return base;
143
+ // Elliptical closure from 92% span to the tip, floored for a clean cap
144
+ const s = (rNorm - TIP_ROUND_START) / (1 - TIP_ROUND_START);
145
+ return Math.max(base * Math.sqrt(Math.max(0, 1 - s * s)), maxChord * 0.05);
138
146
  }
139
147
 
140
148
  // Thickness ratio: thick root for structure, thin tip for aero.
@@ -163,27 +171,41 @@ function camberAt(rNorm) {
163
171
  // - Zero pitch → chord along tangential (Y in world)
164
172
  // - Positive β → leading edge tilts toward thrust axis (+Z)
165
173
 
166
- const NUM_STATIONS = 12;
174
+ const NUM_STATIONS = 24;
167
175
  const NACA_PTS = 40; // points per airfoil surface (80 total outline)
168
176
  const CAMBER_POS = 0.4; // max camber at 40% chord (standard for props)
177
+ const rRoot = rHub * 0.55; // blade shank starts inside the spinner
169
178
 
170
- const profiles = [];
171
- const heights = [];
172
-
173
- for (let i = 0; i <= NUM_STATIONS; i++) {
174
- const rNorm = i / NUM_STATIONS;
175
- const r = rHub + rNorm * (R - rHub);
176
-
177
- const chord = Math.max(chordAt(rNorm), 5); // minimum 5mm to avoid degenerate polygon
178
- const thick = thicknessRatioAt(rNorm);
179
+ // Airfoil section at a given normalized span position (clamped to the
180
+ // aerodynamic range — the shank inside the spinner reuses the hub section).
181
+ function bladeSection(rNorm, r) {
182
+ const chord = chordAt(rNorm);
183
+ const thick = thicknessRatioAt(rNorm);
179
184
  const camber = camberAt(rNorm);
180
- const twist = twistAt(r);
185
+ const twist = twistAt(Math.max(r, rHub));
181
186
 
182
- // Generate NACA points and rotate to blade orientation
183
187
  let pts = nacaPoints(camber, CAMBER_POS, thick, chord, NACA_PTS);
184
188
  pts = rotate2D(pts, 90 + twist); // 90° aligns chord with tangential, +twist adds pitch
189
+ return polygon(pts);
190
+ }
191
+
192
+ const profiles = [];
193
+ const heights = [];
185
194
 
186
- profiles.push(polygon(pts));
195
+ // Shank stations buried inside the spinner — a constant hub section carries
196
+ // the blade to a structural attachment instead of floating at the hub surface.
197
+ for (const r of [rRoot, rHub * 0.92]) {
198
+ profiles.push(bladeSection(0, rHub));
199
+ heights.push(r);
200
+ }
201
+
202
+ // Aerodynamic stations from the hub surface to the tip. Cosine spacing
203
+ // clusters stations at the root (where the BEMT twist gradient is steepest)
204
+ // and at the tip (where the planform rounds off).
205
+ for (let i = 0; i <= NUM_STATIONS; i++) {
206
+ const rNorm = 0.5 - 0.5 * Math.cos(Math.PI * i / NUM_STATIONS);
207
+ const r = rHub + rNorm * (R - rHub);
208
+ profiles.push(bladeSection(rNorm, r));
187
209
  heights.push(r);
188
210
  }
189
211
 
@@ -195,24 +217,27 @@ const blade = bladeRaw.rotateY(90);
195
217
 
196
218
  // ─── Spinner / Hub ──────────────────────────────────────────────
197
219
  //
198
- // Ogive spinner: parabolic nose + cylindrical body + rear taper.
220
+ // Ogive spinner: elliptical nose + cylindrical body + rear taper.
199
221
  // Built as a loft of circular profiles along the propeller axis (Z).
222
+ // The cylindrical body is centered on the blade plane (z = 0) so the
223
+ // blade shanks bury fully into the spinner at maximum radius.
200
224
 
201
225
  const spinnerLen = hubDiameter * 1.3;
202
226
  const spinnerR = rHub * 0.95;
203
- const HUB_STATIONS = 10;
227
+ const HUB_STATIONS = 36;
204
228
 
205
229
  const hubProfiles = [];
206
230
  const hubHeights = [];
207
231
 
208
232
  for (let i = 0; i <= HUB_STATIONS; i++) {
209
- const t = i / HUB_STATIONS; // 0 = nose (front), 1 = back
233
+ // Cosine clustering at the nose, where curvature is highest
234
+ const t = 1 - Math.cos(Math.PI / 2 * i / HUB_STATIONS); // 0 = nose (front), 1 = back
210
235
 
211
236
  let r;
212
237
  if (t < 0.35) {
213
- // Nose: parabolic ogive for low drag
214
- const tn = t / 0.35;
215
- r = spinnerR * Math.sqrt(tn);
238
+ // Nose: elliptical ogive rounds to a closed dome instead of a flat disc
239
+ const tn = (0.35 - t) / 0.35;
240
+ r = spinnerR * Math.sqrt(Math.max(0, 1 - tn * tn));
216
241
  } else if (t < 0.7) {
217
242
  // Cylindrical body where blades attach
218
243
  r = spinnerR;
@@ -222,41 +247,51 @@ for (let i = 0; i <= HUB_STATIONS; i++) {
222
247
  r = spinnerR * (1 - 0.25 * tb * tb);
223
248
  }
224
249
 
225
- hubProfiles.push(circle2d(Math.max(r, 3)));
226
- hubHeights.push(-spinnerLen * 0.35 + t * spinnerLen);
250
+ hubProfiles.push(circle2d(Math.max(r, 0.8)));
251
+ hubHeights.push(-spinnerLen * 0.525 + t * spinnerLen);
227
252
  }
228
253
 
229
254
  const spinner = loft(hubProfiles, hubHeights, { edgeLength: meshRes });
230
255
 
231
256
  // ─── Assembly ───────────────────────────────────────────────────
257
+ //
258
+ // Real propellers are built from separate parts: the blades bolt into an
259
+ // internal hub barrel, and the spinner is a thin dome with blade-shaped
260
+ // cutouts (with running clearance) that the blades pass through. Modeling
261
+ // it that way also keeps the aerodynamic skin free of boolean cuts and
262
+ // near-tangent surface overlaps.
232
263
 
233
264
  const allBlades = circularPattern(blade, numBlades);
234
265
 
266
+ // Internal hub barrel the blade shanks merge into (hidden by the spinner)
267
+ const hubBarrel = cylinder(spinnerLen * 0.5, rHub * 0.62)
268
+ .translate(0, 0, -spinnerLen * 0.2);
269
+
270
+ const bladeAssembly = union(allBlades, hubBarrel);
271
+
272
+ // Blade-shaped cutouts through the spinner with a small running
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);
276
+ const spinnerCutouts = circularPattern(bladeCutout, numBlades);
277
+
235
278
  // ─── Optional: Airfoil Section Visualization ────────────────────
236
279
  //
237
280
  // When enabled, shows thin extrusions of each airfoil cross-section
238
281
  // along the blade, revealing the twist and chord distribution.
239
282
 
240
283
  const result = [
241
- { name: "Blades", shape: allBlades.color('#2d2d30') },
242
- { name: "Spinner", shape: spinner.color('#c8c8cc') },
284
+ { name: "Blades", shape: bladeAssembly.color('#2d2d30') },
285
+ { name: "Spinner", shape: spinner.subtract(spinnerCutouts).color('#c8c8cc') },
243
286
  ];
244
287
 
245
288
  if (showSections) {
246
289
  const sectionShapes = [];
247
290
  for (let i = 0; i <= NUM_STATIONS; i++) {
248
- const rNorm = i / NUM_STATIONS;
291
+ const rNorm = 0.5 - 0.5 * Math.cos(Math.PI * i / NUM_STATIONS);
249
292
  const r = rHub + rNorm * (R - rHub);
250
293
 
251
- const chord = Math.max(chordAt(rNorm), 5);
252
- const thick = thicknessRatioAt(rNorm);
253
- const camber = camberAt(rNorm);
254
- const twist = twistAt(r);
255
-
256
- let pts = nacaPoints(camber, CAMBER_POS, thick, chord, NACA_PTS);
257
- pts = rotate2D(pts, 90 + twist);
258
-
259
- const section = polygon(pts).extrude(2)
294
+ const section = bladeSection(rNorm, r).extrude(2)
260
295
  .rotateY(90)
261
296
  .translate(r, 0, 0)
262
297
  .color('#ff4422');
@@ -5,4 +5,4 @@ const grid = [
5
5
  [[0,20,1], [10,20,6], [20,20,6], [30,20,1]],
6
6
  [[0,30,0], [10,30,2], [20,30,2], [30,30,0]],
7
7
  ];
8
- return nurbsSurface(grid, { thickness: 1.5 });
8
+ return Surface.Nurbs(grid, { thickness: 1.5 });
@@ -51,7 +51,7 @@ const lensR = Param.number("Lens Radius", 6, { min: 3, max: 10, unit: "mm" });
51
51
  const lensGap = Param.number("Lens Gap", 3, { min: 1, max: 8, unit: "mm" });
52
52
 
53
53
  // Use Rectangle2D entity to derive lens positions from island bounds
54
- const camRect = Rectangle2D.fromCenterAndDimensions(point(camX, camY), camSize, camSize);
54
+ const camRect = Rectangle2D.fromCenterAndDimensions(new Point2D(camX, camY), camSize, camSize);
55
55
  const triRadius = camSize / 2 - lensR - lensGap;
56
56
 
57
57
  // Equilateral triangle: two lenses stacked on outer (left) edge,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forgecad",
3
- "version": "0.9.15",
3
+ "version": "0.10.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",
@@ -32,6 +32,9 @@
32
32
  "check": {
33
33
  "description": "Run model-focused readiness checks."
34
34
  },
35
+ "context": {
36
+ "description": "Read and render submitted marker context for agent workflows."
37
+ },
35
38
  "compare": {
36
39
  "description": "Compare ForgeCAD scripts and imported 3D assets."
37
40
  },