fluidcad 0.0.37 → 0.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/lib/dist/core/2d/aline.d.ts +0 -8
  2. package/lib/dist/core/2d/aline.js +3 -22
  3. package/lib/dist/core/2d/arc.d.ts +1 -23
  4. package/lib/dist/core/2d/arc.js +11 -28
  5. package/lib/dist/core/2d/circle.d.ts +1 -8
  6. package/lib/dist/core/2d/circle.js +7 -24
  7. package/lib/dist/core/2d/ellipse.d.ts +1 -17
  8. package/lib/dist/core/2d/ellipse.js +7 -45
  9. package/lib/dist/core/2d/hline.d.ts +0 -7
  10. package/lib/dist/core/2d/hline.js +5 -27
  11. package/lib/dist/core/2d/intersect.d.ts +0 -7
  12. package/lib/dist/core/2d/intersect.js +0 -13
  13. package/lib/dist/core/2d/line.d.ts +1 -8
  14. package/lib/dist/core/2d/line.js +6 -24
  15. package/lib/dist/core/2d/offset.d.ts +1 -11
  16. package/lib/dist/core/2d/offset.js +0 -16
  17. package/lib/dist/core/2d/polygon.d.ts +1 -17
  18. package/lib/dist/core/2d/polygon.js +18 -37
  19. package/lib/dist/core/2d/project.d.ts +0 -7
  20. package/lib/dist/core/2d/project.js +0 -13
  21. package/lib/dist/core/2d/rect.d.ts +1 -9
  22. package/lib/dist/core/2d/rect.js +0 -19
  23. package/lib/dist/core/2d/slot.d.ts +0 -23
  24. package/lib/dist/core/2d/slot.js +18 -37
  25. package/lib/dist/core/2d/text.d.ts +0 -7
  26. package/lib/dist/core/2d/text.js +0 -14
  27. package/lib/dist/core/2d/vline.d.ts +0 -7
  28. package/lib/dist/core/2d/vline.js +5 -23
  29. package/lib/dist/core/fillet.js +7 -0
  30. package/lib/dist/core/index.d.ts +1 -1
  31. package/lib/dist/core/interfaces.d.ts +43 -0
  32. package/lib/dist/core/plane.d.ts +26 -6
  33. package/lib/dist/core/plane.js +21 -44
  34. package/lib/dist/features/2d/connect.d.ts +2 -0
  35. package/lib/dist/features/2d/connect.js +3 -0
  36. package/lib/dist/features/2d/intersect.js +4 -1
  37. package/lib/dist/features/2d/offset.js +2 -2
  38. package/lib/dist/features/frozen-geometry.d.ts +29 -0
  39. package/lib/dist/features/frozen-geometry.js +62 -0
  40. package/lib/dist/features/loft.d.ts +38 -1
  41. package/lib/dist/features/loft.js +133 -8
  42. package/lib/dist/features/plane-from-object.d.ts +16 -4
  43. package/lib/dist/features/plane-from-object.js +101 -8
  44. package/lib/dist/features/rib.js +11 -1
  45. package/lib/dist/features/shell.d.ts +1 -1
  46. package/lib/dist/features/shell.js +9 -0
  47. package/lib/dist/features/sweep.d.ts +11 -1
  48. package/lib/dist/features/sweep.js +43 -7
  49. package/lib/dist/helpers/clone-transform.js +62 -5
  50. package/lib/dist/helpers/scene-helpers.d.ts +12 -0
  51. package/lib/dist/helpers/scene-helpers.js +26 -0
  52. package/lib/dist/math/bspline-interpolation.d.ts +33 -6
  53. package/lib/dist/math/bspline-interpolation.js +187 -84
  54. package/lib/dist/oc/loft/constrained-loft.d.ts +32 -0
  55. package/lib/dist/oc/loft/constrained-loft.js +61 -0
  56. package/lib/dist/oc/loft/curve-data.d.ts +18 -0
  57. package/lib/dist/oc/loft/curve-data.js +54 -0
  58. package/lib/dist/oc/loft/curve-eval.d.ts +23 -0
  59. package/lib/dist/oc/loft/curve-eval.js +84 -0
  60. package/lib/dist/oc/loft/guided-loft.d.ts +89 -0
  61. package/lib/dist/oc/loft/guided-loft.js +368 -0
  62. package/lib/dist/oc/loft/section-compatibility.d.ts +131 -0
  63. package/lib/dist/oc/loft/section-compatibility.js +481 -0
  64. package/lib/dist/oc/loft/section-curve.d.ts +53 -0
  65. package/lib/dist/oc/loft/section-curve.js +264 -0
  66. package/lib/dist/oc/loft/skinning.d.ts +104 -0
  67. package/lib/dist/oc/loft/skinning.js +299 -0
  68. package/lib/dist/oc/loft-ops.d.ts +28 -1
  69. package/lib/dist/oc/loft-ops.js +31 -1
  70. package/lib/dist/oc/ncollection.d.ts +19 -0
  71. package/lib/dist/oc/ncollection.js +69 -0
  72. package/lib/dist/oc/rib-ops.js +5 -17
  73. package/lib/dist/oc/sweep-ops.d.ts +7 -16
  74. package/lib/dist/oc/sweep-ops.js +67 -99
  75. package/lib/dist/oc/thin-face-maker.d.ts +0 -19
  76. package/lib/dist/oc/thin-face-maker.js +3 -68
  77. package/lib/dist/oc/wire-extend-ops.d.ts +12 -0
  78. package/lib/dist/oc/wire-extend-ops.js +42 -0
  79. package/lib/dist/oc/wire-ops.d.ts +28 -2
  80. package/lib/dist/oc/wire-ops.js +88 -4
  81. package/lib/dist/oc/wrap-ops.js +8 -15
  82. package/lib/dist/tests/features/2d/circle.test.js +0 -10
  83. package/lib/dist/tests/features/2d/ellipse.test.js +0 -30
  84. package/lib/dist/tests/features/2d/line.test.js +0 -5
  85. package/lib/dist/tests/features/2d/offset.test.js +74 -11
  86. package/lib/dist/tests/features/2d/polygon.test.js +0 -16
  87. package/lib/dist/tests/features/2d/rect.test.js +0 -11
  88. package/lib/dist/tests/features/2d/slot.test.js +0 -8
  89. package/lib/dist/tests/features/fillet2d.test.js +37 -1
  90. package/lib/dist/tests/features/loft-conditions.test.d.ts +1 -0
  91. package/lib/dist/tests/features/loft-conditions.test.js +246 -0
  92. package/lib/dist/tests/features/loft-guides.test.d.ts +1 -0
  93. package/lib/dist/tests/features/loft-guides.test.js +276 -0
  94. package/lib/dist/tests/features/plane.test.js +95 -0
  95. package/lib/dist/tests/features/repeat-sweep-borrowed-path.test.d.ts +1 -0
  96. package/lib/dist/tests/features/repeat-sweep-borrowed-path.test.js +35 -0
  97. package/lib/dist/tests/features/rib.test.js +50 -0
  98. package/lib/dist/tests/features/shell.test.js +35 -1
  99. package/lib/dist/tests/features/sweep.test.js +127 -1
  100. package/lib/dist/tests/features/text.test.js +33 -14
  101. package/lib/dist/tests/math/bspline-interpolation.test.js +97 -1
  102. package/lib/dist/tsconfig.tsbuildinfo +1 -1
  103. package/llm-docs/api/index.json +1 -1
  104. package/llm-docs/api/types/loft.md +36 -1
  105. package/llm-docs/api/types/sweep.md +13 -1
  106. package/llm-docs/api/types/text.md +2 -2
  107. package/llm-docs/index.json +5 -5
  108. package/package.json +1 -1
  109. package/server/dist/fluidcad-server.d.ts +1 -1
  110. package/server/dist/fluidcad-server.js +11 -1
  111. package/server/dist/routes/params.js +1 -1
  112. package/ui/dist/assets/{index-no7mtr5s.js → index-D8zV21wB.js} +83 -83
  113. package/ui/dist/index.html +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-06-12T18:19:00.445Z",
