fluidcad 0.0.25 → 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 +4 -14
- package/lib/dist/common/scene-object.js +10 -127
- package/lib/dist/common/transformable-primitive.d.ts +16 -0
- package/lib/dist/common/transformable-primitive.js +116 -0
- package/lib/dist/core/chamfer.d.ts +5 -5
- package/lib/dist/core/color.d.ts +3 -3
- package/lib/dist/core/fillet.d.ts +6 -6
- package/lib/dist/core/index.d.ts +1 -1
- package/lib/dist/core/interfaces.d.ts +32 -24
- package/lib/dist/core/load.d.ts +2 -2
- package/lib/dist/core/mirror.d.ts +7 -7
- package/lib/dist/core/mirror.js +42 -57
- package/lib/dist/core/plane.d.ts +5 -7
- package/lib/dist/core/remove.d.ts +2 -2
- package/lib/dist/core/rotate.d.ts +5 -5
- package/lib/dist/core/subtract.d.ts +2 -2
- package/lib/dist/core/translate.d.ts +9 -9
- package/lib/dist/features/2d/slot.d.ts +3 -0
- package/lib/dist/features/2d/slot.js +28 -7
- package/lib/dist/features/cylinder.d.ts +2 -2
- package/lib/dist/features/cylinder.js +2 -2
- 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.d.ts +1 -1
- package/lib/dist/features/select.js +1 -1
- package/lib/dist/features/sphere.d.ts +2 -2
- package/lib/dist/features/sphere.js +2 -2
- package/lib/dist/math/index.d.ts +1 -1
- package/lib/dist/math/plane.d.ts +1 -2
- package/lib/dist/math/plane.js +20 -19
- 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/primitive-chain.test.js +45 -0
- package/lib/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/ui/dist/assets/{index-D2eOzshJ.js → index-BeLxRMCv.js} +1 -1
- package/ui/dist/index.html +1 -1
- package/lib/dist/tests/features/scene-object-chain.test.js +0 -64
- /package/lib/dist/tests/features/{scene-object-chain.test.d.ts → primitive-chain.test.d.ts} +0 -0
package/lib/dist/core/mirror.js
CHANGED
|
@@ -4,84 +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
61
|
context.addSceneObject(mirror);
|
|
72
62
|
return mirror;
|
|
73
63
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (!(args[0] instanceof PlaneObjectBase)) {
|
|
78
|
-
const normalizedPlane = normalizePlane(args[0]);
|
|
79
|
-
planeObj = new PlaneObject(normalizedPlane);
|
|
80
|
-
context.addSceneObject(planeObj);
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
planeObj = args[0];
|
|
64
|
+
let planeArg = args[0];
|
|
65
|
+
if (isStandardAxis(planeArg)) {
|
|
66
|
+
planeArg = axisToPlaneName[planeArg];
|
|
84
67
|
}
|
|
68
|
+
const planeObj = resolvePlane(planeArg, context);
|
|
69
|
+
const targetObjects = args.slice(1);
|
|
85
70
|
const mirror = new MirrorShape(planeObj, targetObjects);
|
|
86
71
|
context.addSceneObject(mirror);
|
|
87
72
|
return mirror;
|
package/lib/dist/core/plane.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { PlaneLike, PlaneTransformOptions } from "../math/plane.js";
|
|
2
2
|
import { IPlane, ISceneObject } from "./interfaces.js";
|
|
3
|
-
export type PlaneRenderableOptions = PlaneTransformOptions
|
|
4
|
-
sticky?: boolean;
|
|
5
|
-
};
|
|
3
|
+
export type PlaneRenderableOptions = PlaneTransformOptions;
|
|
6
4
|
interface PlaneFunction {
|
|
7
5
|
/**
|
|
8
6
|
* Creates a plane from a standard plane or normal vector.
|
|
@@ -12,7 +10,7 @@ interface PlaneFunction {
|
|
|
12
10
|
/**
|
|
13
11
|
* Creates a plane with transform options.
|
|
14
12
|
* @param plane - The standard plane or normal vector
|
|
15
|
-
* @param options - Transform options (offset,
|
|
13
|
+
* @param options - Transform options (offset, rotate, etc.)
|
|
16
14
|
*/
|
|
17
15
|
(plane: PlaneLike, options: PlaneRenderableOptions): IPlane;
|
|
18
16
|
/**
|
|
@@ -29,7 +27,7 @@ interface PlaneFunction {
|
|
|
29
27
|
/**
|
|
30
28
|
* Creates a plane from a face selection with transform options.
|
|
31
29
|
* @param selection - The selected face to create a plane from
|
|
32
|
-
* @param options - Transform options (offset,
|
|
30
|
+
* @param options - Transform options (offset, rotate, etc.)
|
|
33
31
|
*/
|
|
34
32
|
(selection: ISceneObject, options: PlaneRenderableOptions): IPlane;
|
|
35
33
|
/**
|
|
@@ -41,14 +39,14 @@ interface PlaneFunction {
|
|
|
41
39
|
/**
|
|
42
40
|
* Transforms an existing plane with options.
|
|
43
41
|
* @param plane - The existing plane to transform
|
|
44
|
-
* @param options - Transform options (offset,
|
|
42
|
+
* @param options - Transform options (offset, rotate, etc.)
|
|
45
43
|
*/
|
|
46
44
|
(plane: IPlane, options: PlaneRenderableOptions): IPlane;
|
|
47
45
|
/**
|
|
48
46
|
* Creates a plane midway between two standard planes or normal vectors.
|
|
49
47
|
* @param p1 - The first standard plane or normal vector
|
|
50
48
|
* @param p2 - The second standard plane or normal vector
|
|
51
|
-
* @param options - Transform options (offset,
|
|
49
|
+
* @param options - Transform options (offset, rotate, etc.)
|
|
52
50
|
*/
|
|
53
51
|
(p1: PlaneLike, p2: PlaneLike, options?: PlaneRenderableOptions): IPlane;
|
|
54
52
|
/**
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { ISceneObject
|
|
1
|
+
import { ISceneObject } 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[]):
|
|
7
|
+
(...objects: ISceneObject[]): ISceneObject;
|
|
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
|
|
2
|
+
import { ISceneObject } 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[]):
|
|
9
|
+
(angle: number, ...targets: ISceneObject[]): ISceneObject;
|
|
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[]):
|
|
16
|
+
(angle: number, copy: boolean, ...targets: ISceneObject[]): ISceneObject;
|
|
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[]):
|
|
23
|
+
(axis: AxisLike, angle: number, ...targets: ISceneObject[]): ISceneObject;
|
|
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[]):
|
|
31
|
+
(axis: AxisLike, angle: number, copy: boolean, ...targets: ISceneObject[]): ISceneObject;
|
|
32
32
|
}
|
|
33
33
|
declare const _default: RotateFunction;
|
|
34
34
|
export default _default;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ISceneObject
|
|
1
|
+
import { ISceneObject } from "./interfaces.js";
|
|
2
2
|
interface SubtractFunction {
|
|
3
3
|
/**
|
|
4
4
|
* Subtracts the second shape from the first (boolean difference).
|
|
@@ -6,7 +6,7 @@ interface SubtractFunction {
|
|
|
6
6
|
* @param object1 - The base shape
|
|
7
7
|
* @param object2 - The shape to subtract
|
|
8
8
|
*/
|
|
9
|
-
(object1: ISceneObject, object2: ISceneObject):
|
|
9
|
+
(object1: ISceneObject, object2: ISceneObject): ISceneObject;
|
|
10
10
|
}
|
|
11
11
|
declare const _default: SubtractFunction;
|
|
12
12
|
export default _default;
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import { PointLike } from "../math/point.js";
|
|
2
|
-
import { ISceneObject
|
|
2
|
+
import { ISceneObject } from "./interfaces.js";
|
|
3
3
|
interface TranslateFunction {
|
|
4
4
|
/**
|
|
5
5
|
* Translates objects along the X axis.
|
|
6
6
|
* @param x - The X distance
|
|
7
7
|
* @param targets - The objects to translate (defaults to last object)
|
|
8
8
|
*/
|
|
9
|
-
(x: number, ...targets: ISceneObject[]):
|
|
9
|
+
(x: number, ...targets: ISceneObject[]): ISceneObject;
|
|
10
10
|
/**
|
|
11
11
|
* Translates objects along the X axis, optionally making a copy.
|
|
12
12
|
* @param x - The X distance
|
|
13
13
|
* @param copy - Whether to copy instead of move
|
|
14
14
|
* @param targets - The objects to translate (defaults to last object)
|
|
15
15
|
*/
|
|
16
|
-
(x: number, copy: boolean, ...targets: ISceneObject[]):
|
|
16
|
+
(x: number, copy: boolean, ...targets: ISceneObject[]): ISceneObject;
|
|
17
17
|
/**
|
|
18
18
|
* Translates objects along the X and Y axes.
|
|
19
19
|
* @param x - The X distance
|
|
20
20
|
* @param y - The Y distance
|
|
21
21
|
* @param targets - The objects to translate (defaults to last object)
|
|
22
22
|
*/
|
|
23
|
-
(x: number, y: number, ...targets: ISceneObject[]):
|
|
23
|
+
(x: number, y: number, ...targets: ISceneObject[]): ISceneObject;
|
|
24
24
|
/**
|
|
25
25
|
* Translates objects along the X and Y axes, optionally making a copy.
|
|
26
26
|
* @param x - The X distance
|
|
@@ -28,7 +28,7 @@ interface TranslateFunction {
|
|
|
28
28
|
* @param copy - Whether to copy instead of move
|
|
29
29
|
* @param targets - The objects to translate (defaults to last object)
|
|
30
30
|
*/
|
|
31
|
-
(x: number, y: number, copy: boolean, ...targets: ISceneObject[]):
|
|
31
|
+
(x: number, y: number, copy: boolean, ...targets: ISceneObject[]): ISceneObject;
|
|
32
32
|
/**
|
|
33
33
|
* Translates objects along all three axes.
|
|
34
34
|
* @param x - The X distance
|
|
@@ -36,7 +36,7 @@ interface TranslateFunction {
|
|
|
36
36
|
* @param z - The Z distance
|
|
37
37
|
* @param targets - The objects to translate (defaults to last object)
|
|
38
38
|
*/
|
|
39
|
-
(x: number, y: number, z: number, ...targets: ISceneObject[]):
|
|
39
|
+
(x: number, y: number, z: number, ...targets: ISceneObject[]): ISceneObject;
|
|
40
40
|
/**
|
|
41
41
|
* Translates objects along all three axes, optionally making a copy.
|
|
42
42
|
* @param x - The X distance
|
|
@@ -45,20 +45,20 @@ interface TranslateFunction {
|
|
|
45
45
|
* @param copy - Whether to copy instead of move
|
|
46
46
|
* @param targets - The objects to translate (defaults to last object)
|
|
47
47
|
*/
|
|
48
|
-
(x: number, y: number, z: number, copy: boolean, ...targets: ISceneObject[]):
|
|
48
|
+
(x: number, y: number, z: number, copy: boolean, ...targets: ISceneObject[]): ISceneObject;
|
|
49
49
|
/**
|
|
50
50
|
* Translates objects by a point-like offset.
|
|
51
51
|
* @param distance - The offset as a point
|
|
52
52
|
* @param targets - The objects to translate (defaults to last object)
|
|
53
53
|
*/
|
|
54
|
-
(distance: PointLike, ...targets: ISceneObject[]):
|
|
54
|
+
(distance: PointLike, ...targets: ISceneObject[]): ISceneObject;
|
|
55
55
|
/**
|
|
56
56
|
* Translates objects by a point-like offset, optionally making a copy.
|
|
57
57
|
* @param distance - The offset as a point
|
|
58
58
|
* @param copy - Whether to copy instead of move
|
|
59
59
|
* @param targets - The objects to translate (defaults to last object)
|
|
60
60
|
*/
|
|
61
|
-
(distance: PointLike, copy: boolean, ...targets: ISceneObject[]):
|
|
61
|
+
(distance: PointLike, copy: boolean, ...targets: ISceneObject[]): ISceneObject;
|
|
62
62
|
}
|
|
63
63
|
declare const _default: TranslateFunction;
|
|
64
64
|
export default _default;
|
|
@@ -6,8 +6,10 @@ export declare class Slot extends ExtrudableGeometryBase implements ISlot {
|
|
|
6
6
|
distance: number;
|
|
7
7
|
radius: number;
|
|
8
8
|
private _center;
|
|
9
|
+
private _angle;
|
|
9
10
|
constructor(distance: number, radius: number, targetPlane?: PlaneObjectBase);
|
|
10
11
|
centered(value?: boolean): this;
|
|
12
|
+
rotate(angle: number): this;
|
|
11
13
|
build(): void;
|
|
12
14
|
getType(): string;
|
|
13
15
|
getDependencies(): SceneObject[];
|
|
@@ -17,5 +19,6 @@ export declare class Slot extends ExtrudableGeometryBase implements ISlot {
|
|
|
17
19
|
distance: number;
|
|
18
20
|
radius: number;
|
|
19
21
|
centered: boolean;
|
|
22
|
+
angle: number;
|
|
20
23
|
};
|
|
21
24
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Point2D } from "../../math/point.js";
|
|
2
2
|
import { Geometry } from "../../oc/geometry.js";
|
|
3
|
+
import { rad } from "../../helpers/math-helpers.js";
|
|
3
4
|
import { ExtrudableGeometryBase } from "./extrudable-base.js";
|
|
4
5
|
export class Slot extends ExtrudableGeometryBase {
|
|
5
6
|
distance;
|
|
6
7
|
radius;
|
|
7
8
|
_center = false;
|
|
9
|
+
_angle = 0;
|
|
8
10
|
constructor(distance, radius, targetPlane = null) {
|
|
9
11
|
super(targetPlane);
|
|
10
12
|
this.distance = distance;
|
|
@@ -14,6 +16,10 @@ export class Slot extends ExtrudableGeometryBase {
|
|
|
14
16
|
this._center = value;
|
|
15
17
|
return this;
|
|
16
18
|
}
|
|
19
|
+
rotate(angle) {
|
|
20
|
+
this._angle = angle;
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
17
23
|
build() {
|
|
18
24
|
if (this.distance < 0) {
|
|
19
25
|
throw new Error("Slot distance must be positive");
|
|
@@ -24,14 +30,26 @@ export class Slot extends ExtrudableGeometryBase {
|
|
|
24
30
|
? plane.worldToLocal(this.targetPlane.getPlaneCenter())
|
|
25
31
|
: this.getCurrentPosition();
|
|
26
32
|
if (this._center) {
|
|
27
|
-
|
|
33
|
+
const angleRad = rad(this._angle);
|
|
34
|
+
const cos = Math.cos(angleRad);
|
|
35
|
+
const sin = Math.sin(angleRad);
|
|
36
|
+
leftCenter = leftCenter.translate(-this.distance / 2 * cos, -this.distance / 2 * sin);
|
|
28
37
|
}
|
|
29
|
-
const
|
|
38
|
+
const angleRad = rad(this._angle);
|
|
39
|
+
const cos = Math.cos(angleRad);
|
|
40
|
+
const sin = Math.sin(angleRad);
|
|
41
|
+
// Direction along the slot axis
|
|
42
|
+
const dirX = cos;
|
|
43
|
+
const dirY = sin;
|
|
44
|
+
// Perpendicular direction (90 degrees CCW)
|
|
45
|
+
const perpX = -sin;
|
|
46
|
+
const perpY = cos;
|
|
47
|
+
const rightCenter = new Point2D(leftCenter.x + this.distance * dirX, leftCenter.y + this.distance * dirY);
|
|
30
48
|
// Four key points where lines meet arcs
|
|
31
|
-
const topLeft = new Point2D(leftCenter.x, leftCenter.y + this.radius);
|
|
32
|
-
const topRight = new Point2D(rightCenter.x, rightCenter.y + this.radius);
|
|
33
|
-
const bottomRight = new Point2D(rightCenter.x, rightCenter.y - this.radius);
|
|
34
|
-
const bottomLeft = new Point2D(leftCenter.x, leftCenter.y - this.radius);
|
|
49
|
+
const topLeft = new Point2D(leftCenter.x + this.radius * perpX, leftCenter.y + this.radius * perpY);
|
|
50
|
+
const topRight = new Point2D(rightCenter.x + this.radius * perpX, rightCenter.y + this.radius * perpY);
|
|
51
|
+
const bottomRight = new Point2D(rightCenter.x - this.radius * perpX, rightCenter.y - this.radius * perpY);
|
|
52
|
+
const bottomLeft = new Point2D(leftCenter.x - this.radius * perpX, leftCenter.y - this.radius * perpY);
|
|
35
53
|
// Top line: topLeft -> topRight
|
|
36
54
|
const topSegment = Geometry.makeSegment(localToWorld(topLeft), localToWorld(topRight));
|
|
37
55
|
// Right arc: topRight -> bottomRight (CW semicircle around rightCenter)
|
|
@@ -69,6 +87,7 @@ export class Slot extends ExtrudableGeometryBase {
|
|
|
69
87
|
const targetPlane = this.targetPlane ? (remap.get(this.targetPlane) || this.targetPlane) : null;
|
|
70
88
|
const s = new Slot(this.distance, this.radius, targetPlane);
|
|
71
89
|
s.centered(this._center);
|
|
90
|
+
s.rotate(this._angle);
|
|
72
91
|
return s;
|
|
73
92
|
}
|
|
74
93
|
compareTo(other) {
|
|
@@ -86,13 +105,15 @@ export class Slot extends ExtrudableGeometryBase {
|
|
|
86
105
|
}
|
|
87
106
|
return this.distance === other.distance &&
|
|
88
107
|
this.radius === other.radius &&
|
|
89
|
-
this._center === other._center
|
|
108
|
+
this._center === other._center &&
|
|
109
|
+
this._angle === other._angle;
|
|
90
110
|
}
|
|
91
111
|
serialize() {
|
|
92
112
|
return {
|
|
93
113
|
distance: this.distance,
|
|
94
114
|
radius: this.radius,
|
|
95
115
|
centered: this._center,
|
|
116
|
+
angle: this._angle,
|
|
96
117
|
};
|
|
97
118
|
}
|
|
98
119
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare class Cylinder extends
|
|
1
|
+
import { TransformablePrimitive } from "../common/transformable-primitive.js";
|
|
2
|
+
export declare class Cylinder extends TransformablePrimitive {
|
|
3
3
|
radius: number;
|
|
4
4
|
height: number;
|
|
5
5
|
constructor(radius: number, height: number);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TransformablePrimitive } from "../common/transformable-primitive.js";
|
|
2
2
|
import { Primitives } from "../oc/primitives.js";
|
|
3
|
-
export class Cylinder extends
|
|
3
|
+
export class Cylinder extends TransformablePrimitive {
|
|
4
4
|
radius;
|
|
5
5
|
height;
|
|
6
6
|
constructor(radius, height) {
|
|
@@ -23,7 +23,7 @@ export declare class PlaneFromObject extends PlaneObjectBase {
|
|
|
23
23
|
xDirection: import("../math/vector3d.js").Vector3d;
|
|
24
24
|
yDirection: import("../math/vector3d.js").Vector3d;
|
|
25
25
|
normal: import("../math/vector3d.js").Vector3d;
|
|
26
|
-
options:
|
|
26
|
+
options: import("../math/plane.js").PlaneTransformOptions;
|
|
27
27
|
center: any;
|
|
28
28
|
};
|
|
29
29
|
}
|
|
@@ -24,24 +24,29 @@ export class PlaneFromObject extends PlaneObjectBase {
|
|
|
24
24
|
sourceFace = extract.sourceFace;
|
|
25
25
|
}
|
|
26
26
|
this.sourceObject.removeShapes(this);
|
|
27
|
-
if (this.options) {
|
|
28
|
-
plane = plane.transform(this.options);
|
|
29
|
-
}
|
|
30
27
|
if (sourceFace) {
|
|
31
28
|
const bbox = ShapeOps.getBoundingBox(sourceFace.getShape());
|
|
32
29
|
center = new Point(bbox.centerX, bbox.centerY, bbox.centerZ);
|
|
33
30
|
}
|
|
34
|
-
if (
|
|
35
|
-
|
|
31
|
+
if (this.options) {
|
|
32
|
+
// Apply the same transform to the center so the preview face stays on
|
|
33
|
+
// the rotated plane instead of floating at its pre-rotation position.
|
|
34
|
+
const matrix = plane.getTransformMatrix(this.options);
|
|
35
|
+
plane = plane.applyMatrix(matrix);
|
|
36
|
+
if (center) {
|
|
37
|
+
center = center.transform(matrix);
|
|
38
|
+
}
|
|
36
39
|
}
|
|
37
40
|
const transform = context?.getTransform() ?? null;
|
|
38
41
|
if (transform) {
|
|
39
42
|
plane = plane.applyMatrix(transform);
|
|
40
43
|
if (center) {
|
|
41
44
|
center = center.transform(transform);
|
|
42
|
-
this.setState('plane-center', center);
|
|
43
45
|
}
|
|
44
46
|
}
|
|
47
|
+
if (center) {
|
|
48
|
+
this.setState('plane-center', center);
|
|
49
|
+
}
|
|
45
50
|
this.setState('plane', plane);
|
|
46
51
|
const face = FaceOps.planeToFace(plane, center);
|
|
47
52
|
face.markAsMetaShape();
|
|
@@ -13,6 +13,6 @@ export declare class PlaneMiddleRenderable extends PlaneObjectBase {
|
|
|
13
13
|
yDirection: import("../math/vector3d.js").Vector3d;
|
|
14
14
|
normal: import("../math/vector3d.js").Vector3d;
|
|
15
15
|
center: import("../math/point.js").Point;
|
|
16
|
-
options:
|
|
16
|
+
options: import("../math/plane.js").PlaneTransformOptions;
|
|
17
17
|
};
|
|
18
18
|
}
|
|
@@ -16,6 +16,6 @@ export declare class PlaneObject extends PlaneObjectBase {
|
|
|
16
16
|
yDirection: import("../math/vector3d.js").Vector3d;
|
|
17
17
|
normal: import("../math/vector3d.js").Vector3d;
|
|
18
18
|
center: import("../math/point.js").Point;
|
|
19
|
-
options:
|
|
19
|
+
options: import("../math/plane.js").PlaneTransformOptions;
|
|
20
20
|
};
|
|
21
21
|
}
|
|
@@ -14,7 +14,7 @@ export declare class SelectSceneObject extends SceneObject implements ISelect {
|
|
|
14
14
|
private getAllShapes;
|
|
15
15
|
getDependencies(): SceneObject[];
|
|
16
16
|
createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
|
|
17
|
-
|
|
17
|
+
transform(matrix: Matrix4): SelectSceneObject;
|
|
18
18
|
private injectScopeFaces;
|
|
19
19
|
applyFilters(shapes: Shape[], filters: FilterBuilderBase<Shape>[]): Shape[];
|
|
20
20
|
compareTo(other: SelectSceneObject): boolean;
|
|
@@ -63,7 +63,7 @@ export class SelectSceneObject extends SceneObject {
|
|
|
63
63
|
: undefined;
|
|
64
64
|
return new SelectSceneObject(this.filters, remappedConstraint);
|
|
65
65
|
}
|
|
66
|
-
|
|
66
|
+
transform(matrix) {
|
|
67
67
|
const mirroredFilters = this.filters.map(f => f.transform(matrix));
|
|
68
68
|
return new SelectSceneObject(mirroredFilters, this.constraintObject);
|
|
69
69
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare class Sphere extends
|
|
1
|
+
import { TransformablePrimitive } from "../common/transformable-primitive.js";
|
|
2
|
+
export declare class Sphere extends TransformablePrimitive {
|
|
3
3
|
radius: number;
|
|
4
4
|
angle: number;
|
|
5
5
|
constructor(radius: number, angle: number);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TransformablePrimitive } from "../common/transformable-primitive.js";
|
|
2
2
|
import { Primitives } from "../oc/primitives.js";
|
|
3
|
-
export class Sphere extends
|
|
3
|
+
export class Sphere extends TransformablePrimitive {
|
|
4
4
|
radius;
|
|
5
5
|
angle;
|
|
6
6
|
constructor(radius, angle) {
|
package/lib/dist/math/index.d.ts
CHANGED
|
@@ -3,6 +3,6 @@ export { Point, Point2D, PointLike, Point2DLike, isPointLike, isPoint2DLike } fr
|
|
|
3
3
|
export { Quaternion } from "./quaternion.js";
|
|
4
4
|
export { Matrix4 } from "./matrix4.js";
|
|
5
5
|
export { Axis, AxisLike, StandardAxis, AxisTransformOptions, isAxisLike, isStandardAxis, toAxis } from "./axis.js";
|
|
6
|
-
export { Plane, PlaneLike, StandardPlane, PlaneTransformOptions,
|
|
6
|
+
export { Plane, PlaneLike, StandardPlane, PlaneTransformOptions, isPlaneLike, toPlane } from "./plane.js";
|
|
7
7
|
export { CoordinateSystem } from "./coordinate-system.js";
|
|
8
8
|
export { Convert } from "./convert.js";
|
package/lib/dist/math/plane.d.ts
CHANGED
|
@@ -4,13 +4,11 @@ import { Axis, AxisLike } from "./axis.js";
|
|
|
4
4
|
import { Matrix4 } from "./matrix4.js";
|
|
5
5
|
import { PlaneObjectBase } from "../features/plane-renderable-base.js";
|
|
6
6
|
import { IPlane } from "../core/interfaces.js";
|
|
7
|
-
export type RotationSpace = 'local' | 'global';
|
|
8
7
|
export interface PlaneTransformOptions {
|
|
9
8
|
offset?: number;
|
|
10
9
|
rotateX?: number;
|
|
11
10
|
rotateY?: number;
|
|
12
11
|
rotateZ?: number;
|
|
13
|
-
rotationSpace?: RotationSpace;
|
|
14
12
|
}
|
|
15
13
|
export declare class Plane {
|
|
16
14
|
readonly origin: Point;
|
|
@@ -25,6 +23,7 @@ export declare class Plane {
|
|
|
25
23
|
localToWorld(point: Point2D): Point;
|
|
26
24
|
offset(distance: number): Plane;
|
|
27
25
|
transform(options: PlaneTransformOptions): Plane;
|
|
26
|
+
getTransformMatrix(options: PlaneTransformOptions): Matrix4;
|
|
28
27
|
applyMatrix(matrix: Matrix4): Plane;
|
|
29
28
|
translateAlongNormal(distance: number): Plane;
|
|
30
29
|
translate(dx: number, dy: number, dz: number): Plane;
|
package/lib/dist/math/plane.js
CHANGED
|
@@ -36,36 +36,37 @@ export class Plane {
|
|
|
36
36
|
return new Plane(newOrigin, this.xDirection, this.normal);
|
|
37
37
|
}
|
|
38
38
|
transform(options) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
return this.applyMatrix(this.getTransformMatrix(options));
|
|
40
|
+
}
|
|
41
|
+
getTransformMatrix(options) {
|
|
42
|
+
const offset = options.offset || 0;
|
|
43
|
+
const offsetVec = this.normal.multiply(offset);
|
|
44
|
+
const offsetMatrix = offset
|
|
45
|
+
? Matrix4.fromTranslation(offsetVec.x, offsetVec.y, offsetVec.z)
|
|
46
|
+
: Matrix4.identity();
|
|
43
47
|
const hasRotation = options.rotateX || options.rotateY || options.rotateZ;
|
|
44
48
|
if (!hasRotation) {
|
|
45
|
-
return
|
|
49
|
+
return offsetMatrix;
|
|
46
50
|
}
|
|
47
|
-
|
|
48
|
-
//
|
|
49
|
-
const xAxis = useGlobal ? Vector3d.unitX() : result.xDirection;
|
|
50
|
-
const yAxis = useGlobal ? Vector3d.unitY() : result.yDirection;
|
|
51
|
-
const zAxis = useGlobal ? Vector3d.unitZ() : result.normal;
|
|
52
|
-
// Compose all rotations into a single quaternion to avoid gimbal lock
|
|
51
|
+
// Compose all rotations into a single quaternion to avoid gimbal lock.
|
|
52
|
+
// Axes are taken from the current plane (offset doesn't change orientation).
|
|
53
53
|
let q = Quaternion.identity();
|
|
54
54
|
if (options.rotateX) {
|
|
55
|
-
q = q.multiply(Quaternion.fromAxisAngle(
|
|
55
|
+
q = q.multiply(Quaternion.fromAxisAngle(this.xDirection, rad(options.rotateX)));
|
|
56
56
|
}
|
|
57
57
|
if (options.rotateY) {
|
|
58
|
-
q = q.multiply(Quaternion.fromAxisAngle(
|
|
58
|
+
q = q.multiply(Quaternion.fromAxisAngle(this.yDirection, rad(options.rotateY)));
|
|
59
59
|
}
|
|
60
60
|
if (options.rotateZ) {
|
|
61
|
-
q = q.multiply(Quaternion.fromAxisAngle(
|
|
61
|
+
q = q.multiply(Quaternion.fromAxisAngle(this.normal, rad(options.rotateZ)));
|
|
62
62
|
}
|
|
63
|
-
//
|
|
64
|
-
const
|
|
63
|
+
// Rotate around the offset-applied origin (the plane's origin after offset).
|
|
64
|
+
const pivot = this.origin.add(offsetVec);
|
|
65
|
+
const toOrigin = Matrix4.fromTranslation(-pivot.x, -pivot.y, -pivot.z);
|
|
65
66
|
const rotation = Matrix4.fromQuaternion(q);
|
|
66
|
-
const fromOrigin = Matrix4.fromTranslation(
|
|
67
|
-
const
|
|
68
|
-
return
|
|
67
|
+
const fromOrigin = Matrix4.fromTranslation(pivot.x, pivot.y, pivot.z);
|
|
68
|
+
const rotationMatrix = fromOrigin.multiply(rotation).multiply(toOrigin);
|
|
69
|
+
return rotationMatrix.multiply(offsetMatrix);
|
|
69
70
|
}
|
|
70
71
|
applyMatrix(matrix) {
|
|
71
72
|
return new Plane(matrix.transformPoint(this.origin), matrix.transformDirection(this.xDirection), matrix.transformDirection(this.normal), matrix.transformDirection(this.yDirection));
|
|
@@ -97,7 +97,7 @@ describe("cut two distances", () => {
|
|
|
97
97
|
move([25, 25]);
|
|
98
98
|
rect(50, 50);
|
|
99
99
|
});
|
|
100
|
-
cut(20, 10).
|
|
100
|
+
cut(20, 10).scope(e1);
|
|
101
101
|
const scene = render();
|
|
102
102
|
// First box is cut, second box is untouched — 2 shapes
|
|
103
103
|
expect(countShapes(scene)).toBe(2);
|
|
@@ -154,7 +154,7 @@ describe("cut", () => {
|
|
|
154
154
|
move([25, 25]);
|
|
155
155
|
rect(50, 50);
|
|
156
156
|
});
|
|
157
|
-
cut(20).
|
|
157
|
+
cut(20).scope(e1);
|
|
158
158
|
const scene = render();
|
|
159
159
|
// First box is cut (modified), second box is untouched — 2 shapes
|
|
160
160
|
expect(countShapes(scene)).toBe(2);
|