fluidcad 0.0.33 → 0.0.34

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 (237) hide show
  1. package/README.md +3 -2
  2. package/bin/commands/init.js +55 -0
  3. package/bin/commands/mcp.js +33 -0
  4. package/bin/commands/serve.js +77 -0
  5. package/bin/fluidcad.js +15 -107
  6. package/lib/dist/common/scene-object.d.ts +2 -1
  7. package/lib/dist/common/scene-object.js +3 -2
  8. package/lib/dist/core/2d/tarc.d.ts +20 -2
  9. package/lib/dist/core/2d/tarc.js +24 -0
  10. package/lib/dist/core/interfaces.d.ts +31 -2
  11. package/lib/dist/core/repeat.js +62 -46
  12. package/lib/dist/features/2d/arc.d.ts +8 -2
  13. package/lib/dist/features/2d/arc.js +94 -17
  14. package/lib/dist/features/2d/back.js +3 -2
  15. package/lib/dist/features/2d/sketch.d.ts +4 -0
  16. package/lib/dist/features/2d/sketch.js +21 -0
  17. package/lib/dist/features/2d/tarc-constrained.d.ts +2 -0
  18. package/lib/dist/features/2d/tarc-constrained.js +8 -0
  19. package/lib/dist/features/2d/tarc-radius-to-object.d.ts +16 -0
  20. package/lib/dist/features/2d/tarc-radius-to-object.js +58 -0
  21. package/lib/dist/features/2d/tarc-to-object.d.ts +18 -0
  22. package/lib/dist/features/2d/tarc-to-object.js +66 -0
  23. package/lib/dist/features/2d/tarc-to-point-tangent.d.ts +2 -0
  24. package/lib/dist/features/2d/tarc-to-point-tangent.js +3 -0
  25. package/lib/dist/features/2d/tarc-to-point.d.ts +2 -0
  26. package/lib/dist/features/2d/tarc-to-point.js +3 -0
  27. package/lib/dist/features/2d/tarc-with-tangent.d.ts +2 -0
  28. package/lib/dist/features/2d/tarc-with-tangent.js +3 -0
  29. package/lib/dist/features/2d/tarc.d.ts +2 -0
  30. package/lib/dist/features/2d/tarc.js +3 -0
  31. package/lib/dist/features/extrude-base.d.ts +9 -0
  32. package/lib/dist/features/extrude-base.js +22 -0
  33. package/lib/dist/features/extrude-to-face.js +1 -5
  34. package/lib/dist/features/extrude-two-distances.js +1 -2
  35. package/lib/dist/features/extrude.js +1 -2
  36. package/lib/dist/features/mirror-feature.d.ts +3 -2
  37. package/lib/dist/features/mirror-feature.js +1 -1
  38. package/lib/dist/features/repeat-circular.d.ts +3 -3
  39. package/lib/dist/features/repeat-circular.js +8 -1
  40. package/lib/dist/features/repeat-linear.d.ts +4 -2
  41. package/lib/dist/features/repeat-linear.js +10 -1
  42. package/lib/dist/features/repeat-matrix.d.ts +3 -1
  43. package/lib/dist/features/repeat-matrix.js +7 -2
  44. package/lib/dist/features/shell.d.ts +4 -1
  45. package/lib/dist/features/shell.js +14 -3
  46. package/lib/dist/helpers/clone-transform.d.ts +2 -1
  47. package/lib/dist/index.d.ts +7 -1
  48. package/lib/dist/index.js +3 -3
  49. package/lib/dist/math/lazy-matrix.d.ts +31 -0
  50. package/lib/dist/math/lazy-matrix.js +66 -0
  51. package/lib/dist/oc/constraints/constraint-solver-adaptor.d.ts +5 -0
  52. package/lib/dist/oc/constraints/constraint-solver-adaptor.js +16 -0
  53. package/lib/dist/oc/constraints/constraint-solver.d.ts +4 -0
  54. package/lib/dist/oc/constraints/curve/curve-constraint-solver.d.ts +4 -0
  55. package/lib/dist/oc/constraints/curve/curve-constraint-solver.js +3 -0
  56. package/lib/dist/oc/constraints/geometric/geometric-constraint-solver.d.ts +6 -1
  57. package/lib/dist/oc/constraints/geometric/geometric-constraint-solver.js +4 -0
  58. package/lib/dist/oc/constraints/geometric/tangent-arc-from-point-tangent.d.ts +8 -0
  59. package/lib/dist/oc/constraints/geometric/tangent-arc-from-point-tangent.js +111 -0
  60. package/lib/dist/oc/constraints/geometric/tangent-arc-radius-to-object.d.ts +8 -0
  61. package/lib/dist/oc/constraints/geometric/tangent-arc-radius-to-object.js +161 -0
  62. package/lib/dist/oc/mesh.d.ts +9 -4
  63. package/lib/dist/oc/mesh.js +14 -13
  64. package/lib/dist/oc/shell-ops.d.ts +2 -1
  65. package/lib/dist/oc/shell-ops.js +5 -2
  66. package/lib/dist/rendering/mesh-builder.d.ts +3 -0
  67. package/lib/dist/rendering/mesh-builder.js +8 -4
  68. package/lib/dist/rendering/render-edge.d.ts +2 -1
  69. package/lib/dist/rendering/render-edge.js +2 -2
  70. package/lib/dist/rendering/render-face.d.ts +2 -1
  71. package/lib/dist/rendering/render-face.js +2 -2
  72. package/lib/dist/rendering/render-solid.d.ts +2 -1
  73. package/lib/dist/rendering/render-solid.js +2 -2
  74. package/lib/dist/rendering/render-wire.d.ts +2 -1
  75. package/lib/dist/rendering/render-wire.js +2 -2
  76. package/lib/dist/rendering/render.d.ts +3 -0
  77. package/lib/dist/rendering/render.js +7 -2
  78. package/lib/dist/scene-manager.d.ts +4 -2
  79. package/lib/dist/scene-manager.js +12 -4
  80. package/lib/dist/tests/features/2d/arc.test.js +64 -0
  81. package/lib/dist/tests/features/2d/back.test.js +17 -1
  82. package/lib/dist/tests/features/2d/tarc.test.js +157 -0
  83. package/lib/dist/tests/features/repeat-user-repro.test.d.ts +1 -0
  84. package/lib/dist/tests/features/repeat-user-repro.test.js +60 -0
  85. package/lib/dist/tests/features/shell.test.js +36 -0
  86. package/lib/dist/tests/global-setup.js +2 -1
  87. package/lib/dist/tests/helpers/extract-blocks.d.ts +9 -0
  88. package/lib/dist/tests/helpers/extract-blocks.js +56 -0
  89. package/lib/dist/tests/llm-docs-examples.test.d.ts +1 -0
  90. package/lib/dist/tests/llm-docs-examples.test.js +62 -0
  91. package/lib/dist/tests/setup.js +2 -1
  92. package/lib/dist/tsconfig.tsbuildinfo +1 -1
  93. package/llm-docs/.coverage-allowlist.txt +9 -0
  94. package/llm-docs/api/arc.md +48 -0
  95. package/llm-docs/api/axis.md +42 -0
  96. package/llm-docs/api/bezier.md +42 -0
  97. package/llm-docs/api/booleans.md +44 -0
  98. package/llm-docs/api/chamfer.md +40 -0
  99. package/llm-docs/api/circle.md +36 -0
  100. package/llm-docs/api/color.md +34 -0
  101. package/llm-docs/api/connect.md +41 -0
  102. package/llm-docs/api/constraint-qualifiers.md +48 -0
  103. package/llm-docs/api/copy.md +63 -0
  104. package/llm-docs/api/cursor-lines.md +50 -0
  105. package/llm-docs/api/cursor-move.md +61 -0
  106. package/llm-docs/api/cut.md +55 -0
  107. package/llm-docs/api/draft.md +36 -0
  108. package/llm-docs/api/edge-filter.md +57 -0
  109. package/llm-docs/api/ellipse.md +34 -0
  110. package/llm-docs/api/extrude.md +74 -0
  111. package/llm-docs/api/face-filter.md +61 -0
  112. package/llm-docs/api/fillet.md +51 -0
  113. package/llm-docs/api/index.json +139 -0
  114. package/llm-docs/api/line.md +42 -0
  115. package/llm-docs/api/load.md +37 -0
  116. package/llm-docs/api/local.md +38 -0
  117. package/llm-docs/api/loft.md +37 -0
  118. package/llm-docs/api/mirror.md +44 -0
  119. package/llm-docs/api/offset.md +36 -0
  120. package/llm-docs/api/part.md +40 -0
  121. package/llm-docs/api/plane.md +44 -0
  122. package/llm-docs/api/polygon.md +37 -0
  123. package/llm-docs/api/primitive-solids.md +39 -0
  124. package/llm-docs/api/project-intersect.md +48 -0
  125. package/llm-docs/api/rect.md +48 -0
  126. package/llm-docs/api/remove.md +32 -0
  127. package/llm-docs/api/repeat.md +79 -0
  128. package/llm-docs/api/revolve.md +38 -0
  129. package/llm-docs/api/rib.md +40 -0
  130. package/llm-docs/api/rotate.md +37 -0
  131. package/llm-docs/api/select.md +41 -0
  132. package/llm-docs/api/shell.md +41 -0
  133. package/llm-docs/api/sketch.md +76 -0
  134. package/llm-docs/api/slot.md +36 -0
  135. package/llm-docs/api/split-trim.md +42 -0
  136. package/llm-docs/api/sweep.md +43 -0
  137. package/llm-docs/api/tarc.md +45 -0
  138. package/llm-docs/api/tcircle.md +38 -0
  139. package/llm-docs/api/tline.md +42 -0
  140. package/llm-docs/api/translate.md +40 -0
  141. package/llm-docs/api/types/aline.md +35 -0
  142. package/llm-docs/api/types/arc-angles.md +29 -0
  143. package/llm-docs/api/types/arc-points.md +48 -0
  144. package/llm-docs/api/types/axis-like.md +38 -0
  145. package/llm-docs/api/types/axis.md +21 -0
  146. package/llm-docs/api/types/boolean-operation.md +50 -0
  147. package/llm-docs/api/types/circular-repeat-options.md +31 -0
  148. package/llm-docs/api/types/common.md +32 -0
  149. package/llm-docs/api/types/cut.md +125 -0
  150. package/llm-docs/api/types/draft.md +21 -0
  151. package/llm-docs/api/types/extrudable-geometry.md +23 -0
  152. package/llm-docs/api/types/extrude.md +194 -0
  153. package/llm-docs/api/types/geometry.md +51 -0
  154. package/llm-docs/api/types/hline.md +35 -0
  155. package/llm-docs/api/types/linear-repeat-options.md +31 -0
  156. package/llm-docs/api/types/loft.md +154 -0
  157. package/llm-docs/api/types/mirror.md +35 -0
  158. package/llm-docs/api/types/offset.md +31 -0
  159. package/llm-docs/api/types/plane-like.md +35 -0
  160. package/llm-docs/api/types/plane-transform-options.md +29 -0
  161. package/llm-docs/api/types/plane.md +21 -0
  162. package/llm-docs/api/types/point-like.md +22 -0
  163. package/llm-docs/api/types/point2dlike.md +26 -0
  164. package/llm-docs/api/types/polygon.md +46 -0
  165. package/llm-docs/api/types/rect.md +128 -0
  166. package/llm-docs/api/types/revolve.md +102 -0
  167. package/llm-docs/api/types/rib.md +133 -0
  168. package/llm-docs/api/types/scene-object.md +33 -0
  169. package/llm-docs/api/types/select.md +21 -0
  170. package/llm-docs/api/types/shell.md +54 -0
  171. package/llm-docs/api/types/slot.md +43 -0
  172. package/llm-docs/api/types/sweep.md +189 -0
  173. package/llm-docs/api/types/tangent-arc-two-objects.md +46 -0
  174. package/llm-docs/api/types/transformable.md +93 -0
  175. package/llm-docs/api/types/trim.md +27 -0
  176. package/llm-docs/api/types/two-objects-tangent-line.md +46 -0
  177. package/llm-docs/api/types/vertex.md +17 -0
  178. package/llm-docs/api/types/vline.md +35 -0
  179. package/llm-docs/concepts/coordinate-system.md +45 -0
  180. package/llm-docs/concepts/history-and-rollback.md +40 -0
  181. package/llm-docs/concepts/last-selection.md +49 -0
  182. package/llm-docs/concepts/scene-graph.md +37 -0
  183. package/llm-docs/index.json +1750 -0
  184. package/mcp/dist/client.d.ts +64 -0
  185. package/mcp/dist/client.js +248 -0
  186. package/mcp/dist/discovery.d.ts +11 -0
  187. package/mcp/dist/discovery.js +78 -0
  188. package/mcp/dist/docs-index.d.ts +81 -0
  189. package/mcp/dist/docs-index.js +261 -0
  190. package/mcp/dist/resources.d.ts +4 -0
  191. package/mcp/dist/resources.js +115 -0
  192. package/mcp/dist/server.d.ts +12 -0
  193. package/mcp/dist/server.js +489 -0
  194. package/mcp/dist/tools/coordination.d.ts +9 -0
  195. package/mcp/dist/tools/coordination.js +46 -0
  196. package/mcp/dist/tools/docs.d.ts +66 -0
  197. package/mcp/dist/tools/docs.js +122 -0
  198. package/mcp/dist/tools/engine.d.ts +56 -0
  199. package/mcp/dist/tools/engine.js +145 -0
  200. package/mcp/dist/tools/inspection.d.ts +75 -0
  201. package/mcp/dist/tools/inspection.js +121 -0
  202. package/mcp/dist/tools/screenshot.d.ts +63 -0
  203. package/mcp/dist/tools/screenshot.js +263 -0
  204. package/mcp/dist/tools/source.d.ts +84 -0
  205. package/mcp/dist/tools/source.js +434 -0
  206. package/mcp/dist/tools/workspaces.d.ts +13 -0
  207. package/mcp/dist/tools/workspaces.js +33 -0
  208. package/mcp/dist/types.d.ts +18 -0
  209. package/mcp/dist/types.js +11 -0
  210. package/package.json +19 -5
  211. package/server/dist/code-editor.d.ts +36 -0
  212. package/server/dist/code-editor.js +8 -0
  213. package/server/dist/fluidcad-server.d.ts +50 -0
  214. package/server/dist/fluidcad-server.js +153 -1
  215. package/server/dist/global-registry.d.ts +30 -0
  216. package/server/dist/global-registry.js +126 -0
  217. package/server/dist/index.js +171 -26
  218. package/server/dist/instance-file.d.ts +31 -0
  219. package/server/dist/instance-file.js +73 -0
  220. package/server/dist/lint-fluid-js.d.ts +15 -0
  221. package/server/dist/lint-fluid-js.js +271 -0
  222. package/server/dist/routes/editor.d.ts +24 -0
  223. package/server/dist/routes/editor.js +44 -0
  224. package/server/dist/routes/export.d.ts +1 -1
  225. package/server/dist/routes/export.js +45 -8
  226. package/server/dist/routes/health.d.ts +7 -0
  227. package/server/dist/routes/health.js +14 -0
  228. package/server/dist/routes/lint.d.ts +10 -0
  229. package/server/dist/routes/lint.js +28 -0
  230. package/server/dist/routes/render.d.ts +33 -0
  231. package/server/dist/routes/render.js +34 -0
  232. package/server/dist/routes/scene.d.ts +5 -0
  233. package/server/dist/routes/scene.js +48 -0
  234. package/server/dist/routes/screenshot.js +68 -1
  235. package/server/dist/ws-protocol.d.ts +56 -2
  236. package/ui/dist/assets/{index-CFi9p7wR.js → index-BdqrMDRu.js} +21 -21
  237. package/ui/dist/index.html +1 -1
