fluidcad 0.0.24 → 0.0.25

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 (48) hide show
  1. package/lib/dist/common/scene-object.d.ts +14 -0
  2. package/lib/dist/common/scene-object.js +129 -0
  3. package/lib/dist/core/2d/tarc.d.ts +2 -2
  4. package/lib/dist/core/chamfer.d.ts +5 -5
  5. package/lib/dist/core/color.d.ts +3 -3
  6. package/lib/dist/core/copy.js +5 -4
  7. package/lib/dist/core/cylinder.d.ts +2 -2
  8. package/lib/dist/core/fillet.d.ts +6 -6
  9. package/lib/dist/core/index.d.ts +2 -1
  10. package/lib/dist/core/index.js +1 -0
  11. package/lib/dist/core/interfaces.d.ts +68 -17
  12. package/lib/dist/core/load.d.ts +2 -2
  13. package/lib/dist/core/local.d.ts +12 -0
  14. package/lib/dist/core/local.js +18 -0
  15. package/lib/dist/core/mirror.d.ts +9 -9
  16. package/lib/dist/core/mirror.js +0 -3
  17. package/lib/dist/core/remove.d.ts +2 -2
  18. package/lib/dist/core/rotate.d.ts +5 -5
  19. package/lib/dist/core/sphere.d.ts +3 -3
  20. package/lib/dist/core/subtract.d.ts +2 -2
  21. package/lib/dist/core/translate.d.ts +9 -9
  22. package/lib/dist/features/2d/circle.js +2 -1
  23. package/lib/dist/features/2d/slot.d.ts +0 -3
  24. package/lib/dist/features/2d/slot.js +7 -28
  25. package/lib/dist/features/2d/tarc-with-tangent.js +4 -2
  26. package/lib/dist/features/2d/tarc.js +4 -2
  27. package/lib/dist/features/axis-from-edge.js +2 -2
  28. package/lib/dist/features/axis-from-sketch.d.ts +18 -0
  29. package/lib/dist/features/axis-from-sketch.js +58 -0
  30. package/lib/dist/features/copy-linear2d.d.ts +4 -2
  31. package/lib/dist/features/copy-linear2d.js +23 -9
  32. package/lib/dist/features/mirror-shape.js +10 -0
  33. package/lib/dist/features/select.d.ts +1 -1
  34. package/lib/dist/features/select.js +1 -2
  35. package/lib/dist/math/axis.d.ts +1 -0
  36. package/lib/dist/math/axis.js +4 -1
  37. package/lib/dist/math/index.d.ts +1 -1
  38. package/lib/dist/math/index.js +1 -1
  39. package/lib/dist/rendering/render.js +8 -0
  40. package/lib/dist/tests/features/mirror2d.test.js +34 -0
  41. package/lib/dist/tests/features/scene-object-chain.test.d.ts +1 -0
  42. package/lib/dist/tests/features/scene-object-chain.test.js +64 -0
  43. package/lib/dist/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +1 -1
  45. package/server/dist/code-editor.d.ts +3 -2
  46. package/server/dist/code-editor.js +244 -121
  47. package/ui/dist/assets/{index-CqP_mgZk.js → index-D2eOzshJ.js} +3 -3
  48. package/ui/dist/index.html +1 -1
@@ -3,6 +3,9 @@ import { Matrix4 } from "../math/matrix4.js";
3
3
  import { ISceneObject } from "../core/interfaces.js";
4
4
  import { FusionScope, OperationMode } from "../features/extrude-options.js";
5
5
  import { ShapeType } from "./shape-type.js";