3
+ "generatedAt": "2026-07-05T08:56:29.709Z",
4
4
  "symbols": {
5
5
  "arc": "api/arc",
6
6
  "axis": "api/axis",
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  id: api/types/loft
3
3
  title: Loft
4
- summary: "The Loft type. Extends BooleanOperation; adds 11 methods."
4
+ summary: "The Loft type. Extends BooleanOperation; adds 14 methods."
5
5
  tags: [api, type, interface]
6
6
  symbols: [Loft, ILoft]
7
7
  seeAlso: [api/loft, api/types/boolean-operation]
@@ -10,6 +10,9 @@ seeAlso: [api/loft, api/types/boolean-operation]
10
10
 
11
11
  ```ts
12
12
  interface Loft extends BooleanOperation {
13
+ guides(...guides: SceneObject[]): this;
14
+ startCondition(type: LoftConditionType, magnitude?: NumberParam): this;
15
+ endCondition(type: LoftConditionType, magnitude?: NumberParam): this;
13
16
  startFaces(...args: (number | FaceFilter)[]): SceneObject;
14
17
  endFaces(...args: (number | FaceFilter)[]): SceneObject;
15
18
  sideFaces(...args: (number | FaceFilter)[]): SceneObject;
@@ -29,6 +32,38 @@ Extends [[api/types/boolean-operation]].
29
32
 
30
33
  ## Methods
31
34
 
35
+ ### `guides()`
36
+
37
+ Adds side guide curves (rails) the loft surface must follow. Supports one
38
+ or two guides in total; a single argument may carry several separate
39
+ curves (e.g. a sketch holding a curve and its mirror) — each connected
40
+ chain counts as one guide. Every guide must pass through every profile.
41
+ Composes with start/end conditions (the condition fades out around each
42
+ guide's contact point — rails win locally, the condition shapes the
43
+ rest). Cannot be combined with thin mode.
44
+
45
+ | Parameter | Type | Description |
46
+ | --- | --- | --- |
47
+ | `...guides` | [[api/types/scene-object]][] | Sketches or edges forming the guide curves. *(optional)* |
48
+
49
+ ### `startCondition()`
50
+
51
+ Constrains how the surface leaves the first profile.
52
+
53
+ | Parameter | Type | Description |
54
+ | --- | --- | --- |
55
+ | `type` | `LoftConditionType` | `'none'`, `'normal'` or `'tangent'` — see LoftConditionType. |
56
+ | `magnitude` | `NumberParam` | Scales the takeoff strength; defaults to 1. Negative values flip the direction (e.g. inward instead of outward for `'tangent'`). *(optional)* |
57
+
58
+ ### `endCondition()`
59
+
60
+ Constrains how the surface arrives at the last profile.
61
+
62
+ | Parameter | Type | Description |
63
+ | --- | --- | --- |
64
+ | `type` | `LoftConditionType` | `'none'`, `'normal'` or `'tangent'` — see LoftConditionType. |
65
+ | `magnitude` | `NumberParam` | Scales the arrival strength; defaults to 1. Negative values flip the direction (e.g. inward instead of outward for `'tangent'`). *(optional)* |
66
+
32
67
  ### `startFaces()`
33
68
 
34
69
  Selects faces on the first profile plane of the loft.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  id: api/types/sweep
3
3
  title: Sweep
4
- summary: "The Sweep type. Extends BooleanOperation; adds 15 methods."
4
+ summary: "The Sweep type. Extends BooleanOperation; adds 16 methods."
5
5
  tags: [api, type, interface]
6
6
  symbols: [Sweep, ISweep]
7
7
  seeAlso: [api/sweep, api/types/boolean-operation]
@@ -20,6 +20,7 @@ interface Sweep extends BooleanOperation {
20
20
  internalEdges(...args: (number | EdgeFilter)[]): SceneObject;
21
21
  draft(value: NumberParam | [NumberParam, NumberParam]): this;
22
22
  endOffset(value: NumberParam): this;
23
+ extend(side: SweepSide, amount: NumberParam): this;
23
24
  drill(value?: boolean): this;
24
25
  pick(...points: Point2DLike[]): this;
25
26
  thin(offset: NumberParam): this;
@@ -129,6 +130,17 @@ Offsets the end face by a specified distance along the sweep direction.
129
130
  | --- | --- | --- |
130
131
  | `value` | `NumberParam` | The offset distance. |
131
132
 
133
+ ### `extend()`
134
+
135
+ Extends the swept solid beyond the path at the given end by `amount`,
136
+ continuing straight along the path's tangent direction there. Chain twice to
137
+ extend both ends, e.g. `.extend('start', 10).extend('end', 5)`.
138
+
139
+ | Parameter | Type | Description |
140
+ | --- | --- | --- |
141
+ | `side` | `SweepSide` | Which end of the path to extend: `'start'` or `'end'`. |
142
+ | `amount` | `NumberParam` | Distance to extend, in mm (positive; non-positive is a no-op). |
143
+
132
144
  ### `drill()`
133
145
 
134
146
  Enables or disables drill mode.
@@ -15,7 +15,7 @@ interface Text extends ExtrudableGeometry {
15
15
  weight(value: string | number): this;
16
16
  bold(): this;
17
17
  italic(value?: boolean): this;
18
- align(value: "left" | "right" | "center" | "start" | "end" | "space-between" | "space-around"): this;
18
+ align(value: "left" | "right" | "start" | "end" | "center" | "space-between" | "space-around"): this;
19
19
  lineSpacing(value: number): this;
20
20
  letterSpacing(value: number): this;
21
21
  offset(value: number): this;
@@ -82,7 +82,7 @@ synonyms of `"start"` and `"end"`.
82
82
 
83
83
  | Parameter | Type | Description |
84
84
  | --- | --- | --- |
85
- | `value` | `"left"` \| `"right"` \| `"center"` \| `"start"` \| `"end"` \| `"space-between"` \| `"space-around"` | `"left"`/`"start"` (default), `"center"`, `"right"`/`"end"`, `"space-between"`, or `"space-around"`. |
85
+ | `value` | `"left"` \| `"right"` \| `"start"` \| `"end"` \| `"center"` \| `"space-between"` \| `"space-around"` | `"left"`/`"start"` (default), `"center"`, `"right"`/`"end"`, `"space-between"`, or `"space-around"`. |
86
86
 
87
87
  ### `lineSpacing()`
88
88
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-06-12T18:19:00.445Z",
3
+ "generatedAt": "2026-07-05T08:56:29.709Z",
4
4
  "docs": [
5
5
  {
6
6
  "id": "api/arc",
@@ -1289,7 +1289,7 @@
1289
1289
  {
1290
1290
  "id": "api/types/loft",
1291
1291
  "title": "Loft",
1292
- "summary": "The Loft type. Extends BooleanOperation; adds 11 methods.",
1292
+ "summary": "The Loft type. Extends BooleanOperation; adds 14 methods.",
1293
1293
  "tags": [
1294
1294
  "api",
1295
1295
  "type",
@@ -1304,7 +1304,7 @@
1304
1304
  "api/types/boolean-operation"
1305
1305
  ],
1306
1306
  "file": "api/types/loft.md",
1307
- "bodyLength": 4872
1307
+ "bodyLength": 6520
1308
1308
  },
1309
1309
  {
1310
1310
  "id": "api/types/mirror",
@@ -1609,7 +1609,7 @@
1609
1609
  {
1610
1610
  "id": "api/types/sweep",
1611
1611
  "title": "Sweep",
1612
- "summary": "The Sweep type. Extends BooleanOperation; adds 15 methods.",
1612
+ "summary": "The Sweep type. Extends BooleanOperation; adds 16 methods.",
1613
1613
  "tags": [
1614
1614
  "api",
1615
1615
  "type",
@@ -1624,7 +1624,7 @@
1624
1624
  "api/types/boolean-operation"
1625
1625
  ],
1626
1626
  "file": "api/types/sweep.md",
1627
- "bodyLength": 5877
1627
+ "bodyLength": 6391
1628
1628
  },
1629
1629
  {
1630
1630
  "id": "api/types/tangent-arc-two-objects",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluidcad",
3
- "version": "0.0.37",
3
+ "version": "0.0.39",
4
4
  "description": "Parametric CAD modeling library using javascript",
5
5
  "author": "Marwan Aouida <contact@marwan.dev>",
6
6
  "license": "MIT",
@@ -114,7 +114,7 @@ export declare class FluidCadServer {
114
114
  processFile(filePath: string, ignoreCache?: boolean): Promise<SceneRenderedData | null>;
115
115
  updateLiveCode(fileName: string, code: string): Promise<SceneRenderedData | null>;
116
116
  rollbackFromUI(index: number): Promise<SceneRenderedData | null>;
117
- recomputeCurrentFile(): Promise<SceneRenderedData | null>;
117
+ recomputeCurrentFile(forceFullRebuild?: boolean): Promise<SceneRenderedData | null>;
118
118
  rollback(fileName: string, index: number): Promise<SceneRenderedData | null>;
119
119
  importFile(workspacePath: string, fileName: string, data: string): Promise<void>;
120
120
  getShapeProperties(shapeId: string): any;
@@ -220,13 +220,23 @@ export class FluidCadServer {
220
220
  async rollbackFromUI(index) {
221
221
  return this.rollback(this.currentFileName, index);
222
222
  }
223
- async recomputeCurrentFile() {
223
+ async recomputeCurrentFile(forceFullRebuild = false) {
224
224
  if (!this.currentFilePath) {
225
225
  return null;
226
226
  }
227
227
  const sessionId = this.currentFileName;
228
228
  this.renderingCache.delete(sessionId);
229
229
  this.lastRendered.delete(sessionId);
230
+ if (forceFullRebuild) {
231
+ // Drop the incremental-compare baseline so every object is rebuilt from
232
+ // scratch instead of being carried over as cached. Without this, an
233
+ // unchanged file compares equal at every index, the whole scene is
234
+ // marked cached, and the render reuses all geometry — so the explicit
235
+ // "Recompute scene" action does no visible work and reports no build
236
+ // timings (buildDurationMs is only recorded for objects that rebuild).
237
+ // Param edits keep the baseline so slider drags stay fast.
238
+ this.previousScenes.delete(sessionId);
239
+ }
230
240
  return this.processFileInternal(sessionId, this.currentFilePath, true);
231
241
  }
232
242
  async rollback(fileName, index) {
@@ -2,7 +2,7 @@ import { Router } from 'express';
2
2
  export function createParamsRouter(fluidCadServer, sendToExtension, broadcastToUI) {
3
3
  const router = Router();
4
4
  router.post('/recompute', async (_req, res) => {
5
- const data = await fluidCadServer.recomputeCurrentFile();
5
+ const data = await fluidCadServer.recomputeCurrentFile(true);
6
6
  if (!data) {
7
7
  res.status(404).json({ error: 'No active scene' });
8
8
  return;