fluidcad 0.0.13 → 0.0.15

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 (68) hide show
  1. package/lib/dist/common/scene-object.d.ts +3 -0
  2. package/lib/dist/common/scene-object.js +7 -0
  3. package/lib/dist/core/2d/arc.d.ts +14 -56
  4. package/lib/dist/core/2d/arc.js +8 -23
  5. package/lib/dist/core/2d/center.d.ts +9 -0
  6. package/lib/dist/core/2d/center.js +10 -0
  7. package/lib/dist/core/2d/index.d.ts +2 -0
  8. package/lib/dist/core/2d/index.js +2 -0
  9. package/lib/dist/core/2d/intersect.d.ts +17 -0
  10. package/lib/dist/core/2d/intersect.js +20 -0
  11. package/lib/dist/core/interfaces.d.ts +50 -2
  12. package/lib/dist/core/repeat.js +10 -3
  13. package/lib/dist/features/2d/arc.d.ts +27 -14
  14. package/lib/dist/features/2d/arc.js +269 -38
  15. package/lib/dist/features/2d/intersect.d.ts +15 -0
  16. package/lib/dist/features/2d/intersect.js +83 -0
  17. package/lib/dist/features/2d/plane-center.d.ts +13 -0
  18. package/lib/dist/features/2d/plane-center.js +40 -0
  19. package/lib/dist/features/2d/projection.js +3 -4
  20. package/lib/dist/features/2d/rect.d.ts +2 -2
  21. package/lib/dist/features/2d/rect.js +3 -3
  22. package/lib/dist/features/2d/sketch.d.ts +2 -2
  23. package/lib/dist/features/2d/sketch.js +13 -1
  24. package/lib/dist/features/2d/slot.d.ts +2 -2
  25. package/lib/dist/features/2d/slot.js +3 -3
  26. package/lib/dist/features/extrude-base.d.ts +4 -0
  27. package/lib/dist/features/extrude-base.js +27 -0
  28. package/lib/dist/features/extrude-to-face.d.ts +1 -0
  29. package/lib/dist/features/extrude-to-face.js +5 -1
  30. package/lib/dist/features/extrude-two-distances.d.ts +1 -0
  31. package/lib/dist/features/extrude-two-distances.js +5 -2
  32. package/lib/dist/features/extrude.d.ts +1 -0
  33. package/lib/dist/features/extrude.js +5 -1
  34. package/lib/dist/features/plane-renderable-base.d.ts +2 -1
  35. package/lib/dist/features/plane-renderable-base.js +1 -1
  36. package/lib/dist/features/plane.d.ts +1 -1
  37. package/lib/dist/filters/face/face-filter.d.ts +10 -0
  38. package/lib/dist/filters/face/face-filter.js +39 -0
  39. package/lib/dist/filters/face/intersects-with.d.ts +18 -0
  40. package/lib/dist/filters/face/intersects-with.js +41 -0
  41. package/lib/dist/helpers/clone-transform.js +1 -0
  42. package/lib/dist/oc/boolean-ops.js +0 -2
  43. package/lib/dist/oc/face-query.d.ts +1 -0
  44. package/lib/dist/oc/face-query.js +15 -0
  45. package/lib/dist/oc/index.d.ts +1 -0
  46. package/lib/dist/oc/index.js +1 -0
  47. package/lib/dist/oc/section-ops.d.ts +6 -0
  48. package/lib/dist/oc/section-ops.js +26 -0
  49. package/lib/dist/oc/thin-face-maker.d.ts +29 -0
  50. package/lib/dist/oc/thin-face-maker.js +163 -0
  51. package/lib/dist/rendering/render.js +16 -0
  52. package/lib/dist/tests/features/2d/arc.test.js +2 -2
  53. package/lib/dist/tests/features/2d/intersect.test.d.ts +1 -0
  54. package/lib/dist/tests/features/2d/intersect.test.js +22 -0
  55. package/lib/dist/tests/features/2d/rect.test.js +1 -1
  56. package/lib/dist/tests/features/loft.test.js +1 -1
  57. package/lib/dist/tests/features/select.test.js +49 -1
  58. package/lib/dist/tests/features/thin-extrude.test.d.ts +1 -0
  59. package/lib/dist/tests/features/thin-extrude.test.js +137 -0
  60. package/lib/dist/tsconfig.tsbuildinfo +1 -1
  61. package/package.json +3 -3
  62. package/server/dist/index.js +23 -15
  63. package/ui/dist/assets/{index-mLcpjEcV.js → index-BJG141m7.js} +2 -2
  64. package/ui/dist/index.html +1 -1
  65. package/lib/dist/features/2d/arc-three-points.d.ts +0 -19
  66. package/lib/dist/features/2d/arc-three-points.js +0 -75
  67. package/lib/dist/features/2d/arc-to-point.d.ts +0 -17
  68. package/lib/dist/features/2d/arc-to-point.js +0 -95