6
+ import type { AxisLike } from "../math/axis.js";
7
+ import type { PlaneLike } from "../math/plane.js";
8
+ import type { PointLike } from "../math/point.js";
6
9
  export type SourceLocation = {
7
10
  filePath: string;
8
11
  line: number;
@@ -27,6 +30,7 @@ export declare abstract class SceneObject implements Comparable<SceneObject>, Se
27
30
  private _id;
28
31
  private _order;
29
32
  private _transform;
33
+ private _appliedTransform;
30
34
  private _cloneSource;
31
35
  private _parent;
32
36
  private _alwaysVisible;
@@ -56,6 +60,16 @@ export declare abstract class SceneObject implements Comparable<SceneObject>, Se
56
60
  abstract serialize(scope?: Set<SceneObject>): any;
57
61
  abstract getType(): string;
58
62
  abstract build(context?: BuildSceneObjectContext): void;
63
+ getAppliedTransform(): Matrix4 | null;
64
+ transform(matrix: Matrix4): this;
65
+ translate(x: number): this;
66
+ translate(x: number, y: number): this;
67
+ translate(x: number, y: number, z: number): this;
68
+ translate(p: PointLike): this;
69
+ rotate(angle: number): this;
70
+ rotate(axis: AxisLike, angle: number): this;
71
+ mirror(plane: PlaneLike): this;
72
+ mirror(axis: AxisLike): this;
59
73
  compareTo(other: SceneObject): boolean;
60
74
  getDependencies(): SceneObject[];
61
75
  createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
@@ -1,10 +1,15 @@
1
1
  import { randomUUID } from "crypto";
2
+ import { Matrix4 } from "../math/matrix4.js";
3
+ import { Point } from "../math/point.js";
4
+ import { Vector3d } from "../math/vector3d.js";
5
+ import { rad } from "../helpers/math-helpers.js";
2
6
  export class SceneObject {
3
7
  state;
4
8
  children = [];
5
9
  _id;
6
10
  _order = 0;
7
11
  _transform = null;
12
+ _appliedTransform = null;
8
13
  _cloneSource = null;
9
14
  _parent = null;
10
15
  _alwaysVisible = false;
@@ -89,6 +94,59 @@ export class SceneObject {
89
94
  getSnapshot() {
90
95
  return this.getState('snapshot') || [];
91
96
  }
97
+ getAppliedTransform() {
98
+ return this._appliedTransform;
99
+ }
100
+ transform(matrix) {
101
+ this._appliedTransform = this._appliedTransform
102
+ ? matrix.multiply(this._appliedTransform)
103
+ : matrix;
104
+ return this;
105
+ }
106
+ translate(a, b, c) {
107
+ let x, y, z;
108
+ if (typeof a === 'number') {
109
+ x = a;
110
+ y = b ?? 0;
111
+ z = c ?? 0;
112
+ }
113
+ else if (Array.isArray(a)) {
114
+ x = a[0] ?? 0;
115
+ y = a[1] ?? 0;
116
+ z = a[2] ?? 0;
117
+ }
118
+ else {
119
+ x = a.x;
120
+ y = a.y;
121
+ z = a.z;
122
+ }
123
+ return this.transform(Matrix4.fromTranslation(x, y, z));
124
+ }
125
+ rotate(a, b) {
126
+ let origin;
127
+ let direction;
128
+ let angleDeg;
129
+ if (typeof a === 'number') {
130
+ origin = new Point(0, 0, 0);
131
+ direction = Vector3d.unitZ();
132
+ angleDeg = a;
133
+ }
134
+ else {
135
+ const resolved = resolveAxisLike(a);
136
+ origin = resolved.origin;
137
+ direction = resolved.direction;
138
+ angleDeg = b;
139
+ }
140
+ return this.transform(Matrix4.fromRotationAroundAxis(origin, direction, rad(angleDeg)));
141
+ }
142
+ mirror(arg) {
143
+ if (isAxisLikeArg(arg)) {
144
+ const axis = resolveAxisLike(arg);
145
+ return this.transform(Matrix4.mirrorAxis(axis.origin, axis.direction));
146
+ }
147
+ const plane = resolvePlaneLike(arg);
148
+ return this.transform(Matrix4.mirrorPlane(plane.normal, plane.origin));
149
+ }
92
150
  compareTo(other) {
93
151
  const match = this._guide === other._guide && this._reusable === other._reusable;
94
152
  if (!match) {
@@ -100,6 +158,13 @@ export class SceneObject {
100
158
  if (this._symmetric !== other._symmetric) {
101
159
  return false;
102
160
  }
161
+ if (!this._appliedTransform !== !other._appliedTransform) {
162
+ return false;
163
+ }
164
+ if (this._appliedTransform && other._appliedTransform
165
+ && !this._appliedTransform.equals(other._appliedTransform)) {
166
+ return false;
167
+ }
103
168
  if (typeof (this._fusionScope) !== typeof (other._fusionScope)) {
104
169
  return false;
105
170
  }
@@ -148,6 +213,9 @@ export class SceneObject {
148
213
  const result = [];
149
214
  for (const obj of ordered) {
150
215
  const copy = obj.createCopy(remap);
216
+ if (obj._appliedTransform) {
217
+ copy._appliedTransform = obj._appliedTransform;
218
+ }
151
219
  remap.set(obj, copy);
152
220
  result.push(copy);
153
221
  const parent = obj.getParent();
@@ -395,3 +463,64 @@ export class SceneObject {
395
463
  return `${this.getOrder()}-${this.getUniqueType()}-${suffix}`;
396
464
  }
397
465
  }
466
+ function isAxisLikeArg(arg) {
467
+ if (arg === 'x' || arg === 'y' || arg === 'z') {
468
+ return true;
469
+ }
470
+ if (arg && typeof arg === 'object') {
471
+ if (typeof arg.getAxis === 'function') {
472
+ return true;
473
+ }
474
+ if (arg.origin && arg.direction) {
475
+ return true;
476
+ }
477
+ }
478
+ return false;
479
+ }
480
+ function resolveAxisLike(arg) {
481
+ if (arg === 'x') {
482
+ return { origin: new Point(0, 0, 0), direction: Vector3d.unitX() };
483
+ }
484
+ if (arg === 'y') {
485
+ return { origin: new Point(0, 0, 0), direction: Vector3d.unitY() };
486
+ }
487
+ if (arg === 'z') {
488
+ return { origin: new Point(0, 0, 0), direction: Vector3d.unitZ() };
489
+ }
490
+ const a = arg;
491
+ if (typeof a.getAxis === 'function') {
492
+ const axis = a.getAxis();
493
+ return { origin: axis.origin, direction: axis.direction };
494
+ }
495
+ return { origin: a.origin, direction: a.direction };
496
+ }
497
+ function resolvePlaneLike(arg) {
498
+ if (typeof arg === 'string') {
499
+ switch (arg) {
500
+ case 'xy':
501
+ case 'top':
502
+ return { origin: new Point(0, 0, 0), normal: Vector3d.unitZ() };
503
+ case '-xy':
504
+ case 'bottom':
505
+ return { origin: new Point(0, 0, 0), normal: Vector3d.unitZ().multiply(-1) };
506
+ case 'xz':
507
+ case 'front':
508
+ return { origin: new Point(0, 0, 0), normal: Vector3d.unitY().multiply(-1) };
509
+ case '-xz':
510
+ case 'back':
511
+ return { origin: new Point(0, 0, 0), normal: Vector3d.unitY() };
512
+ case 'yz':
513
+ case 'right':
514
+ return { origin: new Point(0, 0, 0), normal: Vector3d.unitX() };
515
+ case '-yz':
516
+ case 'left':
517
+ return { origin: new Point(0, 0, 0), normal: Vector3d.unitX().multiply(-1) };
518
+ }
519
+ }
520
+ const p = arg;
521
+ if (typeof p.getPlane === 'function') {
522
+ const plane = p.getPlane();
523
+ return { origin: plane.origin, normal: plane.normal };
524
+ }
525
+ return { origin: p.origin, normal: p.normal };
526
+ }
@@ -4,13 +4,13 @@ import { IGeometry, ISceneObject, ITangentArcTwoObjects } from "../interfaces.js
4
4
  interface TArcFunction {
5
5
  /**
6
6
  * Draws a tangent arc with a given radius and end angle.
7
- * @param radius - The arc radius (defaults to 100)
7
+ * @param radius - The arc radius (defaults to 100). A negative value flips the sweep direction.
8
8
  * @param endAngle - The sweep angle in degrees (defaults to 90)
9
9
  */
10
10
  (radius?: number, endAngle?: number): IGeometry;
11
11
  /**
12
12
  * Draws a tangent arc with a given radius, angle, and start tangent direction.
13
- * @param radius - The arc radius
13
+ * @param radius - The arc radius. A negative value flips the sweep direction.
14
14
  * @param angle - The sweep angle in degrees
15
15
  * @param tangent - The start tangent direction
16
16
  */
@@ -1,23 +1,23 @@
1
- import { ISceneObject } from "./interfaces.js";
1
+ import { ISceneObject, ITransformable } from "./interfaces.js";
2
2
  interface ChamferFunction {
3
3
  /**
4
4
  * Chamfers selected edges with the given distance.
5
5
  * @param distance - The chamfer distance (defaults to 1)
6
6
  */
7
- (distance?: number): ISceneObject;
7
+ (distance?: number): ITransformable;
8
8
  /**
9
9
  * Chamfers the given edge selections with the given distance.
10
10
  * @param distance - The chamfer distance
11
11
  * @param sceneObjects - The edge selections to chamfer
12
12
  */
13
- (distance: number, ...sceneObjects: ISceneObject[]): ISceneObject;
13
+ (distance: number, ...sceneObjects: ISceneObject[]): ITransformable;
14
14
  /**
15
15
  * Chamfers selected edges with two distances or a distance and angle.
16
16
  * @param distance - The first chamfer distance
17
17
  * @param distance2 - The second distance, or angle if `isAngle` is true
18
18
  * @param isAngle - Whether `distance2` is an angle
19
19
  */
20
- (distance: number, distance2: number, isAngle?: boolean): ISceneObject;
20
+ (distance: number, distance2: number, isAngle?: boolean): ITransformable;
21
21
  /**
22
22
  * Chamfers the given edge selections with two distances or a distance and angle.
23
23
  * @param distance - The first chamfer distance
@@ -25,7 +25,7 @@ interface ChamferFunction {
25
25
  * @param isAngle - Whether `distance2` is an angle
26
26
  * @param sceneObjects - The edge selections to chamfer
27
27
  */
28
- (distance: number, distance2: number, isAngle: boolean, ...sceneObjects: ISceneObject[]): ISceneObject;
28
+ (distance: number, distance2: number, isAngle: boolean, ...sceneObjects: ISceneObject[]): ITransformable;
29
29
  }
30
30
  declare const _default: ChamferFunction;
31
31
  export default _default;
@@ -1,16 +1,16 @@
1
- import { ISceneObject } from "./interfaces.js";
1
+ import { ISceneObject, ITransformable } from "./interfaces.js";
2
2
  interface ColorFunction {
3
3
  /**
4
4
  * Applies a color to the last selection.
5
5
  * @param color - The color value (CSS color string)
6
6
  */
7
- (color: string): ISceneObject;
7
+ (color: string): ITransformable;
8
8
  /**
9
9
  * Applies a color to the given selection.
10
10
  * @param color - The color value (CSS color string)
11
11
  * @param selection - The face or edge selection to color
12
12
  */
13
- (color: string, selection: ISceneObject): ISceneObject;
13
+ (color: string, selection: ISceneObject): ITransformable;
14
14
  }
15
15
  declare const _default: ColorFunction;
16
16
  export default _default;
@@ -4,6 +4,7 @@ import { CopyLinear } from "../features/copy-linear.js";
4
4
  import { CopyCircular } from "../features/copy-circular.js";
5
5
  import { CopyLinear2D } from "../features/copy-linear2d.js";
6
6
  import { CopyCircular2D } from "../features/copy-circular2d.js";
7
+ import { AxisObjectBase } from "../features/axis-renderable-base.js";
7
8
  function build(context) {
8
9
  return function copy() {
9
10
  const args = Array.from(arguments);
@@ -19,14 +20,14 @@ function build(context) {
19
20
  : null;
20
21
  if (type === 'linear') {
21
22
  const axisArg = args[1];
22
- const axes = Array.isArray(axisArg)
23
- ? axisArg.map(a => normalizeAxis(a))
24
- : [normalizeAxis(axisArg)];
23
+ const axisList = Array.isArray(axisArg) ? axisArg : [axisArg];
25
24
  if (activeSketch) {
26
- const copy = new CopyLinear2D(axes, options, restObjects.length > 0 ? restObjects : null);
25
+ const sketchAxes = axisList.map(a => a instanceof AxisObjectBase ? a : normalizeAxis(a));
26
+ const copy = new CopyLinear2D(sketchAxes, options, restObjects.length > 0 ? restObjects : null);
27
27
  context.addSceneObject(copy);
28
28
  return copy;
29
29
  }
30
+ const axes = axisList.map(a => normalizeAxis(a));
30
31
  const copy = new CopyLinear(axes, options, objects);
31
32
  context.addSceneObject(copy);
32
33
  return copy;
@@ -1,11 +1,11 @@
1
- import { ISceneObject } from "./interfaces.js";
1
+ import { ITransformable } from "./interfaces.js";
2
2
  interface CylinderFunction {
3
3
  /**
4
4
  * Creates a cylinder with the given radius and height.
5
5
  * @param radius - The cylinder radius
6
6
  * @param height - The cylinder height
7
7
  */
8
- (radius: number, height: number): ISceneObject;
8
+ (radius: number, height: number): ITransformable;
9
9
  }
10
10
  declare const _default: CylinderFunction;
11
11
  export default _default;
@@ -1,33 +1,33 @@
1
- import { IGeometry, ISceneObject } from "./interfaces.js";
1
+ import { IGeometry, ISceneObject, ITransformable } from "./interfaces.js";
2
2
  interface FilletFunction {
3
3
  /**
4
4
  * Fillets selected edges with the given radius.
5
5
  * @param radius - The fillet radius (defaults to 1)
6
6
  */
7
- (radius?: number): ISceneObject;
7
+ (radius?: number): ITransformable;
8
8
  /**
9
9
  * Fillets the given edge selections with the given radius.
10
10
  * @param radius - The fillet radius
11
11
  * @param sceneObjects - The edge selections to fillet
12
12
  */
13
- (radius: number, ...sceneObjects: ISceneObject[]): ISceneObject;
13
+ (radius: number, ...sceneObjects: ISceneObject[]): ITransformable;
14
14
  /**
15
15
  * [2D] Fillets corners between the given geometries.
16
16
  * @param objects - The geometries whose corners to fillet
17
17
  */
18
- (objects: IGeometry[]): ISceneObject;
18
+ (objects: IGeometry[]): ITransformable;
19
19
  /**
20
20
  * [2D] Fillets corners between the given geometries with a radius.
21
21
  * @param objects - The geometries whose corners to fillet
22
22
  * @param radius - The fillet radius
23
23
  */
24
- (objects: IGeometry[], radius: number): ISceneObject;
24
+ (objects: IGeometry[], radius: number): ITransformable;
25
25
  /**
26
26
  * [2D] Fillets corners at the given radius and geometries.
27
27
  * @param radius - The fillet radius
28
28
  * @param objects - The geometries whose corners to fillet
29
29
  */
30
- (radius: number, ...objects: IGeometry[]): ISceneObject;
30
+ (radius: number, ...objects: IGeometry[]): ITransformable;
31
31
  }
32
32
  declare const _default: FilletFunction;
33
33
  export default _default;
@@ -1,5 +1,6 @@
1
- export type { ISceneObject, IFuseable, IPlane, IAxis, ISelect, IGeometry, IExtrudableGeometry, IRect, ISlot, IPolygon, ITwoObjectsTangentLine, ITangentArcTwoObjects, IExtrude, ICut, ICommon, ISweep, ILoft, IRevolve, IDraft } from "./interfaces.js";
1
+ export type { ISceneObject, ITransformable, IFuseable, IPlane, IAxis, ISelect, IGeometry, IExtrudableGeometry, IRect, ISlot, IPolygon, ITwoObjectsTangentLine, ITangentArcTwoObjects, IExtrude, ICut, ICommon, ISweep, ILoft, IRevolve, IDraft } from "./interfaces.js";
2
2
  export { default as axis } from "./axis.js";
3
+ export { default as local } from "./local.js";
3
4
  export { default as plane } from "./plane.js";
4
5
  export { default as sketch } from "./sketch.js";
5
6
  export { default as fuse } from "./fuse.js";
@@ -1,4 +1,5 @@
1
1
  export { default as axis } from "./axis.js";
2
+ export { default as local } from "./local.js";
2
3
  export { default as plane } from "./plane.js";
3
4
  export { default as sketch } from "./sketch.js";
4
5
  export { default as fuse } from "./fuse.js";
@@ -1,7 +1,10 @@
1
- import { LazyVertex } from "../features/lazy-vertex.js";
2
- import { Point2DLike } from "../math/point.js";
3
- import { FaceFilterBuilder } from "../filters/face/face-filter.js";
4
- import { EdgeFilterBuilder } from "../filters/edge/edge-filter.js";
1
+ import type { LazyVertex } from "../features/lazy-vertex.js";
2
+ import type { Point2DLike, PointLike } from "../math/point.js";
3
+ import type { FaceFilterBuilder } from "../filters/face/face-filter.js";
4
+ import type { EdgeFilterBuilder } from "../filters/edge/edge-filter.js";
5
+ import type { Matrix4 } from "../math/matrix4.js";
6
+ import type { AxisLike } from "../math/axis.js";
7
+ import type { PlaneLike } from "../math/plane.js";
5
8
  export interface ISceneObject {
6
9
  /**
7
10
  * Sets a custom display name for this object, overriding the default type-based name.
@@ -21,7 +24,7 @@ export interface ISceneObject {
21
24
  */
22
25
  reusable(): this;
23
26
  }
24
- export interface IFuseable extends ISceneObject {
27
+ export interface IFuseable extends ITransformable {
25
28
  /**
26
29
  * Additive boolean operation — fuses the result with existing shapes.
27
30
  * When called with no arguments, fuses with all intersecting scene objects.
@@ -42,13 +45,66 @@ export interface IFuseable extends ISceneObject {
42
45
  */
43
46
  remove(...objects: ISceneObject[]): this;
44
47
  }
45
- export interface IPlane extends ISceneObject {
48
+ /**
49
+ * Scene objects that can be chained with world-space transformations.
50
+ * The chained form `obj.translate(...)` / `obj.rotate(...)` / `obj.mirror(...)`
51
+ * applies the transform to the object's built shapes; it does not create
52
+ * a separate history entry like the free-function `translate()` does.
53
+ *
54
+ * Container objects (sketches, parts, repeat/mirror features) deliberately
55
+ * do not expose this interface — apply transforms to their contents instead.
56
+ */
57
+ export interface ITransformable extends ISceneObject {
58
+ /**
59
+ * Composes a 4x4 transformation matrix onto this object. Applied to the
60
+ * object's own shapes after build. Chained calls compose left-to-right:
61
+ * `.translate(T).rotate(R)` applies translation first, then rotation.
62
+ */
63
+ transform(matrix: Matrix4): this;
64
+ /**
65
+ * Translate along X.
66
+ * @param x - Distance along world X.
67
+ */
68
+ translate(x: number): this;
69
+ /**
70
+ * Translate along X and Y.
71
+ */
72
+ translate(x: number, y: number): this;
73
+ /**
74
+ * Translate along X, Y, and Z.
75
+ */
76
+ translate(x: number, y: number, z: number): this;
77
+ /**
78
+ * Translate by a point-like offset in world space.
79
+ */
80
+ translate(offset: PointLike): this;
81
+ /**
82
+ * Rotate by an angle around world Z through the origin.
83
+ * @param angle - Rotation in degrees.
84
+ */
85
+ rotate(angle: number): this;
86
+ /**
87
+ * Rotate around an axis by an angle.
88
+ * @param axis - The axis to rotate around. Use `local(...)` to reference a sketch-local axis.
89
+ * @param angle - Rotation in degrees.
90
+ */
91
+ rotate(axis: AxisLike, angle: number): this;
92
+ /**
93
+ * Mirror across a plane.
94
+ */
95
+ mirror(plane: PlaneLike): this;
96
+ /**
97
+ * Mirror across an axis (primarily useful for 2D geometry).
98
+ */
99
+ mirror(axis: AxisLike): this;
100
+ }
101
+ export interface IPlane extends ITransformable {
46
102
  }
47
- export interface IAxis extends ISceneObject {
103
+ export interface IAxis extends ITransformable {
48
104
  }
49
105
  export interface ISelect extends ISceneObject {
50
106
  }
51
- export interface IGeometry extends ISceneObject {
107
+ export interface IGeometry extends ITransformable {
52
108
  /**
53
109
  * Returns a lazy-evaluated vertex at the start point of this geometry element.
54
110
  */
@@ -155,11 +211,6 @@ export interface ISlot extends IExtrudableGeometry {
155
211
  * @param value - `true` to center, `false` (default) to start from the current position.
156
212
  */
157
213
  centered(value?: boolean): this;
158
- /**
159
- * Sets the rotation angle of the slot's primary axis.
160
- * @param angle - Rotation in degrees.
161
- */
162
- rotate(angle: number): this;
163
214
  }
164
215
  export interface IPolygon extends IExtrudableGeometry {
165
216
  /**
@@ -197,7 +248,7 @@ export interface ITangentArcTwoObjects extends IGeometry {
197
248
  */
198
249
  end(index?: number): LazyVertex;
199
250
  }
200
- export interface ICommon extends ISceneObject {
251
+ export interface ICommon extends ITransformable {
201
252
  /**
202
253
  * Controls whether the original objects involved in the boolean intersection
203
254
  * are retained or removed after the operation.
@@ -297,7 +348,7 @@ export interface IExtrude extends IFuseable {
297
348
  */
298
349
  thin(offset1: number, offset2: number): this;
299
350
  }
300
- export interface ICut extends ISceneObject {
351
+ export interface ICut extends ITransformable {
301
352
  /**
302
353
  * Enables symmetric mode — cuts equally in both directions from the sketch plane.
303
354
  */
@@ -562,9 +613,9 @@ export interface ISweep extends IFuseable {
562
613
  */
563
614
  capEdges(...args: (number | EdgeFilterBuilder)[]): ISceneObject;
564
615
  }
565
- export interface IDraft extends ISceneObject {
616
+ export interface IDraft extends ITransformable {
566
617
  }
567
- export interface IShell extends ISceneObject {
618
+ export interface IShell extends ITransformable {
568
619
  /**
569
620
  * Selects the inner wall faces created by the shell operation (from thickness removal).
570
621
  * @param args - Numeric indices or {@link FaceFilterBuilder} instances to filter the selection.
@@ -1,10 +1,10 @@
1
- import { ISceneObject } from "./interfaces.js";
1
+ import { ITransformable } from "./interfaces.js";
2
2
  interface LoadFunction {
3
3
  /**
4
4
  * Loads a 3D model file (STEP, STL, etc.) by filename.
5
5
  * @param fileName - The path to the model file
6
6
  */
7
- (fileName: string): ISceneObject;
7
+ (fileName: string): ITransformable;
8
8
  }
9
9
  declare const _default: LoadFunction;
10
10
  export default _default;
@@ -0,0 +1,12 @@
1
+ import { StandardAxis } from "../math/axis.js";
2
+ import { IAxis } from "./interfaces.js";
3
+ interface LocalFunction {
4
+ /**
5
+ * Creates an axis in the active sketch's local coordinate system.
6
+ * @param axis - One of the standard axes ('x', 'y', 'z') to interpret
7
+ * relative to the active sketch's plane.
8
+ */
9
+ (axis: StandardAxis): IAxis;
10
+ }
11
+ declare const _default: LocalFunction;
12
+ export default _default;
@@ -0,0 +1,18 @@
1
+ import { registerBuilder } from "../index.js";
2
+ import { AxisFromSketch } from "../features/axis-from-sketch.js";
3
+ import { isStandardAxis } from "../math/axis.js";
4
+ function build(context) {
5
+ return function local(axis) {
6
+ if (!isStandardAxis(axis)) {
7
+ throw new Error("local() accepts only 'x', 'y', or 'z'");
8
+ }
9
+ const sketch = context.getActiveSketch();
10
+ if (!sketch) {
11
+ throw new Error("local() can only be used inside a sketch");
12
+ }
13
+ const ax = new AxisFromSketch(sketch, axis);
14
+ context.addSceneObject(ax);
15
+ return ax;
16
+ };
17
+ }
18
+ export default registerBuilder(build);
@@ -1,40 +1,40 @@
1
1
  import { PlaneLike } from "../math/plane.js";
2
2
  import { AxisLike } from "../math/axis.js";
3
- import { ISceneObject } from "./interfaces.js";
3
+ import { ISceneObject, ITransformable } from "./interfaces.js";
4
4
  interface MirrorFunction {
5
5
  /**
6
6
  * [2D] Mirror all sketch geometries across a given line.
7
7
  * @param line The line to mirror across
8
8
  */
9
- (line: ISceneObject): ISceneObject;
9
+ (line: ISceneObject): ITransformable;
10
10
  /**
11
11
  * [2D] Mirror all sketch geometries across a given axis.
12
- * @param axis The axis to mirror across
12
+ * @param axis The local axis to mirror across
13
13
  */
14
- (axis: AxisLike): ISceneObject;
14
+ (axis: AxisLike): ITransformable;
15
15
  /**
16
16
  * [2D] Mirror given sketch geometries across a given line.
17
17
  * @param line The line to mirror across
18
18
  * @param geometries The geometries to mirror
19
19
  */
20
- (line: ISceneObject, ...geometries: ISceneObject[]): ISceneObject;
20
+ (line: ISceneObject, ...geometries: ISceneObject[]): ITransformable;
21
21
  /**
22
22
  * [2D] Mirror given sketch geometries across a given axis.
23
- * @param axis The axis to mirror across
23
+ * @param axis The local axis to mirror across
24
24
  * @param geometries The geometries to mirror
25
25
  */
26
- (axis: AxisLike, ...geometries: ISceneObject[]): ISceneObject;
26
+ (axis: AxisLike, ...geometries: ISceneObject[]): ITransformable;
27
27
  /**
28
28
  * [3D] Mirror all scene shapes across a given plane.
29
29
  * @param plane The plane to mirror across
30
30
  */
31
- (plane: PlaneLike): ISceneObject;
31
+ (plane: PlaneLike): ITransformable;
32
32
  /**
33
33
  * [3D] Mirror given shapes across a given plane.
34
34
  * @param plane The plane to mirror across
35
35
  * @param objects The shapes to mirror
36
36
  */
37
- (plane: PlaneLike, ...objects: ISceneObject[]): ISceneObject;
37
+ (plane: PlaneLike, ...objects: ISceneObject[]): ITransformable;
38
38
  }
39
39
  declare const _default: MirrorFunction;
40
40
  export default _default;
@@ -68,9 +68,6 @@ function build(context) {
68
68
  }
69
69
  const targetObjects = args.slice(1);
70
70
  const mirror = new MirrorShape2D(axis, targetObjects);
71
- if (!(args[0] instanceof AxisObjectBase) && !(args[0] instanceof SceneObject)) {
72
- context.addSceneObject(axis);
73
- }
74
71
  context.addSceneObject(mirror);
75
72
  return mirror;
76
73
  }
@@ -1,10 +1,10 @@
1
- import { ISceneObject } from "./interfaces.js";
1
+ import { ISceneObject, ITransformable } from "./interfaces.js";
2
2
  interface RemoveFunction {
3
3
  /**
4
4
  * Removes the given objects from the scene.
5
5
  * @param objects - The objects to remove
6
6
  */
7
- (...objects: ISceneObject[]): ISceneObject;
7
+ (...objects: ISceneObject[]): ITransformable;
8
8
  }
9
9
  declare const _default: RemoveFunction;
10
10
  export default _default;
@@ -1,26 +1,26 @@
1
1
  import { AxisLike } from "../math/axis.js";
2
- import { ISceneObject } from "./interfaces.js";
2
+ import { ISceneObject, ITransformable } from "./interfaces.js";
3
3
  interface RotateFunction {
4
4
  /**
5
5
  * [2D] Rotates geometry by an angle inside a sketch.
6
6
  * @param angle - The rotation angle in degrees
7
7
  * @param targets - The geometries to rotate (defaults to last object)
8
8
  */
9
- (angle: number, ...targets: ISceneObject[]): ISceneObject;
9
+ (angle: number, ...targets: ISceneObject[]): ITransformable;
10
10
  /**
11
11
  * [2D] Rotates geometry by an angle inside a sketch, optionally making a copy.
12
12
  * @param angle - The rotation angle in degrees
13
13
  * @param copy - Whether to copy instead of move
14
14
  * @param targets - The geometries to rotate (defaults to last object)
15
15
  */
16
- (angle: number, copy: boolean, ...targets: ISceneObject[]): ISceneObject;
16
+ (angle: number, copy: boolean, ...targets: ISceneObject[]): ITransformable;
17
17
  /**
18
18
  * [3D] Rotates objects around an axis by an angle.
19
19
  * @param axis - The axis to rotate around
20
20
  * @param angle - The rotation angle in degrees
21
21
  * @param targets - The objects to rotate (defaults to last object)
22
22
  */
23
- (axis: AxisLike, angle: number, ...targets: ISceneObject[]): ISceneObject;
23
+ (axis: AxisLike, angle: number, ...targets: ISceneObject[]): ITransformable;
24
24
  /**
25
25
  * [3D] Rotates objects around an axis by an angle, optionally making a copy.
26
26
  * @param axis - The axis to rotate around
@@ -28,7 +28,7 @@ interface RotateFunction {
28
28
  * @param copy - Whether to copy instead of move
29
29
  * @param targets - The objects to rotate (defaults to last object)
30
30
  */
31
- (axis: AxisLike, angle: number, copy: boolean, ...targets: ISceneObject[]): ISceneObject;
31
+ (axis: AxisLike, angle: number, copy: boolean, ...targets: ISceneObject[]): ITransformable;
32
32
  }
33
33
  declare const _default: RotateFunction;
34
34
  export default _default;