fluidcad 0.0.24 → 0.0.26
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.
- package/lib/dist/common/scene-object.d.ts +6 -2
- package/lib/dist/common/scene-object.js +28 -16
- package/lib/dist/common/transformable-primitive.d.ts +16 -0
- package/lib/dist/common/transformable-primitive.js +116 -0
- package/lib/dist/core/2d/tarc.d.ts +2 -2
- package/lib/dist/core/copy.js +5 -4
- package/lib/dist/core/cylinder.d.ts +2 -2
- package/lib/dist/core/index.d.ts +2 -1
- package/lib/dist/core/index.js +1 -0
- package/lib/dist/core/interfaces.d.ts +80 -21
- package/lib/dist/core/local.d.ts +12 -0
- package/lib/dist/core/local.js +18 -0
- package/lib/dist/core/mirror.d.ts +2 -2
- package/lib/dist/core/mirror.js +42 -60
- package/lib/dist/core/plane.d.ts +5 -7
- package/lib/dist/core/sphere.d.ts +3 -3
- package/lib/dist/features/2d/circle.js +2 -1
- package/lib/dist/features/2d/tarc-with-tangent.js +4 -2
- package/lib/dist/features/2d/tarc.js +4 -2
- package/lib/dist/features/axis-from-edge.js +2 -2
- package/lib/dist/features/axis-from-sketch.d.ts +18 -0
- package/lib/dist/features/axis-from-sketch.js +58 -0
- package/lib/dist/features/copy-linear2d.d.ts +4 -2
- package/lib/dist/features/copy-linear2d.js +23 -9
- package/lib/dist/features/cylinder.d.ts +2 -2
- package/lib/dist/features/cylinder.js +2 -2
- package/lib/dist/features/mirror-shape.js +10 -0
- package/lib/dist/features/plane-from-object.d.ts +1 -1
- package/lib/dist/features/plane-from-object.js +11 -6
- package/lib/dist/features/plane-mid.d.ts +1 -1
- package/lib/dist/features/plane.d.ts +1 -1
- package/lib/dist/features/select.js +0 -1
- package/lib/dist/features/sphere.d.ts +2 -2
- package/lib/dist/features/sphere.js +2 -2
- package/lib/dist/math/axis.d.ts +1 -0
- package/lib/dist/math/axis.js +4 -1
- package/lib/dist/math/index.d.ts +2 -2
- package/lib/dist/math/index.js +1 -1
- package/lib/dist/math/plane.d.ts +1 -2
- package/lib/dist/math/plane.js +20 -19
- package/lib/dist/rendering/render.js +8 -0
- package/lib/dist/tests/features/cut-two-distances.test.js +1 -1
- package/lib/dist/tests/features/cut.test.js +1 -1
- package/lib/dist/tests/features/mirror2d.test.js +34 -0
- package/lib/dist/tests/features/primitive-chain.test.d.ts +1 -0
- package/lib/dist/tests/features/primitive-chain.test.js +45 -0
- package/lib/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/server/dist/code-editor.d.ts +3 -2
- package/server/dist/code-editor.js +244 -121
- package/ui/dist/assets/{index-CqP_mgZk.js → index-BeLxRMCv.js} +4 -4
- package/ui/dist/index.html +1 -1
|
@@ -27,6 +27,7 @@ export declare abstract class SceneObject implements Comparable<SceneObject>, Se
|
|
|
27
27
|
private _id;
|
|
28
28
|
private _order;
|
|
29
29
|
private _transform;
|
|
30
|
+
private _appliedTransform;
|
|
30
31
|
private _cloneSource;
|
|
31
32
|
private _parent;
|
|
32
33
|
private _alwaysVisible;
|
|
@@ -56,6 +57,8 @@ export declare abstract class SceneObject implements Comparable<SceneObject>, Se
|
|
|
56
57
|
abstract serialize(scope?: Set<SceneObject>): any;
|
|
57
58
|
abstract getType(): string;
|
|
58
59
|
abstract build(context?: BuildSceneObjectContext): void;
|
|
60
|
+
getAppliedTransform(): Matrix4 | null;
|
|
61
|
+
protected composeAppliedTransform(matrix: Matrix4): void;
|
|
59
62
|
compareTo(other: SceneObject): boolean;
|
|
60
63
|
getDependencies(): SceneObject[];
|
|
61
64
|
createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
|
|
@@ -104,9 +107,10 @@ export declare abstract class SceneObject implements Comparable<SceneObject>, Se
|
|
|
104
107
|
getOperationMode(): OperationMode;
|
|
105
108
|
isSymmetric(): boolean;
|
|
106
109
|
resolveFusionScope(sceneObjects: SceneObject[]): SceneObject[];
|
|
107
|
-
add(
|
|
110
|
+
add(): this;
|
|
108
111
|
new(): this;
|
|
109
|
-
remove(
|
|
112
|
+
remove(): this;
|
|
113
|
+
scope(...objects: ISceneObject[]): this;
|
|
110
114
|
symmetric(): this;
|
|
111
115
|
/**
|
|
112
116
|
* Called after all objects have been built. Override to perform
|
|
@@ -5,6 +5,7 @@ export class SceneObject {
|
|
|
5
5
|
_id;
|
|
6
6
|
_order = 0;
|
|
7
7
|
_transform = null;
|
|
8
|
+
_appliedTransform = null;
|
|
8
9
|
_cloneSource = null;
|
|
9
10
|
_parent = null;
|
|
10
11
|
_alwaysVisible = false;
|
|
@@ -89,6 +90,14 @@ export class SceneObject {
|
|
|
89
90
|
getSnapshot() {
|
|
90
91
|
return this.getState('snapshot') || [];
|
|
91
92
|
}
|
|
93
|
+
getAppliedTransform() {
|
|
94
|
+
return this._appliedTransform;
|
|
95
|
+
}
|
|
96
|
+
composeAppliedTransform(matrix) {
|
|
97
|
+
this._appliedTransform = this._appliedTransform
|
|
98
|
+
? matrix.multiply(this._appliedTransform)
|
|
99
|
+
: matrix;
|
|
100
|
+
}
|
|
92
101
|
compareTo(other) {
|
|
93
102
|
const match = this._guide === other._guide && this._reusable === other._reusable;
|
|
94
103
|
if (!match) {
|
|
@@ -100,6 +109,13 @@ export class SceneObject {
|
|
|
100
109
|
if (this._symmetric !== other._symmetric) {
|
|
101
110
|
return false;
|
|
102
111
|
}
|
|
112
|
+
if (!this._appliedTransform !== !other._appliedTransform) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
if (this._appliedTransform && other._appliedTransform
|
|
116
|
+
&& !this._appliedTransform.equals(other._appliedTransform)) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
103
119
|
if (typeof (this._fusionScope) !== typeof (other._fusionScope)) {
|
|
104
120
|
return false;
|
|
105
121
|
}
|
|
@@ -148,6 +164,9 @@ export class SceneObject {
|
|
|
148
164
|
const result = [];
|
|
149
165
|
for (const obj of ordered) {
|
|
150
166
|
const copy = obj.createCopy(remap);
|
|
167
|
+
if (obj._appliedTransform) {
|
|
168
|
+
copy._appliedTransform = obj._appliedTransform;
|
|
169
|
+
}
|
|
151
170
|
remap.set(obj, copy);
|
|
152
171
|
result.push(copy);
|
|
153
172
|
const parent = obj.getParent();
|
|
@@ -351,17 +370,9 @@ export class SceneObject {
|
|
|
351
370
|
}
|
|
352
371
|
return sceneObjects;
|
|
353
372
|
}
|
|
354
|
-
add(
|
|
373
|
+
add() {
|
|
355
374
|
this._operationMode = 'add';
|
|
356
|
-
|
|
357
|
-
this._fusionScope = 'all';
|
|
358
|
-
}
|
|
359
|
-
else if (objects.length === 1) {
|
|
360
|
-
this._fusionScope = objects[0];
|
|
361
|
-
}
|
|
362
|
-
else {
|
|
363
|
-
this._fusionScope = objects;
|
|
364
|
-
}
|
|
375
|
+
this._fusionScope = 'all';
|
|
365
376
|
return this;
|
|
366
377
|
}
|
|
367
378
|
new() {
|
|
@@ -369,15 +380,16 @@ export class SceneObject {
|
|
|
369
380
|
this._fusionScope = 'none';
|
|
370
381
|
return this;
|
|
371
382
|
}
|
|
372
|
-
remove(
|
|
383
|
+
remove() {
|
|
373
384
|
this._operationMode = 'remove';
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
385
|
+
this._fusionScope = 'all';
|
|
386
|
+
return this;
|
|
387
|
+
}
|
|
388
|
+
scope(...objects) {
|
|
389
|
+
if (objects.length === 1) {
|
|
378
390
|
this._fusionScope = objects[0];
|
|
379
391
|
}
|
|
380
|
-
else {
|
|
392
|
+
else if (objects.length > 1) {
|
|
381
393
|
this._fusionScope = objects;
|
|
382
394
|
}
|
|
383
395
|
return this;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SceneObject } from "./scene-object.js";
|
|
2
|
+
import { Matrix4 } from "../math/matrix4.js";
|
|
3
|
+
import type { AxisLike } from "../math/axis.js";
|
|
4
|
+
import type { PlaneLike } from "../math/plane.js";
|
|
5
|
+
import type { PointLike } from "../math/point.js";
|
|
6
|
+
export declare abstract class TransformablePrimitive extends SceneObject {
|
|
7
|
+
transform(matrix: Matrix4): this;
|
|
8
|
+
translate(x: number): this;
|
|
9
|
+
translate(x: number, y: number): this;
|
|
10
|
+
translate(x: number, y: number, z: number): this;
|
|
11
|
+
translate(p: PointLike): this;
|
|
12
|
+
rotate(angle: number): this;
|
|
13
|
+
rotate(axis: AxisLike, angle: number): this;
|
|
14
|
+
mirror(plane: PlaneLike): this;
|
|
15
|
+
mirror(axis: AxisLike): this;
|
|
16
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { SceneObject } from "./scene-object.js";
|
|
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";
|
|
6
|
+
export class TransformablePrimitive extends SceneObject {
|
|
7
|
+
transform(matrix) {
|
|
8
|
+
this.composeAppliedTransform(matrix);
|
|
9
|
+
return this;
|
|
10
|
+
}
|
|
11
|
+
translate(a, b, c) {
|
|
12
|
+
let x, y, z;
|
|
13
|
+
if (typeof a === 'number') {
|
|
14
|
+
x = a;
|
|
15
|
+
y = b ?? 0;
|
|
16
|
+
z = c ?? 0;
|
|
17
|
+
}
|
|
18
|
+
else if (Array.isArray(a)) {
|
|
19
|
+
x = a[0] ?? 0;
|
|
20
|
+
y = a[1] ?? 0;
|
|
21
|
+
z = a[2] ?? 0;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
x = a.x;
|
|
25
|
+
y = a.y;
|
|
26
|
+
z = a.z;
|
|
27
|
+
}
|
|
28
|
+
return this.transform(Matrix4.fromTranslation(x, y, z));
|
|
29
|
+
}
|
|
30
|
+
rotate(a, b) {
|
|
31
|
+
let origin;
|
|
32
|
+
let direction;
|
|
33
|
+
let angleDeg;
|
|
34
|
+
if (typeof a === 'number') {
|
|
35
|
+
origin = new Point(0, 0, 0);
|
|
36
|
+
direction = Vector3d.unitZ();
|
|
37
|
+
angleDeg = a;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
const resolved = resolveAxisLike(a);
|
|
41
|
+
origin = resolved.origin;
|
|
42
|
+
direction = resolved.direction;
|
|
43
|
+
angleDeg = b;
|
|
44
|
+
}
|
|
45
|
+
return this.transform(Matrix4.fromRotationAroundAxis(origin, direction, rad(angleDeg)));
|
|
46
|
+
}
|
|
47
|
+
mirror(arg) {
|
|
48
|
+
if (isAxisLikeArg(arg)) {
|
|
49
|
+
const axis = resolveAxisLike(arg);
|
|
50
|
+
return this.transform(Matrix4.mirrorAxis(axis.origin, axis.direction));
|
|
51
|
+
}
|
|
52
|
+
const plane = resolvePlaneLike(arg);
|
|
53
|
+
return this.transform(Matrix4.mirrorPlane(plane.normal, plane.origin));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function isAxisLikeArg(arg) {
|
|
57
|
+
if (arg === 'x' || arg === 'y' || arg === 'z') {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
if (arg && typeof arg === 'object') {
|
|
61
|
+
if (typeof arg.getAxis === 'function') {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
if (arg.origin && arg.direction) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
function resolveAxisLike(arg) {
|
|
71
|
+
if (arg === 'x') {
|
|
72
|
+
return { origin: new Point(0, 0, 0), direction: Vector3d.unitX() };
|
|
73
|
+
}
|
|
74
|
+
if (arg === 'y') {
|
|
75
|
+
return { origin: new Point(0, 0, 0), direction: Vector3d.unitY() };
|
|
76
|
+
}
|
|
77
|
+
if (arg === 'z') {
|
|
78
|
+
return { origin: new Point(0, 0, 0), direction: Vector3d.unitZ() };
|
|
79
|
+
}
|
|
80
|
+
const a = arg;
|
|
81
|
+
if (typeof a.getAxis === 'function') {
|
|
82
|
+
const axis = a.getAxis();
|
|
83
|
+
return { origin: axis.origin, direction: axis.direction };
|
|
84
|
+
}
|
|
85
|
+
return { origin: a.origin, direction: a.direction };
|
|
86
|
+
}
|
|
87
|
+
function resolvePlaneLike(arg) {
|
|
88
|
+
if (typeof arg === 'string') {
|
|
89
|
+
switch (arg) {
|
|
90
|
+
case 'xy':
|
|
91
|
+
case 'top':
|
|
92
|
+
return { origin: new Point(0, 0, 0), normal: Vector3d.unitZ() };
|
|
93
|
+
case '-xy':
|
|
94
|
+
case 'bottom':
|
|
95
|
+
return { origin: new Point(0, 0, 0), normal: Vector3d.unitZ().multiply(-1) };
|
|
96
|
+
case 'xz':
|
|
97
|
+
case 'front':
|
|
98
|
+
return { origin: new Point(0, 0, 0), normal: Vector3d.unitY().multiply(-1) };
|
|
99
|
+
case '-xz':
|
|
100
|
+
case 'back':
|
|
101
|
+
return { origin: new Point(0, 0, 0), normal: Vector3d.unitY() };
|
|
102
|
+
case 'yz':
|
|
103
|
+
case 'right':
|
|
104
|
+
return { origin: new Point(0, 0, 0), normal: Vector3d.unitX() };
|
|
105
|
+
case '-yz':
|
|
106
|
+
case 'left':
|
|
107
|
+
return { origin: new Point(0, 0, 0), normal: Vector3d.unitX().multiply(-1) };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const p = arg;
|
|
111
|
+
if (typeof p.getPlane === 'function') {
|
|
112
|
+
const plane = p.getPlane();
|
|
113
|
+
return { origin: plane.origin, normal: plane.normal };
|
|
114
|
+
}
|
|
115
|
+
return { origin: p.origin, normal: p.normal };
|
|
116
|
+
}
|
|
@@ -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
|
*/
|
package/lib/dist/core/copy.js
CHANGED
|
@@ -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
|
|
23
|
-
? axisArg.map(a => normalizeAxis(a))
|
|
24
|
-
: [normalizeAxis(axisArg)];
|
|
23
|
+
const axisList = Array.isArray(axisArg) ? axisArg : [axisArg];
|
|
25
24
|
if (activeSketch) {
|
|
26
|
-
const
|
|
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 {
|
|
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):
|
|
8
|
+
(radius: number, height: number): ITransformable;
|
|
9
9
|
}
|
|
10
10
|
declare const _default: CylinderFunction;
|
|
11
11
|
export default _default;
|
package/lib/dist/core/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export type { ISceneObject,
|
|
1
|
+
export type { ISceneObject, ITransformable, IBooleanOperation, 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";
|
package/lib/dist/core/index.js
CHANGED
|
@@ -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,26 +24,81 @@ export interface ISceneObject {
|
|
|
21
24
|
*/
|
|
22
25
|
reusable(): this;
|
|
23
26
|
}
|
|
24
|
-
export interface
|
|
27
|
+
export interface IBooleanOperation extends ISceneObject {
|
|
25
28
|
/**
|
|
26
|
-
* Additive boolean operation — fuses the result with
|
|
27
|
-
*
|
|
28
|
-
* When called with specific objects, fuses only with those objects.
|
|
29
|
-
* @param objects - Optional target objects to fuse with.
|
|
29
|
+
* Additive boolean operation — fuses the result with all intersecting scene objects.
|
|
30
|
+
* Use `.scope()` to target specific objects.
|
|
30
31
|
*/
|
|
31
|
-
add(
|
|
32
|
+
add(): this;
|
|
32
33
|
/**
|
|
33
34
|
* No boolean operation — keeps the result as a standalone shape,
|
|
34
35
|
* separate from all other scene objects.
|
|
35
36
|
*/
|
|
36
37
|
'new'(): this;
|
|
37
38
|
/**
|
|
38
|
-
* Subtractive boolean operation — cuts the result from
|
|
39
|
-
*
|
|
40
|
-
* When called with specific objects, cuts only from those objects.
|
|
41
|
-
* @param objects - Optional target objects to cut from.
|
|
39
|
+
* Subtractive boolean operation — cuts the result from all intersecting scene objects.
|
|
40
|
+
* Use `.scope()` to target specific objects.
|
|
42
41
|
*/
|
|
43
|
-
remove(
|
|
42
|
+
remove(): this;
|
|
43
|
+
/**
|
|
44
|
+
* Narrows the boolean operation scope to specific target objects.
|
|
45
|
+
* Must be chained after `.add()` or `.remove()`.
|
|
46
|
+
* @param objects - The target objects to operate on.
|
|
47
|
+
*/
|
|
48
|
+
scope(...objects: ISceneObject[]): this;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Scene objects that can be chained with world-space transformations.
|
|
52
|
+
* The chained form `obj.translate(...)` / `obj.rotate(...)` / `obj.mirror(...)`
|
|
53
|
+
* applies the transform to the object's built shapes; it does not create
|
|
54
|
+
* a separate history entry like the free-function `translate()` does.
|
|
55
|
+
*
|
|
56
|
+
* Container objects (sketches, parts, repeat/mirror features) deliberately
|
|
57
|
+
* do not expose this interface — apply transforms to their contents instead.
|
|
58
|
+
*/
|
|
59
|
+
export interface ITransformable extends ISceneObject {
|
|
60
|
+
/**
|
|
61
|
+
* Composes a 4x4 transformation matrix onto this object. Applied to the
|
|
62
|
+
* object's own shapes after build. Chained calls compose left-to-right:
|
|
63
|
+
* `.translate(T).rotate(R)` applies translation first, then rotation.
|
|
64
|
+
*/
|
|
65
|
+
transform(matrix: Matrix4): this;
|
|
66
|
+
/**
|
|
67
|
+
* Translate along X.
|
|
68
|
+
* @param x - Distance along world X.
|
|
69
|
+
*/
|
|
70
|
+
translate(x: number): this;
|
|
71
|
+
/**
|
|
72
|
+
* Translate along X and Y.
|
|
73
|
+
*/
|
|
74
|
+
translate(x: number, y: number): this;
|
|
75
|
+
/**
|
|
76
|
+
* Translate along X, Y, and Z.
|
|
77
|
+
*/
|
|
78
|
+
translate(x: number, y: number, z: number): this;
|
|
79
|
+
/**
|
|
80
|
+
* Translate by a point-like offset in world space.
|
|
81
|
+
*/
|
|
82
|
+
translate(offset: PointLike): this;
|
|
83
|
+
/**
|
|
84
|
+
* Rotate by an angle around world Z through the origin.
|
|
85
|
+
* @param angle - Rotation in degrees.
|
|
86
|
+
*/
|
|
87
|
+
rotate(angle: number): this;
|
|
88
|
+
/**
|
|
89
|
+
* Rotate around an axis by an angle.
|
|
90
|
+
* @param axis - The axis to rotate around. Use `local(...)` to reference a sketch-local axis.
|
|
91
|
+
* @param angle - Rotation in degrees.
|
|
92
|
+
*/
|
|
93
|
+
rotate(axis: AxisLike, angle: number): this;
|
|
94
|
+
/**
|
|
95
|
+
* Mirror across a plane.
|
|
96
|
+
*/
|
|
97
|
+
mirror(plane: PlaneLike): this;
|
|
98
|
+
/**
|
|
99
|
+
* Mirror across an axis (primarily useful for 2D geometry).
|
|
100
|
+
*/
|
|
101
|
+
mirror(axis: AxisLike): this;
|
|
44
102
|
}
|
|
45
103
|
export interface IPlane extends ISceneObject {
|
|
46
104
|
}
|
|
@@ -205,7 +263,7 @@ export interface ICommon extends ISceneObject {
|
|
|
205
263
|
*/
|
|
206
264
|
keepOriginal(value?: boolean): this;
|
|
207
265
|
}
|
|
208
|
-
export interface IExtrude extends
|
|
266
|
+
export interface IExtrude extends IBooleanOperation {
|
|
209
267
|
/**
|
|
210
268
|
* Enables symmetric mode — extrudes equally in both directions from the sketch plane.
|
|
211
269
|
*/
|
|
@@ -303,10 +361,11 @@ export interface ICut extends ISceneObject {
|
|
|
303
361
|
*/
|
|
304
362
|
symmetric(): this;
|
|
305
363
|
/**
|
|
306
|
-
* Narrows the cut scope to specific
|
|
364
|
+
* Narrows the cut scope to specific target objects.
|
|
365
|
+
* Must be chained after `.remove()`.
|
|
307
366
|
* @param objects - The target objects to cut from.
|
|
308
367
|
*/
|
|
309
|
-
|
|
368
|
+
scope(...objects: ISceneObject[]): this;
|
|
310
369
|
/**
|
|
311
370
|
* Applies a draft (taper) angle to the cut walls.
|
|
312
371
|
* @param value - A single angle for uniform draft, or a `[start, end]` tuple for asymmetric draft.
|
|
@@ -357,7 +416,7 @@ export interface ICut extends ISceneObject {
|
|
|
357
416
|
*/
|
|
358
417
|
thin(offset1: number, offset2: number): this;
|
|
359
418
|
}
|
|
360
|
-
export interface IRevolve extends
|
|
419
|
+
export interface IRevolve extends IBooleanOperation {
|
|
361
420
|
/**
|
|
362
421
|
* Enables symmetric mode — revolves equally in both directions from the sketch plane.
|
|
363
422
|
*/
|
|
@@ -405,7 +464,7 @@ export interface IRevolve extends IFuseable {
|
|
|
405
464
|
*/
|
|
406
465
|
capEdges(...args: (number | EdgeFilterBuilder)[]): ISceneObject;
|
|
407
466
|
}
|
|
408
|
-
export interface ILoft extends
|
|
467
|
+
export interface ILoft extends IBooleanOperation {
|
|
409
468
|
/**
|
|
410
469
|
* Selects faces on the first profile plane of the loft.
|
|
411
470
|
* @param args - Numeric indices or {@link FaceFilterBuilder} instances to filter the selection.
|
|
@@ -474,7 +533,7 @@ export interface ILoft extends IFuseable {
|
|
|
474
533
|
*/
|
|
475
534
|
capEdges(...args: (number | EdgeFilterBuilder)[]): ISceneObject;
|
|
476
535
|
}
|
|
477
|
-
export interface ISweep extends
|
|
536
|
+
export interface ISweep extends IBooleanOperation {
|
|
478
537
|
/**
|
|
479
538
|
* Selects faces at the start (profile plane) of the sweep.
|
|
480
539
|
* @param args - Numeric indices or {@link FaceFilterBuilder} instances to filter the selection.
|
|
@@ -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);
|
|
@@ -9,7 +9,7 @@ interface MirrorFunction {
|
|
|
9
9
|
(line: ISceneObject): ISceneObject;
|
|
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
14
|
(axis: AxisLike): ISceneObject;
|
|
15
15
|
/**
|
|
@@ -20,7 +20,7 @@ interface MirrorFunction {
|
|
|
20
20
|
(line: ISceneObject, ...geometries: ISceneObject[]): ISceneObject;
|
|
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
26
|
(axis: AxisLike, ...geometries: ISceneObject[]): ISceneObject;
|
package/lib/dist/core/mirror.js
CHANGED
|
@@ -4,87 +4,69 @@ import { SceneObject } from "../common/scene-object.js";
|
|
|
4
4
|
import { MirrorShape } from "../features/mirror-shape.js";
|
|
5
5
|
import { PlaneObjectBase } from "../features/plane-renderable-base.js";
|
|
6
6
|
import { PlaneObject } from "../features/plane.js";
|
|
7
|
-
import { isAxisLike } from "../math/axis.js";
|
|
7
|
+
import { isAxisLike, isStandardAxis } from "../math/axis.js";
|
|
8
8
|
import { MirrorShape2D } from "../features/mirror-shape2d.js";
|
|
9
9
|
import { AxisObjectBase } from "../features/axis-renderable-base.js";
|
|
10
10
|
import { AxisObject } from "../features/axis.js";
|
|
11
11
|
import { AxisFromEdge } from "../features/axis-from-edge.js";
|
|
12
|
+
const axisToPlaneName = { x: "yz", y: "xz", z: "xy" };
|
|
13
|
+
function resolveAxis(arg, context) {
|
|
14
|
+
if (arg instanceof AxisObjectBase) {
|
|
15
|
+
return arg;
|
|
16
|
+
}
|
|
17
|
+
if (arg instanceof SceneObject) {
|
|
18
|
+
const axis = new AxisFromEdge(arg);
|
|
19
|
+
context.addSceneObject(axis);
|
|
20
|
+
return axis;
|
|
21
|
+
}
|
|
22
|
+
const a = normalizeAxis(arg);
|
|
23
|
+
const axis = new AxisObject(a);
|
|
24
|
+
context.addSceneObject(axis);
|
|
25
|
+
return axis;
|
|
26
|
+
}
|
|
27
|
+
function resolvePlane(arg, context) {
|
|
28
|
+
if (arg instanceof PlaneObjectBase) {
|
|
29
|
+
return arg;
|
|
30
|
+
}
|
|
31
|
+
const normalizedPlane = normalizePlane(arg);
|
|
32
|
+
const planeObj = new PlaneObject(normalizedPlane);
|
|
33
|
+
context.addSceneObject(planeObj);
|
|
34
|
+
return planeObj;
|
|
35
|
+
}
|
|
12
36
|
function build(context) {
|
|
13
37
|
return function mirror() {
|
|
38
|
+
const activeSketch = context.getActiveSketch();
|
|
14
39
|
if (arguments.length === 1) {
|
|
15
|
-
if (isAxisLike(arguments[0] || arguments[0] instanceof SceneObject)) {
|
|
16
|
-
|
|
17
|
-
if (arguments[0] instanceof AxisObjectBase) {
|
|
18
|
-
axis = arguments[0];
|
|
19
|
-
}
|
|
20
|
-
else if (arguments[0] instanceof SceneObject) {
|
|
21
|
-
const line = arguments[0];
|
|
22
|
-
axis = new AxisFromEdge(line);
|
|
23
|
-
context.addSceneObject(axis);
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
const a = normalizeAxis(arguments[0]);
|
|
27
|
-
axis = new AxisObject(a);
|
|
28
|
-
context.addSceneObject(axis);
|
|
29
|
-
}
|
|
40
|
+
if (activeSketch && (isAxisLike(arguments[0]) || arguments[0] instanceof SceneObject)) {
|
|
41
|
+
const axis = resolveAxis(arguments[0], context);
|
|
30
42
|
const mirror = new MirrorShape2D(axis);
|
|
31
43
|
context.addSceneObject(mirror);
|
|
32
44
|
return mirror;
|
|
33
45
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (!(pln instanceof PlaneObjectBase)) {
|
|
38
|
-
const normalizedPlane = normalizePlane(arguments[0]);
|
|
39
|
-
planeObj = new PlaneObject(normalizedPlane);
|
|
40
|
-
context.addSceneObject(planeObj);
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
planeObj = pln;
|
|
44
|
-
;
|
|
45
|
-
}
|
|
46
|
-
const mirror = new MirrorShape(planeObj);
|
|
47
|
-
context.addSceneObject(mirror);
|
|
48
|
-
return mirror;
|
|
46
|
+
let planeArg = arguments[0];
|
|
47
|
+
if (isStandardAxis(planeArg)) {
|
|
48
|
+
planeArg = axisToPlaneName[planeArg];
|
|
49
49
|
}
|
|
50
|
+
const planeObj = resolvePlane(planeArg, context);
|
|
51
|
+
const mirror = new MirrorShape(planeObj);
|
|
52
|
+
context.addSceneObject(mirror);
|
|
53
|
+
return mirror;
|
|
50
54
|
}
|
|
51
55
|
if (arguments.length >= 2) {
|
|
52
56
|
const args = Array.from(arguments);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
let axis = null;
|
|
56
|
-
if (args[0] instanceof AxisObjectBase) {
|
|
57
|
-
axis = args[0];
|
|
58
|
-
}
|
|
59
|
-
else if (args[0] instanceof SceneObject) {
|
|
60
|
-
const line = args[0];
|
|
61
|
-
axis = new AxisFromEdge(line);
|
|
62
|
-
context.addSceneObject(axis);
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
const a = normalizeAxis(args[0]);
|
|
66
|
-
axis = new AxisObject(a);
|
|
67
|
-
context.addSceneObject(axis);
|
|
68
|
-
}
|
|
57
|
+
if (activeSketch && (isAxisLike(args[0]) || args[0] instanceof SceneObject)) {
|
|
58
|
+
const axis = resolveAxis(args[0], context);
|
|
69
59
|
const targetObjects = args.slice(1);
|
|
70
60
|
const mirror = new MirrorShape2D(axis, targetObjects);
|
|
71
|
-
if (!(args[0] instanceof AxisObjectBase) && !(args[0] instanceof SceneObject)) {
|
|
72
|
-
context.addSceneObject(axis);
|
|
73
|
-
}
|
|
74
61
|
context.addSceneObject(mirror);
|
|
75
62
|
return mirror;
|
|
76
63
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (!(args[0] instanceof PlaneObjectBase)) {
|
|
81
|
-
const normalizedPlane = normalizePlane(args[0]);
|
|
82
|
-
planeObj = new PlaneObject(normalizedPlane);
|
|
83
|
-
context.addSceneObject(planeObj);
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
planeObj = args[0];
|
|
64
|
+
let planeArg = args[0];
|
|
65
|
+
if (isStandardAxis(planeArg)) {
|
|
66
|
+
planeArg = axisToPlaneName[planeArg];
|
|
87
67
|
}
|
|
68
|
+
const planeObj = resolvePlane(planeArg, context);
|
|
69
|
+
const targetObjects = args.slice(1);
|
|
88
70
|
const mirror = new MirrorShape(planeObj, targetObjects);
|
|
89
71
|
context.addSceneObject(mirror);
|
|
90
72
|
return mirror;
|