@@ -3,35 +3,233 @@ import { Geometry } from "../../oc/geometry.js";
3
3
  import { rad } from "../../helpers/math-helpers.js";
4
4
  import { Point2D } from "../../math/point.js";
5
5
  import { GeometrySceneObject } from "./geometry.js";
6
- export class ArcFromTwoAngles extends GeometrySceneObject {
7
- radius;
8
- startAngle;
9
- endAngle;
10
- centered;
11
- targetPlane;
12
- constructor(radius, startAngle, endAngle, centered = false, targetPlane = null) {
6
+ import { normalizePoint2D } from "../../helpers/normalize.js";
7
+ export class Arc extends GeometrySceneObject {
8
+ // Two-point mode state (set by factory)
9
+ _startPoint = null;
10
+ _endPoint = null;
11
+ // Angle mode state (set by factory)
12
+ _arcRadius = 0;
13
+ _startAngle = 0;
14
+ _endAngle = 180;
15
+ // Chainable state
16
+ _bulgeRadius = 0;
17
+ _centerPoint = null;
18
+ _centered = false;
19
+ _targetPlane;
20
+ constructor(targetPlane = null) {
13
21
  super();
14
- this.radius = radius;
15
- this.startAngle = startAngle;
16
- this.endAngle = endAngle;
17
- this.centered = centered;
18
- this.targetPlane = targetPlane;
22
+ this._targetPlane = targetPlane;
23
+ }
24
+ static toPoint(endPoint, targetPlane = null) {
25
+ const arc = new Arc(targetPlane);
26
+ arc._endPoint = endPoint;
27
+ return arc;
28
+ }
29
+ static twoPoints(startPoint, endPoint, targetPlane = null) {
30
+ const arc = new Arc(targetPlane);
31
+ arc._startPoint = startPoint;
32
+ arc._endPoint = endPoint;
33
+ return arc;
34
+ }
35
+ static fromAngles(arcRadius, startAngle, endAngle, targetPlane = null) {
36
+ const arc = new Arc(targetPlane);
37
+ arc._arcRadius = arcRadius;
38
+ arc._startAngle = startAngle;
39
+ arc._endAngle = endAngle;
40
+ return arc;
41
+ }
42
+ // Chainable methods (IArc)
43
+ radius(value) {
44
+ this._bulgeRadius = value;
45
+ return this;
46
+ }
47
+ center(value) {
48
+ this._centerPoint = normalizePoint2D(value);
49
+ return this;
50
+ }
51
+ centered() {
52
+ this._centered = true;
53
+ return this;
19
54
  }
20
55
  build() {
21
- const plane = this.targetPlane?.getPlane() || this.sketch.getPlane();
22
- const radius = this.radius;
23
- // Current position (or plane center) is the center of the arc
24
- const centerPoint = this.targetPlane
25
- ? plane.worldToLocal(this.targetPlane.getPlaneCenter())
56
+ if (this._startPoint && this._endPoint) {
57
+ // Two explicit points: default center = current position
58
+ if (this._bulgeRadius !== 0) {
59
+ this.buildTwoPointsBulge();
60
+ }
61
+ else {
62
+ this.buildTwoPointsCenter();
63
+ }
64
+ }
65
+ else if (this._endPoint) {
66
+ // From current position to endpoint
67
+ if (this._centerPoint) {
68
+ this.buildWithCenter();
69
+ }
70
+ else {
71
+ this.buildToPoint();
72
+ }
73
+ }
74
+ else {
75
+ this.buildFromAngles();
76
+ }
77
+ }
78
+ buildTwoPointsCenter() {
79
+ const plane = this._targetPlane?.getPlane() || this.sketch.getPlane();
80
+ const startPt = this._startPoint.asPoint2D();
81
+ const endPt = this._endPoint.asPoint2D();
82
+ const centerPt = this._centerPoint
83
+ ? this._centerPoint.asPoint2D()
26
84
  : this.getCurrentPosition();
27
- // Negative angles indicate a clockwise arc
28
- const cw = this.endAngle < 0;
29
- const absStartAngle = Math.abs(this.startAngle);
30
- const absEndAngle = Math.abs(this.endAngle);
85
+ const dx = startPt.x - centerPt.x;
86
+ const dy = startPt.y - centerPt.y;
87
+ const radius = Math.sqrt(dx * dx + dy * dy);
88
+ const endAngle = Math.atan2(endPt.y - centerPt.y, endPt.x - centerPt.x);
89
+ const center = plane.localToWorld(centerPt);
90
+ const start = plane.localToWorld(startPt);
91
+ const end = plane.localToWorld(endPt);
92
+ const arc = Geometry.makeArc(center, radius, plane.normal, start, end);
93
+ const edge = Geometry.makeEdgeFromCurve(arc);
94
+ const tx = -Math.sin(endAngle);
95
+ const ty = Math.cos(endAngle);
96
+ this.setTangent(new Point2D(tx, ty));
97
+ this.setState('start', Vertex.fromPoint2D(startPt));
98
+ this.setState('end', Vertex.fromPoint2D(endPt));
99
+ this.addShape(edge);
100
+ if (this.sketch) {
101
+ this.setCurrentPosition(endPt);
102
+ }
103
+ if (this._targetPlane) {
104
+ this._targetPlane.removeShapes(this);
105
+ }
106
+ }
107
+ buildTwoPointsBulge() {
108
+ const plane = this._targetPlane?.getPlane() || this.sketch.getPlane();
109
+ const startPoint = this._startPoint.asPoint2D();
110
+ const targetPoint = this._endPoint.asPoint2D();
111
+ const dx = targetPoint.x - startPoint.x;
112
+ const dy = targetPoint.y - startPoint.y;
113
+ const chordLen = Math.sqrt(dx * dx + dy * dy);
114
+ let r = this._bulgeRadius;
115
+ const cw = r < 0;
116
+ r = Math.abs(r);
117
+ if (r < chordLen / 2) {
118
+ r = chordLen / 2;
119
+ }
120
+ const mx = (startPoint.x + targetPoint.x) / 2;
121
+ const my = (startPoint.y + targetPoint.y) / 2;
122
+ const px = -dy / chordLen;
123
+ const py = dx / chordLen;
124
+ const d = Math.sqrt(r * r - (chordLen / 2) * (chordLen / 2));
125
+ const sign = cw ? -1 : 1;
126
+ const centerPoint = new Point2D(mx + sign * d * px, my + sign * d * py);
127
+ const endAngle = Math.atan2(targetPoint.y - centerPoint.y, targetPoint.x - centerPoint.x);
128
+ const normal = cw ? plane.normal.negate() : plane.normal;
129
+ const center = plane.localToWorld(centerPoint);
130
+ const start = plane.localToWorld(startPoint);
131
+ const end = plane.localToWorld(targetPoint);
132
+ const arc = Geometry.makeArc(center, r, normal, start, end);
133
+ const edge = Geometry.makeEdgeFromCurve(arc);
134
+ const signT = cw ? -1 : 1;
135
+ const endTx = signT * (-Math.sin(endAngle));
136
+ const endTy = signT * Math.cos(endAngle);
137
+ this.setTangent(new Point2D(endTx, endTy));
138
+ this.setState('start', Vertex.fromPoint2D(startPoint));
139
+ this.setState('end', Vertex.fromPoint2D(targetPoint));
140
+ this.addShape(edge);
141
+ if (this.sketch) {
142
+ this.setCurrentPosition(targetPoint);
143
+ }
144
+ if (this._targetPlane) {
145
+ this._targetPlane.removeShapes(this);
146
+ }
147
+ }
148
+ buildToPoint() {
149
+ const plane = this._targetPlane?.getPlane() || this.sketch.getPlane();
150
+ const targetPoint = this._endPoint.asPoint2D();
151
+ const startPoint = this._targetPlane
152
+ ? plane.worldToLocal(this._targetPlane.getPlaneCenter())
153
+ : this.getCurrentPosition();
154
+ const dx = targetPoint.x - startPoint.x;
155
+ const dy = targetPoint.y - startPoint.y;
156
+ const chordLen = Math.sqrt(dx * dx + dy * dy);
157
+ let r = this._bulgeRadius || (chordLen / 2);
158
+ const cw = r < 0;
159
+ r = Math.abs(r);
160
+ if (r < chordLen / 2) {
161
+ r = chordLen / 2;
162
+ }
163
+ const mx = (startPoint.x + targetPoint.x) / 2;
164
+ const my = (startPoint.y + targetPoint.y) / 2;
165
+ const px = -dy / chordLen;
166
+ const py = dx / chordLen;
167
+ const d = Math.sqrt(r * r - (chordLen / 2) * (chordLen / 2));
168
+ const sign = cw ? -1 : 1;
169
+ const centerPoint = new Point2D(mx + sign * d * px, my + sign * d * py);
170
+ const startAngle = Math.atan2(startPoint.y - centerPoint.y, startPoint.x - centerPoint.x);
171
+ const endAngle = Math.atan2(targetPoint.y - centerPoint.y, targetPoint.x - centerPoint.x);
172
+ const normal = cw ? plane.normal.negate() : plane.normal;
173
+ const center = plane.localToWorld(centerPoint);
174
+ const start = plane.localToWorld(startPoint);
175
+ const end = plane.localToWorld(targetPoint);
176
+ const arc = Geometry.makeArc(center, r, normal, start, end);
177
+ const edge = Geometry.makeEdgeFromCurve(arc);
178
+ const signT = cw ? -1 : 1;
179
+ const endTx = signT * (-Math.sin(endAngle));
180
+ const endTy = signT * Math.cos(endAngle);
181
+ this.setTangent(new Point2D(endTx, endTy));
182
+ this.setState('start', Vertex.fromPoint2D(startPoint));
183
+ this.setState('end', Vertex.fromPoint2D(targetPoint));
184
+ this.addShape(edge);
185
+ if (this.sketch) {
186
+ this.setCurrentPosition(targetPoint);
187
+ }
188
+ if (this._targetPlane) {
189
+ this._targetPlane.removeShapes(this);
190
+ }
191
+ }
192
+ buildWithCenter() {
193
+ const plane = this._targetPlane?.getPlane() || this.sketch.getPlane();
194
+ const startPt = this._targetPlane
195
+ ? plane.worldToLocal(this._targetPlane.getPlaneCenter())
196
+ : this.getCurrentPosition();
197
+ const endPt = this._endPoint.asPoint2D();
198
+ const centerPt = this._centerPoint.asPoint2D();
199
+ const dx = startPt.x - centerPt.x;
200
+ const dy = startPt.y - centerPt.y;
201
+ const radius = Math.sqrt(dx * dx + dy * dy);
202
+ const endAngle = Math.atan2(endPt.y - centerPt.y, endPt.x - centerPt.x);
203
+ const center = plane.localToWorld(centerPt);
204
+ const start = plane.localToWorld(startPt);
205
+ const end = plane.localToWorld(endPt);
206
+ const arc = Geometry.makeArc(center, radius, plane.normal, start, end);
207
+ const edge = Geometry.makeEdgeFromCurve(arc);
208
+ const tx = -Math.sin(endAngle);
209
+ const ty = Math.cos(endAngle);
210
+ this.setTangent(new Point2D(tx, ty));
211
+ this.setState('start', Vertex.fromPoint2D(startPt));
212
+ this.setState('end', Vertex.fromPoint2D(endPt));
213
+ this.addShape(edge);
214
+ if (this.sketch) {
215
+ this.setCurrentPosition(endPt);
216
+ }
217
+ if (this._targetPlane) {
218
+ this._targetPlane.removeShapes(this);
219
+ }
220
+ }
221
+ buildFromAngles() {
222
+ const plane = this._targetPlane?.getPlane() || this.sketch.getPlane();
223
+ const radius = this._arcRadius;
224
+ const centerPoint = this._targetPlane
225
+ ? plane.worldToLocal(this._targetPlane.getPlaneCenter())
226
+ : this.getCurrentPosition();
227
+ const cw = this._endAngle < 0;
228
+ const absStartAngle = Math.abs(this._startAngle);
229
+ const absEndAngle = Math.abs(this._endAngle);
31
230
  let startAngleRad;
32
231
  let endAngleRad;
33
- if (this.centered) {
34
- // Centered: the sweep is split equally around startAngle
232
+ if (this._centered) {
35
233
  const halfSweep = rad(absEndAngle) / 2;
36
234
  const midAngle = rad(absStartAngle);
37
235
  startAngleRad = midAngle - halfSweep;
@@ -51,44 +249,77 @@ export class ArcFromTwoAngles extends GeometrySceneObject {
51
249
  const edge = Geometry.makeEdgeFromCurve(arc);
52
250
  this.setState('start', Vertex.fromPoint2D(startPoint));
53
251
  this.setState('end', Vertex.fromPoint2D(endPoint));
54
- // Tangent at end point: CCW: (-sin θ, cos θ), CW: (sin θ, -cos θ)
55
252
  const sign = cw ? -1 : 1;
56
253
  const tx = sign * (-Math.sin(endAngleRad));
57
254
  const ty = sign * Math.cos(endAngleRad);
58
255
  this.setTangent(new Point2D(tx, ty));
59
256
  this.addShape(edge);
60
- // Current position should NOT change — the center remains the current position
61
- if (this.targetPlane) {
62
- this.targetPlane.removeShapes(this);
257
+ if (this._targetPlane) {
258
+ this._targetPlane.removeShapes(this);
63
259
  }
64
260
  }
65
261
  getType() {
66
262
  return 'arc';
67
263
  }
68
264
  compareTo(other) {
69
- if (!(other instanceof ArcFromTwoAngles)) {
265
+ if (!(other instanceof Arc)) {
70
266
  return false;
71
267
  }
72
268
  if (!super.compareTo(other)) {
73
269
  return false;
74
270
  }
75
- if (this.targetPlane?.constructor !== other.targetPlane?.constructor) {
271
+ if (this._targetPlane?.constructor !== other._targetPlane?.constructor) {
76
272
  return false;
77
273
  }
78
- if (this.targetPlane && other.targetPlane && !this.targetPlane.compareTo(other.targetPlane)) {
274
+ if (this._targetPlane && other._targetPlane && !this._targetPlane.compareTo(other._targetPlane)) {
79
275
  return false;
80
276
  }
81
- return this.radius === other.radius &&
82
- this.startAngle === other.startAngle &&
83
- this.endAngle === other.endAngle &&
84
- this.centered === other.centered;
277
+ if (this._endPoint && other._endPoint) {
278
+ if (!this._endPoint.compareTo(other._endPoint)) {
279
+ return false;
280
+ }
281
+ if (this._startPoint && other._startPoint) {
282
+ if (!this._startPoint.compareTo(other._startPoint)) {
283
+ return false;
284
+ }
285
+ }
286
+ else if (this._startPoint !== other._startPoint) {
287
+ return false;
288
+ }
289
+ if (this._centerPoint && other._centerPoint) {
290
+ return this._centerPoint.compareTo(other._centerPoint);
291
+ }
292
+ return this._bulgeRadius === other._bulgeRadius;
293
+ }
294
+ if (!this._endPoint && !other._endPoint) {
295
+ return this._arcRadius === other._arcRadius &&
296
+ this._startAngle === other._startAngle &&
297
+ this._endAngle === other._endAngle &&
298
+ this._centered === other._centered;
299
+ }
300
+ return false;
85
301
  }
86
302
  serialize() {
303
+ if (this._endPoint) {
304
+ const base = {
305
+ endPoint: this._endPoint.serialize(),
306
+ };
307
+ if (this._startPoint) {
308
+ base.startPoint = this._startPoint.serialize();
309
+ }
310
+ if (this._centerPoint) {
311
+ base.center = this._centerPoint.serialize();
312
+ }
313
+ if (this._bulgeRadius !== 0) {
314
+ base.radius = this._bulgeRadius;
315
+ }
316
+ return base;
317
+ }
87
318
  return {
88
- radius: this.radius,
89
- startAngle: this.startAngle,
90
- endAngle: this.endAngle,
91
- centered: this.centered,
319
+ radius: this._arcRadius,
320
+ startAngle: this._startAngle,
321
+ endAngle: this._endAngle,
322
+ centered: this._centered
92
323
  };
93
324
  }
94
325
  }
@@ -0,0 +1,15 @@
1
+ import { BuildSceneObjectContext, SceneObject } from "../../common/scene-object.js";
2
+ import { PlaneObjectBase } from "../plane-renderable-base.js";
3
+ import { ExtrudableGeometryBase } from "./extrudable-base.js";
4
+ export declare class Intersect extends ExtrudableGeometryBase {
5
+ private sourceObjects;
6
+ constructor(sourceObjects: SceneObject[], targetPlane?: PlaneObjectBase);
7
+ build(context?: BuildSceneObjectContext): void;
8
+ getDependencies(): SceneObject[];
9
+ createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
10
+ compareTo(other: Intersect): boolean;
11
+ getType(): string;
12
+ serialize(): {
13
+ objectIds: string[];
14
+ };
15
+ }
@@ -0,0 +1,83 @@
1
+ import { Vertex } from "../../common/vertex.js";
2
+ import { SectionOps } from "../../oc/section-ops.js";
3
+ import { ExtrudableGeometryBase } from "./extrudable-base.js";
4
+ export class Intersect extends ExtrudableGeometryBase {
5
+ sourceObjects;
6
+ constructor(sourceObjects, targetPlane = null) {
7
+ super(targetPlane);
8
+ this.sourceObjects = sourceObjects;
9
+ }
10
+ build(context) {
11
+ const plane = this.targetPlane?.getPlane() || this.sketch.getPlane();
12
+ const shapes = this.sourceObjects.flatMap(obj => obj.getShapes());
13
+ const transform = context?.getTransform() ?? null;
14
+ let lastEdge = null;
15
+ for (let shape of shapes) {
16
+ const edges = SectionOps.sectionShapeWithPlane(plane, shape);
17
+ for (const edge of edges) {
18
+ lastEdge = edge;
19
+ }
20
+ this.addShapes(edges);
21
+ }
22
+ if (lastEdge) {
23
+ const localStart = plane.worldToLocal(lastEdge.getFirstVertex().toPoint());
24
+ const localEnd = plane.worldToLocal(lastEdge.getLastVertex().toPoint());
25
+ this.setState('start', Vertex.fromPoint2D(localStart));
26
+ this.setState('end', Vertex.fromPoint2D(localEnd));
27
+ }
28
+ for (const obj of this.sourceObjects) {
29
+ obj.removeShapes(this);
30
+ }
31
+ if (this.targetPlane) {
32
+ this.targetPlane.removeShapes(this);
33
+ }
34
+ if (this.sketch) {
35
+ this.setCurrentPosition(this.getCurrentPosition());
36
+ }
37
+ }
38
+ getDependencies() {
39
+ const deps = [...this.sourceObjects];
40
+ if (this.targetPlane) {
41
+ deps.push(this.targetPlane);
42
+ }
43
+ return deps;
44
+ }
45
+ createCopy(remap) {
46
+ const objects = this.sourceObjects.map(obj => remap.get(obj) || obj);
47
+ const targetPlane = this.targetPlane ? (remap.get(this.targetPlane) || this.targetPlane) : null;
48
+ return new Intersect(objects, targetPlane);
49
+ }
50
+ compareTo(other) {
51
+ if (!(other instanceof Intersect)) {
52
+ return false;
53
+ }
54
+ if (!super.compareTo(other)) {
55
+ return false;
56
+ }
57
+ if (this.targetPlane?.constructor !== other.targetPlane?.constructor) {
58
+ return false;
59
+ }
60
+ if (this.targetPlane && other.targetPlane && !this.targetPlane.compareTo(other.targetPlane)) {
61
+ return false;
62
+ }
63
+ const thisObjects = this.sourceObjects || [];
64
+ const otherObjects = other.sourceObjects || [];
65
+ if (thisObjects.length !== otherObjects.length) {
66
+ return false;
67
+ }
68
+ for (let i = 0; i < thisObjects.length; i++) {
69
+ if (!thisObjects[i].compareTo(otherObjects[i])) {
70
+ return false;
71
+ }
72
+ }
73
+ return true;
74
+ }
75
+ getType() {
76
+ return 'intersect';
77
+ }
78
+ serialize() {
79
+ return {
80
+ objectIds: this.sourceObjects.map(o => o.id)
81
+ };
82
+ }
83
+ }
@@ -0,0 +1,13 @@
1
+ import { SceneObject } from "../../common/scene-object.js";
2
+ import { GeometrySceneObject } from "./geometry.js";
3
+ import { LazyVertex } from "../lazy-vertex.js";
4
+ export declare class PlaneCenter extends GeometrySceneObject {
5
+ constructor();
6
+ getType(): string;
7
+ build(): void;
8
+ center(): LazyVertex;
9
+ getDependencies(): SceneObject[];
10
+ createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
11
+ compareTo(other: this): boolean;
12
+ serialize(): {};
13
+ }
@@ -0,0 +1,40 @@
1
+ import { GeometrySceneObject } from "./geometry.js";
2
+ import { LazyVertex } from "../lazy-vertex.js";
3
+ export class PlaneCenter extends GeometrySceneObject {
4
+ constructor() {
5
+ super();
6
+ }
7
+ getType() {
8
+ return 'plane-center';
9
+ }
10
+ build() {
11
+ const plane = this.sketch.getPlane();
12
+ const centerPoint = this.sketch.planeObj.getPlaneCenter();
13
+ const local = plane.worldToLocal(centerPoint);
14
+ this.setCurrentPosition(local);
15
+ }
16
+ center() {
17
+ return new LazyVertex(this.generateUniqueName('center'), () => {
18
+ const vertex = this.getState('center-vertex');
19
+ if (vertex) {
20
+ return [vertex];
21
+ }
22
+ return [];
23
+ });
24
+ }
25
+ getDependencies() {
26
+ return [];
27
+ }
28
+ createCopy(remap) {
29
+ return new PlaneCenter();
30
+ }
31
+ compareTo(other) {
32
+ if (!(other instanceof PlaneCenter)) {
33
+ return false;
34
+ }
35
+ return super.compareTo(other);
36
+ }
37
+ serialize() {
38
+ return {};
39
+ }
40
+ }
@@ -1,5 +1,4 @@
1
1
  import { Face } from "../../common/face.js";
2
- import { ShapeOps } from "../../oc/shape-ops.js";
3
2
  import { Edge } from "../../common/edge.js";
4
3
  import { Vertex } from "../../common/vertex.js";
5
4
  import { ProjectionOps } from "../../oc/intersection.js";
@@ -18,9 +17,9 @@ export class Projection extends ExtrudableGeometryBase {
18
17
  let lastWire = null;
19
18
  console.log('Projection: building with shapes:', shapes.length);
20
19
  for (let shape of shapes) {
21
- if (transform) {
22
- shape = ShapeOps.transform(shape, transform);
23
- }
20
+ // if (transform) {
21
+ // shape = ShapeOps.transform(shape, transform);
22
+ // }
24
23
  let wires = [];
25
24
  if (shape instanceof Face) {
26
25
  wires = ProjectionOps.projectFaceOntoPlane(plane, shape);
@@ -34,12 +34,12 @@ export declare class Rect extends ExtrudableGeometryBase implements IRect {
34
34
  bottomLeft(): LazyVertex;
35
35
  bottomRight(): LazyVertex;
36
36
  radius(...r: number[]): this;
37
- center(value?: CenteringOptions): this;
37
+ centered(value?: CenteringOptions): this;
38
38
  serialize(): {
39
39
  width: number;
40
40
  height: number;
41
41
  radius: number | number[];
42
- center: CenteringOptions;
42
+ centered: CenteringOptions;
43
43
  };
44
44
  }
45
45
  export {};
@@ -152,7 +152,7 @@ export class Rect extends ExtrudableGeometryBase {
152
152
  if (this._radius) {
153
153
  rect.radius(...(Array.isArray(this._radius) ? this._radius : [this._radius]));
154
154
  }
155
- rect.center(this._center);
155
+ rect.centered(this._center);
156
156
  return rect;
157
157
  }
158
158
  compareTo(other) {
@@ -250,7 +250,7 @@ export class Rect extends ExtrudableGeometryBase {
250
250
  }
251
251
  return this;
252
252
  }
253
- center(value = true) {
253
+ centered(value = true) {
254
254
  this._center = value;
255
255
  return this;
256
256
  }
@@ -259,7 +259,7 @@ export class Rect extends ExtrudableGeometryBase {
259
259
  width: this.width,
260
260
  height: this.height,
261
261
  radius: this._radius,
262
- center: this._center
262
+ centered: this._center
263
263
  };
264
264
  }
265
265
  }
@@ -2,7 +2,7 @@ import { Plane } from "../../math/plane.js";
2
2
  import { Point2D } from "../../math/point.js";
3
3
  import { GeometrySceneObject } from "./geometry.js";
4
4
  import { PlaneObjectBase } from "../plane-renderable-base.js";
5
- import { SceneObject } from "../../common/scene-object.js";
5
+ import { BuildSceneObjectContext, SceneObject } from "../../common/scene-object.js";
6
6
  import { Edge } from "../../common/edge.js";
7
7
  import { Extrudable } from "../../helpers/types.js";
8
8
  export declare class Sketch extends SceneObject implements Extrudable {
@@ -15,7 +15,7 @@ export declare class Sketch extends SceneObject implements Extrudable {
15
15
  getTangentAt(currentObj: GeometrySceneObject): Point2D | null;
16
16
  getPositionAt(currentObj: GeometrySceneObject): Point2D;
17
17
  getLastPosition(scope?: Set<SceneObject>): Point2D;
18
- build(): void;
18
+ build(context?: BuildSceneObjectContext): void;
19
19
  getEdges(): Edge[];
20
20
  getEdgesWithOwner(): Map<Edge, GeometrySceneObject>;
21
21
  getGeometriesWithOwner(): Map<Edge, GeometrySceneObject>;
@@ -3,6 +3,7 @@ import { GeometrySceneObject } from "./geometry.js";
3
3
  import { SceneObject } from "../../common/scene-object.js";
4
4
  import { Edge } from "../../common/edge.js";
5
5
  import { Wire } from "../../common/wire.js";
6
+ import { ShapeOps } from "../../oc/shape-ops.js";
6
7
  export class Sketch extends SceneObject {
7
8
  planeObj;
8
9
  constructor(planeObj) {
@@ -77,10 +78,21 @@ export class Sketch extends SceneObject {
77
78
  children.pop();
78
79
  }
79
80
  }
80
- build() {
81
+ build(context) {
81
82
  this.planeObj.removeShapes(this);
83
+ const source = this.getCloneSource();
84
+ const transform = context?.getTransform();
85
+ if (source instanceof Sketch && transform) {
86
+ const originalEdges = source.getEdges();
87
+ const transformedEdges = originalEdges.map(edge => ShapeOps.transform(edge, transform));
88
+ this.setState('cloned-edges', transformedEdges);
89
+ }
82
90
  }
83
91
  getEdges() {
92
+ const clonedEdges = this.getState('cloned-edges');
93
+ if (clonedEdges) {
94
+ return clonedEdges;
95
+ }
84
96
  return [...this.getEdgesWithOwner().keys()];
85
97
  }
86
98
  getEdgesWithOwner() {
@@ -8,7 +8,7 @@ export declare class Slot extends ExtrudableGeometryBase implements ISlot {
8
8
  private _center;
9
9
  private _angle;
10
10
  constructor(distance: number, radius: number, targetPlane?: PlaneObjectBase);
11
- center(value?: boolean): this;
11
+ centered(value?: boolean): this;
12
12
  rotate(angle: number): this;
13
13
  build(): void;
14
14
  getType(): string;
@@ -18,7 +18,7 @@ export declare class Slot extends ExtrudableGeometryBase implements ISlot {
18
18
  serialize(): {
19
19
  distance: number;
20
20
  radius: number;
21
- center: boolean;
21
+ centered: boolean;
22
22
  angle: number;
23
23
  };
24
24
  }
@@ -12,7 +12,7 @@ export class Slot extends ExtrudableGeometryBase {
12
12
  this.distance = distance;
13
13
  this.radius = radius;
14
14
  }
15
- center(value = true) {
15
+ centered(value = true) {
16
16
  this._center = value;
17
17
  return this;
18
18
  }
@@ -86,7 +86,7 @@ export class Slot extends ExtrudableGeometryBase {
86
86
  createCopy(remap) {
87
87
  const targetPlane = this.targetPlane ? (remap.get(this.targetPlane) || this.targetPlane) : null;
88
88
  const s = new Slot(this.distance, this.radius, targetPlane);
89
- s.center(this._center);
89
+ s.centered(this._center);
90
90
  s.rotate(this._angle);
91
91
  return s;
92
92
  }
@@ -112,7 +112,7 @@ export class Slot extends ExtrudableGeometryBase {
112
112
  return {
113
113
  distance: this.distance,
114
114
  radius: this.radius,
115
- center: this._center,
115
+ centered: this._center,
116
116
  angle: this._angle,
117
117
  };
118
118
  }