@@ -0,0 +1,66 @@
1
+ import { GeometrySceneObject } from "./geometry.js";
2
+ import { Vertex } from "../../common/vertex.js";
3
+ import { QualifiedSceneObject } from "./constraints/qualified-geometry.js";
4
+ import { createConstraintSolver } from "../../oc/constraints/create-solver.js";
5
+ export class TangentArcToObject extends GeometrySceneObject {
6
+ target;
7
+ flipped = false;
8
+ constructor(target) {
9
+ super();
10
+ this.target = target;
11
+ }
12
+ flip() {
13
+ this.flipped = true;
14
+ return this;
15
+ }
16
+ build() {
17
+ const plane = this.sketch.getPlane();
18
+ const startPoint = this.getCurrentPosition();
19
+ const startTangent = this.sketch.getTangentAt(this);
20
+ const targetShape = this.target.toQualifiedShape();
21
+ const solver = createConstraintSolver(false);
22
+ const result = solver.getTangentArcFromPointTangent(plane, startPoint, startTangent, targetShape, this.flipped);
23
+ for (let i = 0; i < result.edges.length; i++) {
24
+ this.setState(`edge-${i}`, result.edges[i]);
25
+ }
26
+ if (result.edges.length > 0) {
27
+ const lastEdge = result.edges[result.edges.length - 1];
28
+ const localStart = plane.worldToLocal(lastEdge.getFirstVertex().toPoint());
29
+ const localEnd = plane.worldToLocal(lastEdge.getLastVertex().toPoint());
30
+ this.setState('start', Vertex.fromPoint2D(localStart));
31
+ this.setState('end', Vertex.fromPoint2D(localEnd));
32
+ if (result.endTangent) {
33
+ this.setTangent(result.endTangent);
34
+ }
35
+ this.setCurrentPosition(localEnd);
36
+ }
37
+ this.addShapes(result.edges);
38
+ }
39
+ createCopy(remap) {
40
+ const remappedObject = remap.get(this.target.object) || this.target.object;
41
+ const target = new QualifiedSceneObject(remappedObject, this.target.qualifier);
42
+ const copy = new TangentArcToObject(target);
43
+ if (this.flipped) {
44
+ copy.flip();
45
+ }
46
+ return copy;
47
+ }
48
+ compareTo(other) {
49
+ if (!(other instanceof TangentArcToObject)) {
50
+ return false;
51
+ }
52
+ if (!super.compareTo(other)) {
53
+ return false;
54
+ }
55
+ return this.target.compareTo(other.target) && this.flipped === other.flipped;
56
+ }
57
+ getType() {
58
+ return 'tarc';
59
+ }
60
+ getUniqueType() {
61
+ return 'tarc-to-object';
62
+ }
63
+ serialize() {
64
+ return { flipped: this.flipped };
65
+ }
66
+ }
@@ -1,3 +1,4 @@
1
+ import { SceneObject } from "../../common/scene-object.js";
1
2
  import { GeometrySceneObject } from "./geometry.js";
2
3
  import { LazyVertex } from "../lazy-vertex.js";
3
4
  export declare class TangentArcToPointTangent extends GeometrySceneObject {
@@ -5,6 +6,7 @@ export declare class TangentArcToPointTangent extends GeometrySceneObject {
5
6
  startTangent: LazyVertex;
6
7
  constructor(endPoint: LazyVertex, startTangent: LazyVertex);
7
8
  build(): void;
9
+ createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
8
10
  compareTo(other: TangentArcToPointTangent): boolean;
9
11
  getType(): string;
10
12
  getUniqueType(): string;
@@ -62,6 +62,9 @@ export class TangentArcToPointTangent extends GeometrySceneObject {
62
62
  this.addShape(edge);
63
63
  this.setCurrentPosition(targetPoint);
64
64
  }
65
+ createCopy(remap) {
66
+ return new TangentArcToPointTangent(this.endPoint, this.startTangent);
67
+ }
65
68
  compareTo(other) {
66
69
  if (!(other instanceof TangentArcToPointTangent)) {
67
70
  return false;
@@ -1,9 +1,11 @@
1
+ import { SceneObject } from "../../common/scene-object.js";
1
2
  import { GeometrySceneObject } from "./geometry.js";
2
3
  import { LazyVertex } from "../lazy-vertex.js";
3
4
  export declare class TangentArcToPoint extends GeometrySceneObject {
4
5
  endPoint: LazyVertex;
5
6
  constructor(endPoint: LazyVertex);
6
7
  build(): void;
8
+ createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
7
9
  compareTo(other: TangentArcToPoint): boolean;
8
10
  getType(): string;
9
11
  getUniqueType(): string;
@@ -60,6 +60,9 @@ export class TangentArcToPoint extends GeometrySceneObject {
60
60
  this.addShape(edge);
61
61
  this.setCurrentPosition(targetPoint);
62
62
  }
63
+ createCopy(remap) {
64
+ return new TangentArcToPoint(this.endPoint);
65
+ }
63
66
  compareTo(other) {
64
67
  if (!(other instanceof TangentArcToPoint)) {
65
68
  return false;
@@ -1,3 +1,4 @@
1
+ import { SceneObject } from "../../common/scene-object.js";
1
2
  import { LazyVertex } from "../lazy-vertex.js";
2
3
  import { GeometrySceneObject } from "./geometry.js";
3
4
  export declare class TangentArcWithTangent extends GeometrySceneObject {
@@ -6,6 +7,7 @@ export declare class TangentArcWithTangent extends GeometrySceneObject {
6
7
  startTangent: LazyVertex;
7
8
  constructor(radius: number, endAngle: number, startTangent: LazyVertex);
8
9
  build(): void;
10
+ createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
9
11
  compareTo(other: TangentArcWithTangent): boolean;
10
12
  getType(): string;
11
13
  getUniqueType(): string;
@@ -46,6 +46,9 @@ export class TangentArcWithTangent extends GeometrySceneObject {
46
46
  this.addShape(edge);
47
47
  this.setCurrentPosition(endPoint);
48
48
  }
49
+ createCopy(remap) {
50
+ return new TangentArcWithTangent(this.radius, this.endAngle, this.startTangent);
51
+ }
49
52
  compareTo(other) {
50
53
  if (!(other instanceof TangentArcWithTangent)) {
51
54
  return false;
@@ -1,9 +1,11 @@
1
+ import { SceneObject } from "../../common/scene-object.js";
1
2
  import { GeometrySceneObject } from "./geometry.js";
2
3
  export declare class TangentArc extends GeometrySceneObject {
3
4
  radius: number;
4
5
  endAngle: number;
5
6
  constructor(radius: number, endAngle: number);
6
7
  build(): void;
8
+ createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
7
9
  compareTo(other: TangentArc): boolean;
8
10
  getType(): string;
9
11
  serialize(): {
@@ -48,6 +48,9 @@ export class TangentArc extends GeometrySceneObject {
48
48
  this.addShape(edge);
49
49
  this.setCurrentPosition(endPoint);
50
50
  }
51
+ createCopy(remap) {
52
+ return new TangentArc(this.radius, this.endAngle);
53
+ }
51
54
  compareTo(other) {
52
55
  if (!(other instanceof TangentArc)) {
53
56
  return false;
@@ -32,6 +32,15 @@ export declare abstract class ExtrudeBase extends SceneObject implements IExtrud
32
32
  get faceSource(): SceneObject | null;
33
33
  isFaceSourced(): boolean;
34
34
  getSource(): SceneObject | null;
35
+ /**
36
+ * Dependency tail for cloning: if the source is a sketch-bound geometry
37
+ * primitive, return its containing `Sketch` so cloneWithTransform pulls
38
+ * the sketch in too. The sketch's clone-mode build path then carries
39
+ * correctly-transformed shapes onto cloned children, and the cloned
40
+ * primitive retains a `Sketch` parent for plane resolution. Otherwise
41
+ * return the source as-is.
42
+ */
43
+ protected getSourceDependencies(): SceneObject[];
35
44
  getSourcePlane(): Plane | null;
36
45
  getSourceFaces(): Face[];
37
46
  startFaces(...args: number[] | FaceFilterBuilder[]): SceneObject;
@@ -2,6 +2,7 @@ import { Face } from "../common/face.js";
2
2
  import { Edge } from "../common/edge.js";
3
3
  import { SceneObject } from "../common/scene-object.js";
4
4
  import { LazySelectionSceneObject } from "./lazy-scene-object.js";
5
+ import { GeometrySceneObject } from "./2d/geometry.js";
5
6
  import { normalizePoint2D } from "../helpers/normalize.js";
6
7
  import { FaceOps } from "../oc/face-ops.js";
7
8
  import { FaceMaker2 } from "../oc/face-maker2.js";
@@ -81,6 +82,27 @@ export class ExtrudeBase extends SceneObject {
81
82
  getSource() {
82
83
  return this._extrudable ?? this._faceSource;
83
84
  }
85
+ /**
86
+ * Dependency tail for cloning: if the source is a sketch-bound geometry
87
+ * primitive, return its containing `Sketch` so cloneWithTransform pulls
88
+ * the sketch in too. The sketch's clone-mode build path then carries
89
+ * correctly-transformed shapes onto cloned children, and the cloned
90
+ * primitive retains a `Sketch` parent for plane resolution. Otherwise
91
+ * return the source as-is.
92
+ */
93
+ getSourceDependencies() {
94
+ const source = this.getSource();
95
+ if (!source) {
96
+ return [];
97
+ }
98
+ if (source instanceof GeometrySceneObject) {
99
+ const sketch = source.sketch;
100
+ if (sketch) {
101
+ return [sketch];
102
+ }
103
+ }
104
+ return [source];
105
+ }
84
106
  getSourcePlane() {
85
107
  if (this._extrudable) {
86
108
  return this._extrudable.getPlane();
@@ -282,11 +282,7 @@ export class ExtrudeToFace extends ExtrudeBase {
282
282
  return objects;
283
283
  }
284
284
  getDependencies() {
285
- const deps = [];
286
- const source = this.getSource();
287
- if (source) {
288
- deps.push(source);
289
- }
285
+ const deps = [...this.getSourceDependencies()];
290
286
  if (this.face instanceof SceneObject) {
291
287
  deps.push(this.face);
292
288
  }
@@ -158,8 +158,7 @@ export class ExtrudeTwoDistances extends ExtrudeBase {
158
158
  this.setFinalShapes(this.getShapes());
159
159
  }
160
160
  getDependencies() {
161
- const source = this.getSource();
162
- return source ? [source] : [];
161
+ return this.getSourceDependencies();
163
162
  }
164
163
  createCopy(remap) {
165
164
  const source = this.getSource();
@@ -286,8 +286,7 @@ export class Extrude extends ExtrudeBase {
286
286
  });
287
287
  }
288
288
  getDependencies() {
289
- const source = this.getSource();
290
- return source ? [source] : [];
289
+ return this.getSourceDependencies();
291
290
  }
292
291
  createCopy(remap) {
293
292
  const source = this.getSource();
@@ -1,10 +1,11 @@
1
1
  import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js";
2
2
  import { Matrix4 } from "../math/matrix4.js";
3
+ import { LazyMatrix } from "../math/lazy-matrix.js";
3
4
  import { PlaneObjectBase } from "./plane-renderable-base.js";
4
5
  export declare class MirrorFeature extends SceneObject {
5
6
  private plane;
6
- private _matrix?;
7
- constructor(plane: PlaneObjectBase, _matrix?: Matrix4);
7
+ private _matrix;
8
+ constructor(plane: PlaneObjectBase, _matrix: LazyMatrix);
8
9
  getTransformMatrix(): Matrix4 | null;
9
10
  isContainer(): boolean;
10
11
  build(context: BuildSceneObjectContext): void;
@@ -9,7 +9,7 @@ export class MirrorFeature extends SceneObject {
9
9
  this.setAlwaysVisible();
10
10
  }
11
11
  getTransformMatrix() {
12
- return this._matrix || null;
12
+ return this._matrix.resolve();
13
13
  }
14
14
  isContainer() {
15
15
  return true;
@@ -1,5 +1,5 @@
1
1
  import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js";
2
- import { Axis } from "../math/axis.js";
2
+ import { RepeatAxisSource } from "./repeat-linear.js";
3
3
  export type CircularRepeatOptions = {
4
4
  count: number;
5
5
  centered?: boolean;
@@ -12,10 +12,10 @@ export type CircularRepeatOptions = {
12
12
  offset?: never;
13
13
  });
14
14
  export declare class RepeatCircular extends SceneObject {
15
- axis: Axis;
15
+ axis: RepeatAxisSource;
16
16
  options: CircularRepeatOptions;
17
17
  targetObjects: SceneObject[] | null;
18
- constructor(axis: Axis, options: CircularRepeatOptions, targetObjects?: SceneObject[] | null);
18
+ constructor(axis: RepeatAxisSource, options: CircularRepeatOptions, targetObjects?: SceneObject[] | null);
19
19
  isContainer(): boolean;
20
20
  build(context: BuildSceneObjectContext): void;
21
21
  compareTo(other: RepeatCircular): boolean;
@@ -1,4 +1,8 @@
1
1
  import { SceneObject } from "../common/scene-object.js";
2
+ import { AxisObjectBase } from "./axis-renderable-base.js";
3
+ function axisOf(source) {
4
+ return source instanceof AxisObjectBase ? source.getAxis() : source;
5
+ }
2
6
  export class RepeatCircular extends SceneObject {
3
7
  axis;
4
8
  options;
@@ -14,6 +18,9 @@ export class RepeatCircular extends SceneObject {
14
18
  return true;
15
19
  }
16
20
  build(context) {
21
+ if (this.axis instanceof AxisObjectBase) {
22
+ this.axis.removeShapes(this);
23
+ }
17
24
  this.saveShapesSnapshot(context);
18
25
  }
19
26
  compareTo(other) {
@@ -23,7 +30,7 @@ export class RepeatCircular extends SceneObject {
23
30
  if (!super.compareTo(other)) {
24
31
  return false;
25
32
  }
26
- if (!this.axis.equals(other.axis)) {
33
+ if (!axisOf(this.axis).equals(axisOf(other.axis))) {
27
34
  return false;
28
35
  }
29
36
  const thisTargetObjects = this.targetObjects || [];
@@ -1,5 +1,7 @@
1
1
  import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js";
2
2
  import { Axis } from "../math/axis.js";
3
+ import { AxisObjectBase } from "./axis-renderable-base.js";
4
+ export type RepeatAxisSource = Axis | AxisObjectBase;
3
5
  export type LinearRepeatOptions = {
4
6
  count: number | number[];
5
7
  centered?: boolean;
@@ -12,10 +14,10 @@ export type LinearRepeatOptions = {
12
14
  offset?: never;
13
15
  });
14
16
  export declare class RepeatLinear extends SceneObject {
15
- axes: Axis[];
17
+ axes: RepeatAxisSource[];
16
18
  options: LinearRepeatOptions;
17
19
  targetObjects: SceneObject[] | null;
18
- constructor(axes: Axis[], options: LinearRepeatOptions, targetObjects?: SceneObject[] | null);
20
+ constructor(axes: RepeatAxisSource[], options: LinearRepeatOptions, targetObjects?: SceneObject[] | null);
19
21
  isContainer(): boolean;
20
22
  build(context: BuildSceneObjectContext): void;
21
23
  compareTo(other: RepeatLinear): boolean;
@@ -1,4 +1,8 @@
1
1
  import { SceneObject } from "../common/scene-object.js";
2
+ import { AxisObjectBase } from "./axis-renderable-base.js";
3
+ function axisOf(source) {
4
+ return source instanceof AxisObjectBase ? source.getAxis() : source;
5
+ }
2
6
  export class RepeatLinear extends SceneObject {
3
7
  axes;
4
8
  options;
@@ -14,6 +18,11 @@ export class RepeatLinear extends SceneObject {
14
18
  return true;
15
19
  }
16
20
  build(context) {
21
+ for (const axis of this.axes) {
22
+ if (axis instanceof AxisObjectBase) {
23
+ axis.removeShapes(this);
24
+ }
25
+ }
17
26
  this.saveShapesSnapshot(context);
18
27
  }
19
28
  compareTo(other) {
@@ -27,7 +36,7 @@ export class RepeatLinear extends SceneObject {
27
36
  return false;
28
37
  }
29
38
  for (let i = 0; i < this.axes.length; i++) {
30
- if (!this.axes[i].equals(other.axes[i])) {
39
+ if (!axisOf(this.axes[i]).equals(axisOf(other.axes[i]))) {
31
40
  return false;
32
41
  }
33
42
  }
@@ -1,9 +1,11 @@
1
1
  import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js";
2
2
  import { Matrix4 } from "../math/matrix4.js";
3
+ import { LazyMatrix } from "../math/lazy-matrix.js";
3
4
  export declare class RepeatMatrix extends SceneObject {
4
5
  private _matrix;
5
6
  targetObjects: SceneObject[];
6
- constructor(_matrix: Matrix4, targetObjects: SceneObject[]);
7
+ private sources;
8
+ constructor(_matrix: LazyMatrix, targetObjects: SceneObject[], sources?: SceneObject[]);
7
9
  getTransformMatrix(): Matrix4 | null;
8
10
  isContainer(): boolean;
9
11
  build(context: BuildSceneObjectContext): void;
@@ -2,19 +2,24 @@ import { SceneObject } from "../common/scene-object.js";
2
2
  export class RepeatMatrix extends SceneObject {
3
3
  _matrix;
4
4
  targetObjects;
5
- constructor(_matrix, targetObjects) {
5
+ sources;
6
+ constructor(_matrix, targetObjects, sources = []) {
6
7
  super();
7
8
  this._matrix = _matrix;
8
9
  this.targetObjects = targetObjects;
10
+ this.sources = sources;
9
11
  this.setAlwaysVisible();
10
12
  }
11
13
  getTransformMatrix() {
12
- return this._matrix;
14
+ return this._matrix.resolve();
13
15
  }
14
16
  isContainer() {
15
17
  return true;
16
18
  }
17
19
  build(context) {
20
+ for (const source of this.sources) {
21
+ source.removeShapes(this);
22
+ }
18
23
  this.saveShapesSnapshot(context);
19
24
  }
20
25
  compareTo(other) {
@@ -2,12 +2,14 @@ import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js"
2
2
  import { SelectSceneObject } from "./select.js";
3
3
  import { FaceFilterBuilder } from "../filters/face/face-filter.js";
4
4
  import { EdgeFilterBuilder } from "../filters/edge/edge-filter.js";
5
- import { IShell } from "../core/interfaces.js";
5
+ import { IShell, ShellJoinType } from "../core/interfaces.js";
6
6
  export declare class Shell extends SceneObject implements IShell {
7
7
  private thickness;
8
8
  private _faceSelections;
9
+ private _joinType;
9
10
  constructor(thickness: number, faceSelections?: SelectSceneObject[]);
10
11
  get faceSelections(): SelectSceneObject[];
12
+ join(type: ShellJoinType): this;
11
13
  validate(): void;
12
14
  build(context: BuildSceneObjectContext): void;
13
15
  internalFaces(...args: (number | FaceFilterBuilder)[]): SceneObject;
@@ -21,5 +23,6 @@ export declare class Shell extends SceneObject implements IShell {
21
23
  getType(): string;
22
24
  serialize(): {
23
25
  thickness: number;
26
+ joinType: "intersection" | "tangent";
24
27
  };
25
28
  }
@@ -11,6 +11,7 @@ import { requireShapes } from "../common/operand-check.js";
11
11
  export class Shell extends SceneObject {
12
12
  thickness;
13
13
  _faceSelections = [];
14
+ _joinType = 'arc';
14
15
  constructor(thickness, faceSelections) {
15
16
  super();
16
17
  this.thickness = thickness;
@@ -19,6 +20,10 @@ export class Shell extends SceneObject {
19
20
  get faceSelections() {
20
21
  return this._faceSelections;
21
22
  }
23
+ join(type) {
24
+ this._joinType = type;
25
+ return this;
26
+ }
22
27
  validate() {
23
28
  for (let i = 0; i < this._faceSelections.length; i++) {
24
29
  requireShapes(this._faceSelections[i], `face selection ${i + 1}`, "shell");
@@ -52,7 +57,7 @@ export class Shell extends SceneObject {
52
57
  continue;
53
58
  }
54
59
  try {
55
- const newShape = ShellOps.makeThickSolid(shape, targetFaces, this.thickness);
60
+ const newShape = ShellOps.makeThickSolid(shape, targetFaces, this.thickness, this._joinType);
56
61
  newShapes.push(newShape);
57
62
  const originalObj = shapeObjMap.get(shape);
58
63
  originalObj.removeShape(shape, this);
@@ -192,6 +197,9 @@ export class Shell extends SceneObject {
192
197
  if (this.thickness !== other.thickness) {
193
198
  return false;
194
199
  }
200
+ if (this._joinType !== other._joinType) {
201
+ return false;
202
+ }
195
203
  if (this._faceSelections.length !== other._faceSelections.length) {
196
204
  return false;
197
205
  }
@@ -207,14 +215,17 @@ export class Shell extends SceneObject {
207
215
  }
208
216
  createCopy(remap) {
209
217
  const faceSelections = this._faceSelections.map(sel => (remap.get(sel) || sel));
210
- return new Shell(this.thickness, faceSelections.length > 0 ? faceSelections : undefined);
218
+ const copy = new Shell(this.thickness, faceSelections.length > 0 ? faceSelections : undefined);
219
+ copy._joinType = this._joinType;
220
+ return copy;
211
221
  }
212
222
  getType() {
213
223
  return 'shell';
214
224
  }
215
225
  serialize() {
216
226
  return {
217
- thickness: this.thickness
227
+ thickness: this.thickness,
228
+ joinType: this._joinType !== 'arc' ? this._joinType : undefined
218
229
  };
219
230
  }
220
231
  }
@@ -1,3 +1,4 @@
1
1
  import { Matrix4 } from "../math/matrix4.js";
2
+ import { LazyMatrix } from "../math/lazy-matrix.js";
2
3
  import { SceneObject } from "../common/scene-object.js";
3
- export declare function cloneWithTransform(objects: SceneObject[], transform: Matrix4, container: SceneObject): SceneObject[];
4
+ export declare function cloneWithTransform(objects: SceneObject[], transform: Matrix4 | LazyMatrix, container: SceneObject): SceneObject[];
@@ -17,7 +17,13 @@ export type SceneParserContext = {
17
17
  getActiveSketch(): Sketch | null;
18
18
  };
19
19
  export declare function registerBuilder<T extends Function>(builder: (context: SceneParserContext) => T): T;
20
- export declare function init(rootPath?: string): Promise<{
20
+ export interface FluidCADOptions {
21
+ mesh?: {
22
+ lineDeflection?: number;
23
+ angularDeflection?: number;
24
+ };
25
+ }
26
+ export declare function init(options?: FluidCADOptions): Promise<{
21
27
  currentScene: Scene;
22
28
  currentFile: string;
23
29
  renderer: import("./rendering/render.js").SceneRenderer;
package/lib/dist/index.js CHANGED
@@ -88,8 +88,8 @@ export function registerBuilder(builder) {
88
88
  return fn;
89
89
  ;
90
90
  }
91
- export async function init(rootPath) {
91
+ export async function init(options) {
92
92
  await loadOC();
93
- const resolvedPath = rootPath || process.env.FLUIDCAD_WORKSPACE_PATH || '';
94
- return createManager(resolvedPath);
93
+ const resolvedPath = process.env.FLUIDCAD_WORKSPACE_PATH || '';
94
+ return createManager(resolvedPath, options);
95
95
  }
@@ -0,0 +1,31 @@
1
+ import { Matrix4 } from "./matrix4.js";
2
+ import { Axis } from "./axis.js";
3
+ import { Plane } from "./plane.js";
4
+ /** Anything that can be resolved to an `Axis` once built — e.g. `AxisObjectBase`. */
5
+ export interface AxisLazySource {
6
+ getAxis(): Axis;
7
+ }
8
+ /** Anything that can be resolved to a `Plane` once built — e.g. `PlaneObjectBase`. */
9
+ export interface PlaneLazySource {
10
+ getPlane(): Plane;
11
+ }
12
+ /**
13
+ * Memoized thunk over a Matrix4. Lets parse-time code thread a transform
14
+ * value that depends on scene state (e.g. an AxisObjectBase or
15
+ * PlaneObjectBase) before that state exists. Resolution is deferred to the
16
+ * first call to `resolve()`, by which point the renderer has built the source
17
+ * object. Concrete `Axis` / `Plane` sources resolve eagerly with no extra
18
+ * indirection.
19
+ */
20
+ export declare class LazyMatrix {
21
+ private _resolver;
22
+ private _cached;
23
+ private constructor();
24
+ resolve(): Matrix4;
25
+ equals(other: LazyMatrix, tolerance?: number): boolean;
26
+ static of(matrix: Matrix4): LazyMatrix;
27
+ static from(resolver: () => Matrix4): LazyMatrix;
28
+ static mirror(plane: Plane | PlaneLazySource): LazyMatrix;
29
+ static rotation(axis: Axis | AxisLazySource, angle: number): LazyMatrix;
30
+ static translation(axis: Axis | AxisLazySource, distance: number): LazyMatrix;
31
+ }
@@ -0,0 +1,66 @@
1
+ import { Matrix4 } from "./matrix4.js";
2
+ function isAxisLazySource(a) {
3
+ return typeof a.getAxis === "function";
4
+ }
5
+ function isPlaneLazySource(p) {
6
+ return typeof p.getPlane === "function";
7
+ }
8
+ /**
9
+ * Memoized thunk over a Matrix4. Lets parse-time code thread a transform
10
+ * value that depends on scene state (e.g. an AxisObjectBase or
11
+ * PlaneObjectBase) before that state exists. Resolution is deferred to the
12
+ * first call to `resolve()`, by which point the renderer has built the source
13
+ * object. Concrete `Axis` / `Plane` sources resolve eagerly with no extra
14
+ * indirection.
15
+ */
16
+ export class LazyMatrix {
17
+ _resolver;
18
+ _cached;
19
+ constructor(resolver, cached = null) {
20
+ this._resolver = resolver;
21
+ this._cached = cached;
22
+ }
23
+ resolve() {
24
+ if (this._cached === null) {
25
+ this._cached = this._resolver();
26
+ }
27
+ return this._cached;
28
+ }
29
+ equals(other, tolerance = 0) {
30
+ return this.resolve().equals(other.resolve(), tolerance);
31
+ }
32
+ static of(matrix) {
33
+ return new LazyMatrix(() => matrix, matrix);
34
+ }
35
+ static from(resolver) {
36
+ return new LazyMatrix(resolver);
37
+ }
38
+ static mirror(plane) {
39
+ if (isPlaneLazySource(plane)) {
40
+ return new LazyMatrix(() => {
41
+ const p = plane.getPlane();
42
+ return Matrix4.mirrorPlane(p.normal, p.origin);
43
+ });
44
+ }
45
+ return LazyMatrix.of(Matrix4.mirrorPlane(plane.normal, plane.origin));
46
+ }
47
+ static rotation(axis, angle) {
48
+ if (isAxisLazySource(axis)) {
49
+ return new LazyMatrix(() => {
50
+ const a = axis.getAxis();
51
+ return Matrix4.fromRotationAroundAxis(a.origin, a.direction, angle);
52
+ });
53
+ }
54
+ return LazyMatrix.of(Matrix4.fromRotationAroundAxis(axis.origin, axis.direction, angle));
55
+ }
56
+ static translation(axis, distance) {
57
+ if (isAxisLazySource(axis)) {
58
+ return new LazyMatrix(() => {
59
+ const dir = axis.getAxis().direction;
60
+ return Matrix4.fromTranslation(dir.x * distance, dir.y * distance, dir.z * distance);
61
+ });
62
+ }
63
+ const dir = axis.direction;
64
+ return LazyMatrix.of(Matrix4.fromTranslation(dir.x * distance, dir.y * distance, dir.z * distance));
65
+ }
66
+ }
@@ -17,6 +17,11 @@ export declare class ConstraintSolverAdaptor extends ConstraintSolver {
17
17
  edges: Edge[];
18
18
  endTangent: Point2D | null;
19
19
  };
20
+ getTangentArcFromPointTangent(plane: Plane, startPoint: Point2D, startTangent: Point2D, target: QualifiedShape, flip: boolean): {
21
+ edges: Edge[];
22
+ endTangent: Point2D | null;
23
+ };
20
24
  isCurve(shape: Shape): boolean;
25
+ private isLine;
21
26
  private getShapeGeometry;
22
27
  }