fluidcad 0.0.3 → 0.0.4
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/README.md +2 -2
- package/lib/dist/common/shape-factory.d.ts +1 -1
- package/lib/dist/oc/boolean-ops.d.ts +2 -2
- package/lib/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/lib/dist/constraints/constraint.d.ts +0 -11
- package/lib/dist/constraints/constraint.js +0 -51
- package/lib/dist/constraints/outside.d.ts +0 -3
- package/lib/dist/constraints/outside.js +0 -4
- package/lib/dist/core/2d/aslot.d.ts +0 -12
- package/lib/dist/core/2d/aslot.js +0 -40
- package/lib/dist/core/2d/crect.d.ts +0 -12
- package/lib/dist/core/2d/crect.js +0 -74
- package/lib/dist/core/2d/face-maker.d.ts +0 -13
- package/lib/dist/core/2d/face-maker.js +0 -119
- package/lib/dist/core/2d/face-maker2.d.ts +0 -6
- package/lib/dist/core/2d/face-maker2.js +0 -54
- package/lib/dist/core/region.d.ts +0 -13
- package/lib/dist/core/region.js +0 -18
- package/lib/dist/features/2d/amove.d.ts +0 -14
- package/lib/dist/features/2d/amove.js +0 -33
- package/lib/dist/features/2d/constraints/constraint.d.ts +0 -11
- package/lib/dist/features/2d/constraints/constraint.js +0 -49
- package/lib/dist/features/2d/constraints/outside.d.ts +0 -3
- package/lib/dist/features/2d/constraints/outside.js +0 -4
- package/lib/dist/features/2d/tarc-two-circles.d.ts +0 -18
- package/lib/dist/features/2d/tarc-two-circles.js +0 -61
- package/lib/dist/features/2d/tcircle-three-tan.d.ts +0 -13
- package/lib/dist/features/2d/tcircle-three-tan.js +0 -33
- package/lib/dist/features/2d/tcircle-two-tan.d.ts +0 -13
- package/lib/dist/features/2d/tcircle-two-tan.js +0 -33
- package/lib/dist/features/Extrude.d.ts +0 -1
- package/lib/dist/features/Extrude.js +0 -1
- package/lib/dist/features/cut-base.d.ts +0 -49
- package/lib/dist/features/cut-base.js +0 -312
- package/lib/dist/features/cut-symmetric.d.ts +0 -23
- package/lib/dist/features/cut-symmetric.js +0 -119
- package/lib/dist/features/cut-two-distances.d.ts +0 -24
- package/lib/dist/features/cut-two-distances.js +0 -110
- package/lib/dist/features/cut.d.ts +0 -27
- package/lib/dist/features/cut.js +0 -101
- package/lib/dist/features/extrude-symmetric.d.ts +0 -28
- package/lib/dist/features/extrude-symmetric.js +0 -177
- package/lib/dist/features/region2d.d.ts +0 -25
- package/lib/dist/features/region2d.js +0 -185
- package/lib/dist/features/repeat-circular2d.d.ts +0 -17
- package/lib/dist/features/repeat-circular2d.js +0 -90
- package/lib/dist/features/repeat-linear2d.d.ts +0 -17
- package/lib/dist/features/repeat-linear2d.js +0 -114
- package/lib/dist/features/revolve-options.d.ts +0 -6
- package/lib/dist/features/revolve-options.js +0 -1
- package/lib/dist/features/split.d.ts +0 -14
- package/lib/dist/features/split.js +0 -74
- package/lib/dist/features/state-scene-object.d.ts +0 -15
- package/lib/dist/features/state-scene-object.js +0 -44
- package/lib/dist/features/state-select.d.ts +0 -21
- package/lib/dist/features/state-select.js +0 -73
- package/lib/dist/features/translate2d.d.ts +0 -16
- package/lib/dist/features/translate2d.js +0 -61
- package/lib/dist/filters/all-filter.d.ts +0 -8
- package/lib/dist/filters/all-filter.js +0 -12
- package/lib/dist/filters/near-point-filter.d.ts +0 -11
- package/lib/dist/filters/near-point-filter.js +0 -33
- package/lib/dist/helpers/resolve-filters.d.ts +0 -6
- package/lib/dist/helpers/resolve-filters.js +0 -25
- package/lib/dist/math/axis.test.d.ts +0 -1
- package/lib/dist/math/axis.test.js +0 -287
- package/lib/dist/math/coordinate-system.test.d.ts +0 -1
- package/lib/dist/math/coordinate-system.test.js +0 -308
- package/lib/dist/math/matrix4.test.d.ts +0 -1
- package/lib/dist/math/matrix4.test.js +0 -357
- package/lib/dist/math/plane.test.d.ts +0 -1
- package/lib/dist/math/plane.test.js +0 -398
- package/lib/dist/math/point.test.d.ts +0 -1
- package/lib/dist/math/point.test.js +0 -385
- package/lib/dist/math/quaternion.test.d.ts +0 -1
- package/lib/dist/math/quaternion.test.js +0 -278
- package/lib/dist/math/vector3d.test.d.ts +0 -1
- package/lib/dist/math/vector3d.test.js +0 -276
- package/lib/dist/oc/constraint-resolver.d.ts +0 -7
- package/lib/dist/oc/constraint-resolver.js +0 -31
- package/lib/dist/oc/constraints/curve-constraint-solver.d.ts +0 -1
- package/lib/dist/oc/constraints/curve-constraint-solver.js +0 -2
- package/lib/dist/oc/constraints/geometric-constraint-solver.d.ts +0 -1
- package/lib/dist/oc/constraints/geometric-constraint-solver.js +0 -5
- package/lib/dist/oc/face-maker.d.ts +0 -14
- package/lib/dist/oc/face-maker.js +0 -191
- package/lib/dist/oc/measure.d.ts +0 -21
- package/lib/dist/oc/measure.js +0 -256
- package/lib/dist/oc/tangent-circle-solver.d.ts +0 -17
- package/lib/dist/oc/tangent-circle-solver.js +0 -72
- package/lib/dist/oc/tangent-line-solver.d.ts +0 -17
- package/lib/dist/oc/tangent-line-solver.js +0 -83
- package/lib/dist/oc/tangent-solver.d.ts +0 -14
- package/lib/dist/oc/tangent-solver.js +0 -199
- package/lib/dist/rendering/builder-context.d.ts +0 -16
- package/lib/dist/rendering/builder-context.js +0 -63
- package/lib/dist/tests/extrude.test.d.ts +0 -1
- package/lib/dist/tests/extrude.test.js +0 -48
- package/lib/dist/tests/features/copy.test.d.ts +0 -1
- package/lib/dist/tests/features/copy.test.js +0 -158
- package/lib/dist/tests/features/dispose.test.d.ts +0 -1
- package/lib/dist/tests/features/dispose.test.js +0 -189
- package/lib/dist/tests/features/part-pick.test.d.ts +0 -1
- package/lib/dist/tests/features/part-pick.test.js +0 -73
- package/lib/dist/tests/features/part-repeat.test.d.ts +0 -1
- package/lib/dist/tests/features/part-repeat.test.js +0 -109
- package/server/dist/fluidcad-server.d.ts +0 -32
- package/server/dist/fluidcad-server.js +0 -150
- package/server/dist/index.d.ts +0 -1
- package/server/dist/index.js +0 -290
- package/server/dist/routes/actions.d.ts +0 -3
- package/server/dist/routes/actions.js +0 -100
- package/server/dist/routes/export.d.ts +0 -3
- package/server/dist/routes/export.js +0 -55
- package/server/dist/routes/properties.d.ts +0 -3
- package/server/dist/routes/properties.js +0 -46
- package/server/dist/routes/screenshot.d.ts +0 -2
- package/server/dist/routes/screenshot.js +0 -76
- package/server/dist/vite-manager.d.ts +0 -10
- package/server/dist/vite-manager.js +0 -64
- package/server/dist/ws-protocol.d.ts +0 -138
- package/server/dist/ws-protocol.js +0 -4
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { Axis, toAxis, isAxisLike } from "./axis.js";
|
|
3
|
-
import { Point } from "./point.js";
|
|
4
|
-
import { Vector3d } from "./vector3d.js";
|
|
5
|
-
describe("Axis", () => {
|
|
6
|
-
describe("constructor", () => {
|
|
7
|
-
it("creates axis with origin and direction", () => {
|
|
8
|
-
const origin = new Point(1, 2, 3);
|
|
9
|
-
const direction = new Vector3d(0, 0, 1);
|
|
10
|
-
const axis = new Axis(origin, direction);
|
|
11
|
-
expect(axis.origin.equals(origin)).toBe(true);
|
|
12
|
-
expect(axis.direction.equals(direction)).toBe(true);
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
describe("static axes", () => {
|
|
16
|
-
it("X returns X axis at origin", () => {
|
|
17
|
-
const axis = Axis.X();
|
|
18
|
-
expect(axis.origin.equals(Point.origin())).toBe(true);
|
|
19
|
-
expect(axis.direction.equals(Vector3d.unitX())).toBe(true);
|
|
20
|
-
});
|
|
21
|
-
it("Y returns Y axis at origin", () => {
|
|
22
|
-
const axis = Axis.Y();
|
|
23
|
-
expect(axis.origin.equals(Point.origin())).toBe(true);
|
|
24
|
-
expect(axis.direction.equals(Vector3d.unitY())).toBe(true);
|
|
25
|
-
});
|
|
26
|
-
it("Z returns Z axis at origin", () => {
|
|
27
|
-
const axis = Axis.Z();
|
|
28
|
-
expect(axis.origin.equals(Point.origin())).toBe(true);
|
|
29
|
-
expect(axis.direction.equals(Vector3d.unitZ())).toBe(true);
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
describe("equals", () => {
|
|
33
|
-
it("returns true for identical axes", () => {
|
|
34
|
-
const a1 = new Axis(new Point(1, 2, 3), new Vector3d(0, 0, 1));
|
|
35
|
-
const a2 = new Axis(new Point(1, 2, 3), new Vector3d(0, 0, 1));
|
|
36
|
-
expect(a1.equals(a2)).toBe(true);
|
|
37
|
-
});
|
|
38
|
-
it("returns false for different origin", () => {
|
|
39
|
-
const a1 = new Axis(new Point(1, 2, 3), new Vector3d(0, 0, 1));
|
|
40
|
-
const a2 = new Axis(new Point(1, 2, 4), new Vector3d(0, 0, 1));
|
|
41
|
-
expect(a1.equals(a2)).toBe(false);
|
|
42
|
-
});
|
|
43
|
-
it("returns false for different direction", () => {
|
|
44
|
-
const a1 = new Axis(new Point(1, 2, 3), new Vector3d(0, 0, 1));
|
|
45
|
-
const a2 = new Axis(new Point(1, 2, 3), new Vector3d(0, 1, 0));
|
|
46
|
-
expect(a1.equals(a2)).toBe(false);
|
|
47
|
-
});
|
|
48
|
-
it("supports tolerance", () => {
|
|
49
|
-
const a1 = new Axis(new Point(1, 2, 3), new Vector3d(0, 0, 1));
|
|
50
|
-
const a2 = new Axis(new Point(1.001, 2.001, 3.001), new Vector3d(0, 0, 1));
|
|
51
|
-
expect(a1.equals(a2, 0.01)).toBe(true);
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
describe("translate", () => {
|
|
55
|
-
it("translates origin, keeps direction", () => {
|
|
56
|
-
const axis = Axis.Z();
|
|
57
|
-
const translated = axis.translate(1, 2, 3);
|
|
58
|
-
expect(translated.origin.x).toBe(1);
|
|
59
|
-
expect(translated.origin.y).toBe(2);
|
|
60
|
-
expect(translated.origin.z).toBe(3);
|
|
61
|
-
expect(translated.direction.equals(Vector3d.unitZ())).toBe(true);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
describe("translateVector", () => {
|
|
65
|
-
it("translates by vector", () => {
|
|
66
|
-
const axis = Axis.Z();
|
|
67
|
-
const translated = axis.translateVector(new Vector3d(1, 2, 3));
|
|
68
|
-
expect(translated.origin.x).toBe(1);
|
|
69
|
-
expect(translated.origin.y).toBe(2);
|
|
70
|
-
expect(translated.origin.z).toBe(3);
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
describe("rotateX/Y/Z", () => {
|
|
74
|
-
it("rotateX rotates around world X axis", () => {
|
|
75
|
-
const axis = new Axis(Point.origin(), Vector3d.unitY());
|
|
76
|
-
const rotated = axis.rotateX(Math.PI / 2);
|
|
77
|
-
expect(rotated.direction.x).toBeCloseTo(0);
|
|
78
|
-
expect(rotated.direction.y).toBeCloseTo(0);
|
|
79
|
-
expect(rotated.direction.z).toBeCloseTo(1);
|
|
80
|
-
});
|
|
81
|
-
it("rotateY rotates around world Y axis", () => {
|
|
82
|
-
const axis = new Axis(Point.origin(), Vector3d.unitX());
|
|
83
|
-
const rotated = axis.rotateY(Math.PI / 2);
|
|
84
|
-
expect(rotated.direction.x).toBeCloseTo(0);
|
|
85
|
-
expect(rotated.direction.y).toBeCloseTo(0);
|
|
86
|
-
expect(rotated.direction.z).toBeCloseTo(-1);
|
|
87
|
-
});
|
|
88
|
-
it("rotateZ rotates around world Z axis", () => {
|
|
89
|
-
const axis = new Axis(Point.origin(), Vector3d.unitX());
|
|
90
|
-
const rotated = axis.rotateZ(Math.PI / 2);
|
|
91
|
-
expect(rotated.direction.x).toBeCloseTo(0);
|
|
92
|
-
expect(rotated.direction.y).toBeCloseTo(1);
|
|
93
|
-
expect(rotated.direction.z).toBeCloseTo(0);
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
describe("rotateAroundAxis", () => {
|
|
97
|
-
it("rotates around another axis", () => {
|
|
98
|
-
const axis = new Axis(new Point(1, 0, 0), Vector3d.unitY());
|
|
99
|
-
const rotateAround = Axis.Z();
|
|
100
|
-
const rotated = axis.rotateAroundAxis(rotateAround, Math.PI / 2);
|
|
101
|
-
expect(rotated.origin.x).toBeCloseTo(0);
|
|
102
|
-
expect(rotated.origin.y).toBeCloseTo(1);
|
|
103
|
-
expect(rotated.origin.z).toBeCloseTo(0);
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
describe("transform", () => {
|
|
107
|
-
it("applies offset", () => {
|
|
108
|
-
const axis = Axis.Z();
|
|
109
|
-
const transformed = axis.transform({ offsetX: 1, offsetY: 2, offsetZ: 3 });
|
|
110
|
-
expect(transformed.origin.x).toBe(1);
|
|
111
|
-
expect(transformed.origin.y).toBe(2);
|
|
112
|
-
expect(transformed.origin.z).toBe(3);
|
|
113
|
-
});
|
|
114
|
-
it("applies rotation without gimbal lock", () => {
|
|
115
|
-
const axis = new Axis(Point.origin(), Vector3d.unitX());
|
|
116
|
-
// Apply 90° Y rotation - this would cause gimbal lock with sequential rotations
|
|
117
|
-
const transformed = axis.transform({ rotateY: Math.PI / 2 });
|
|
118
|
-
expect(transformed.direction.x).toBeCloseTo(0);
|
|
119
|
-
expect(transformed.direction.z).toBeCloseTo(-1);
|
|
120
|
-
});
|
|
121
|
-
it("combines offset and rotation", () => {
|
|
122
|
-
const axis = new Axis(Point.origin(), Vector3d.unitX());
|
|
123
|
-
const transformed = axis.transform({
|
|
124
|
-
offsetX: 5,
|
|
125
|
-
rotateZ: Math.PI / 2,
|
|
126
|
-
});
|
|
127
|
-
expect(transformed.origin.x).toBe(5);
|
|
128
|
-
expect(transformed.direction.x).toBeCloseTo(0);
|
|
129
|
-
expect(transformed.direction.y).toBeCloseTo(1);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
describe("isParallelTo", () => {
|
|
133
|
-
it("returns true for parallel axes", () => {
|
|
134
|
-
const a1 = new Axis(new Point(0, 0, 0), Vector3d.unitZ());
|
|
135
|
-
const a2 = new Axis(new Point(5, 5, 0), Vector3d.unitZ());
|
|
136
|
-
expect(a1.isParallelTo(a2)).toBe(true);
|
|
137
|
-
});
|
|
138
|
-
it("returns true for anti-parallel axes", () => {
|
|
139
|
-
const a1 = new Axis(Point.origin(), Vector3d.unitZ());
|
|
140
|
-
const a2 = new Axis(Point.origin(), Vector3d.unitZ().negate());
|
|
141
|
-
expect(a1.isParallelTo(a2)).toBe(true);
|
|
142
|
-
});
|
|
143
|
-
it("returns false for non-parallel axes", () => {
|
|
144
|
-
const a1 = new Axis(Point.origin(), Vector3d.unitZ());
|
|
145
|
-
const a2 = new Axis(Point.origin(), Vector3d.unitX());
|
|
146
|
-
expect(a1.isParallelTo(a2)).toBe(false);
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
describe("isPerpendicularTo", () => {
|
|
150
|
-
it("returns true for perpendicular axes", () => {
|
|
151
|
-
const a1 = Axis.X();
|
|
152
|
-
const a2 = Axis.Y();
|
|
153
|
-
expect(a1.isPerpendicularTo(a2)).toBe(true);
|
|
154
|
-
});
|
|
155
|
-
it("returns false for non-perpendicular axes", () => {
|
|
156
|
-
const a1 = Axis.X();
|
|
157
|
-
const a2 = new Axis(Point.origin(), new Vector3d(1, 1, 0));
|
|
158
|
-
expect(a1.isPerpendicularTo(a2)).toBe(false);
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
describe("distanceToPoint", () => {
|
|
162
|
-
it("returns 0 for point on axis", () => {
|
|
163
|
-
const axis = Axis.Z();
|
|
164
|
-
const point = new Point(0, 0, 5);
|
|
165
|
-
expect(axis.distanceToPoint(point)).toBeCloseTo(0);
|
|
166
|
-
});
|
|
167
|
-
it("returns perpendicular distance", () => {
|
|
168
|
-
const axis = Axis.Z();
|
|
169
|
-
const point = new Point(3, 4, 0);
|
|
170
|
-
expect(axis.distanceToPoint(point)).toBeCloseTo(5);
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
describe("closestPointOnAxis", () => {
|
|
174
|
-
it("returns closest point", () => {
|
|
175
|
-
const axis = Axis.Z();
|
|
176
|
-
const point = new Point(3, 4, 5);
|
|
177
|
-
const closest = axis.closestPointOnAxis(point);
|
|
178
|
-
expect(closest.x).toBeCloseTo(0);
|
|
179
|
-
expect(closest.y).toBeCloseTo(0);
|
|
180
|
-
expect(closest.z).toBeCloseTo(5);
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
describe("pointAtParameter", () => {
|
|
184
|
-
it("returns point at parameter t", () => {
|
|
185
|
-
const axis = new Axis(new Point(1, 0, 0), Vector3d.unitX());
|
|
186
|
-
const p = axis.pointAtParameter(5);
|
|
187
|
-
expect(p.x).toBe(6);
|
|
188
|
-
expect(p.y).toBe(0);
|
|
189
|
-
expect(p.z).toBe(0);
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
describe("reverse", () => {
|
|
193
|
-
it("reverses direction", () => {
|
|
194
|
-
const axis = Axis.Z();
|
|
195
|
-
const reversed = axis.reverse();
|
|
196
|
-
expect(reversed.direction.z).toBe(-1);
|
|
197
|
-
expect(reversed.origin.equals(axis.origin)).toBe(true);
|
|
198
|
-
});
|
|
199
|
-
});
|
|
200
|
-
describe("mirror methods", () => {
|
|
201
|
-
it("mirrorAroundPoint mirrors through point", () => {
|
|
202
|
-
const axis = new Axis(new Point(2, 0, 0), Vector3d.unitZ());
|
|
203
|
-
const mirrored = axis.mirrorAroundPoint(Point.origin());
|
|
204
|
-
expect(mirrored.origin.x).toBeCloseTo(-2);
|
|
205
|
-
});
|
|
206
|
-
it("mirrorAroundPlane mirrors through plane", () => {
|
|
207
|
-
const axis = new Axis(new Point(0, 0, 2), Vector3d.unitZ());
|
|
208
|
-
const mirrored = axis.mirrorAroundPlane(Vector3d.unitZ(), Point.origin());
|
|
209
|
-
expect(mirrored.origin.z).toBeCloseTo(-2);
|
|
210
|
-
expect(mirrored.direction.z).toBeCloseTo(-1);
|
|
211
|
-
});
|
|
212
|
-
it("mirrorAroundAxis mirrors through axis", () => {
|
|
213
|
-
const axis = new Axis(new Point(2, 0, 0), Vector3d.unitY());
|
|
214
|
-
const mirrorAxis = Axis.Z();
|
|
215
|
-
const mirrored = axis.mirrorAroundAxis(mirrorAxis);
|
|
216
|
-
expect(mirrored.origin.x).toBeCloseTo(-2);
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
describe("fromPoints", () => {
|
|
220
|
-
it("creates axis from two points", () => {
|
|
221
|
-
const start = new Point(0, 0, 0);
|
|
222
|
-
const end = new Point(0, 0, 5);
|
|
223
|
-
const axis = Axis.fromPoints(start, end);
|
|
224
|
-
expect(axis.origin.equals(start)).toBe(true);
|
|
225
|
-
expect(axis.direction.equals(Vector3d.unitZ())).toBe(true);
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
describe("serialize/deserialize", () => {
|
|
229
|
-
it("serializes to object", () => {
|
|
230
|
-
const axis = new Axis(new Point(1, 2, 3), new Vector3d(0, 0, 1));
|
|
231
|
-
const data = axis.serialize();
|
|
232
|
-
expect(data.origin).toEqual({ x: 1, y: 2, z: 3 });
|
|
233
|
-
expect(data.direction).toEqual({ x: 0, y: 0, z: 1 });
|
|
234
|
-
});
|
|
235
|
-
it("deserializes from object", () => {
|
|
236
|
-
const data = {
|
|
237
|
-
origin: { x: 1, y: 2, z: 3 },
|
|
238
|
-
direction: { x: 0, y: 0, z: 1 },
|
|
239
|
-
};
|
|
240
|
-
const axis = Axis.deserialize(data);
|
|
241
|
-
expect(axis.origin.x).toBe(1);
|
|
242
|
-
expect(axis.direction.z).toBe(1);
|
|
243
|
-
});
|
|
244
|
-
});
|
|
245
|
-
describe("clone", () => {
|
|
246
|
-
it("creates independent copy", () => {
|
|
247
|
-
const axis = new Axis(new Point(1, 2, 3), Vector3d.unitZ());
|
|
248
|
-
const clone = axis.clone();
|
|
249
|
-
expect(clone.equals(axis)).toBe(true);
|
|
250
|
-
expect(clone).not.toBe(axis);
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
});
|
|
254
|
-
describe("helper functions", () => {
|
|
255
|
-
describe("toAxis", () => {
|
|
256
|
-
it("returns same instance for Axis", () => {
|
|
257
|
-
const axis = Axis.Z();
|
|
258
|
-
expect(toAxis(axis)).toBe(axis);
|
|
259
|
-
});
|
|
260
|
-
it("converts 'x' to X axis", () => {
|
|
261
|
-
const axis = toAxis("x");
|
|
262
|
-
expect(axis.direction.equals(Vector3d.unitX())).toBe(true);
|
|
263
|
-
});
|
|
264
|
-
it("converts 'y' to Y axis", () => {
|
|
265
|
-
const axis = toAxis("y");
|
|
266
|
-
expect(axis.direction.equals(Vector3d.unitY())).toBe(true);
|
|
267
|
-
});
|
|
268
|
-
it("converts 'z' to Z axis", () => {
|
|
269
|
-
const axis = toAxis("z");
|
|
270
|
-
expect(axis.direction.equals(Vector3d.unitZ())).toBe(true);
|
|
271
|
-
});
|
|
272
|
-
});
|
|
273
|
-
describe("isAxisLike", () => {
|
|
274
|
-
it("returns true for Axis", () => {
|
|
275
|
-
expect(isAxisLike(Axis.Z())).toBe(true);
|
|
276
|
-
});
|
|
277
|
-
it("returns true for 'x', 'y', 'z'", () => {
|
|
278
|
-
expect(isAxisLike("x")).toBe(true);
|
|
279
|
-
expect(isAxisLike("y")).toBe(true);
|
|
280
|
-
expect(isAxisLike("z")).toBe(true);
|
|
281
|
-
});
|
|
282
|
-
it("returns false for other values", () => {
|
|
283
|
-
expect(isAxisLike("w")).toBe(false);
|
|
284
|
-
expect(isAxisLike(123)).toBe(false);
|
|
285
|
-
});
|
|
286
|
-
});
|
|
287
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { CoordinateSystem } from "./coordinate-system.js";
|
|
3
|
-
import { Point } from "./point.js";
|
|
4
|
-
import { Vector3d } from "./vector3d.js";
|
|
5
|
-
import { Axis } from "./axis.js";
|
|
6
|
-
import { Plane } from "./plane.js";
|
|
7
|
-
describe("CoordinateSystem", () => {
|
|
8
|
-
describe("constructor", () => {
|
|
9
|
-
it("creates coordinate system with origin, mainDirection, xDirection", () => {
|
|
10
|
-
const origin = new Point(1, 2, 3);
|
|
11
|
-
const mainDir = Vector3d.unitZ();
|
|
12
|
-
const xDir = Vector3d.unitX();
|
|
13
|
-
const cs = new CoordinateSystem(origin, mainDir, xDir);
|
|
14
|
-
expect(cs.origin.equals(origin)).toBe(true);
|
|
15
|
-
expect(cs.mainDirection.equals(mainDir)).toBe(true);
|
|
16
|
-
expect(cs.xDirection.equals(xDir)).toBe(true);
|
|
17
|
-
});
|
|
18
|
-
it("computes yDirection automatically", () => {
|
|
19
|
-
const cs = CoordinateSystem.World();
|
|
20
|
-
expect(cs.yDirection.x).toBeCloseTo(0);
|
|
21
|
-
expect(cs.yDirection.y).toBeCloseTo(1);
|
|
22
|
-
expect(cs.yDirection.z).toBeCloseTo(0);
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
describe("World", () => {
|
|
26
|
-
it("returns world coordinate system", () => {
|
|
27
|
-
const world = CoordinateSystem.World();
|
|
28
|
-
expect(world.origin.equals(Point.origin())).toBe(true);
|
|
29
|
-
expect(world.mainDirection.equals(Vector3d.unitZ())).toBe(true);
|
|
30
|
-
expect(world.xDirection.equals(Vector3d.unitX())).toBe(true);
|
|
31
|
-
});
|
|
32
|
-
it("returns same instance", () => {
|
|
33
|
-
const w1 = CoordinateSystem.World();
|
|
34
|
-
const w2 = CoordinateSystem.World();
|
|
35
|
-
expect(w1).toBe(w2);
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
describe("axes", () => {
|
|
39
|
-
it("xAxis returns axis along X direction", () => {
|
|
40
|
-
const cs = CoordinateSystem.World();
|
|
41
|
-
const axis = cs.xAxis;
|
|
42
|
-
expect(axis.origin.equals(cs.origin)).toBe(true);
|
|
43
|
-
expect(axis.direction.equals(cs.xDirection)).toBe(true);
|
|
44
|
-
});
|
|
45
|
-
it("yAxis returns axis along Y direction", () => {
|
|
46
|
-
const cs = CoordinateSystem.World();
|
|
47
|
-
const axis = cs.yAxis;
|
|
48
|
-
expect(axis.direction.equals(cs.yDirection)).toBe(true);
|
|
49
|
-
});
|
|
50
|
-
it("mainAxis returns axis along main direction", () => {
|
|
51
|
-
const cs = CoordinateSystem.World();
|
|
52
|
-
const axis = cs.mainAxis;
|
|
53
|
-
expect(axis.direction.equals(cs.mainDirection)).toBe(true);
|
|
54
|
-
});
|
|
55
|
-
it("zAxis is same as mainAxis", () => {
|
|
56
|
-
const cs = CoordinateSystem.World();
|
|
57
|
-
expect(cs.zAxis.direction.equals(cs.mainAxis.direction)).toBe(true);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
describe("angle", () => {
|
|
61
|
-
it("returns 0 for same orientation", () => {
|
|
62
|
-
const cs1 = CoordinateSystem.World();
|
|
63
|
-
const cs2 = new CoordinateSystem(new Point(5, 5, 5), Vector3d.unitZ(), Vector3d.unitX());
|
|
64
|
-
expect(cs1.angle(cs2)).toBeCloseTo(0);
|
|
65
|
-
});
|
|
66
|
-
it("returns PI/2 for perpendicular", () => {
|
|
67
|
-
const cs1 = CoordinateSystem.World();
|
|
68
|
-
const cs2 = new CoordinateSystem(Point.origin(), Vector3d.unitX(), Vector3d.unitY());
|
|
69
|
-
expect(cs1.angle(cs2)).toBeCloseTo(Math.PI / 2);
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
describe("isCoplanar", () => {
|
|
73
|
-
it("returns true for coplanar systems", () => {
|
|
74
|
-
const cs1 = CoordinateSystem.World();
|
|
75
|
-
const cs2 = new CoordinateSystem(new Point(5, 5, 0), Vector3d.unitZ(), Vector3d.unitX());
|
|
76
|
-
expect(cs1.isCoplanar(cs2)).toBe(true);
|
|
77
|
-
});
|
|
78
|
-
it("returns false for non-coplanar systems", () => {
|
|
79
|
-
const cs1 = CoordinateSystem.World();
|
|
80
|
-
const cs2 = new CoordinateSystem(new Point(0, 0, 10), Vector3d.unitZ(), Vector3d.unitX());
|
|
81
|
-
expect(cs1.isCoplanar(cs2)).toBe(false);
|
|
82
|
-
});
|
|
83
|
-
it("returns false for different orientations", () => {
|
|
84
|
-
const cs1 = CoordinateSystem.World();
|
|
85
|
-
const cs2 = new CoordinateSystem(Point.origin(), Vector3d.unitX(), Vector3d.unitY());
|
|
86
|
-
expect(cs1.isCoplanar(cs2)).toBe(false);
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
describe("translate", () => {
|
|
90
|
-
it("translates origin, keeps orientation", () => {
|
|
91
|
-
const cs = CoordinateSystem.World();
|
|
92
|
-
const translated = cs.translate(1, 2, 3);
|
|
93
|
-
expect(translated.origin.x).toBe(1);
|
|
94
|
-
expect(translated.origin.y).toBe(2);
|
|
95
|
-
expect(translated.origin.z).toBe(3);
|
|
96
|
-
expect(translated.mainDirection.equals(cs.mainDirection)).toBe(true);
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
describe("translateVector", () => {
|
|
100
|
-
it("translates by vector", () => {
|
|
101
|
-
const cs = CoordinateSystem.World();
|
|
102
|
-
const translated = cs.translateVector(new Vector3d(5, 10, 15));
|
|
103
|
-
expect(translated.origin.x).toBe(5);
|
|
104
|
-
expect(translated.origin.y).toBe(10);
|
|
105
|
-
expect(translated.origin.z).toBe(15);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
describe("rotate", () => {
|
|
109
|
-
it("rotates around axis", () => {
|
|
110
|
-
const cs = CoordinateSystem.World();
|
|
111
|
-
const rotated = cs.rotate(Axis.Z(), Math.PI / 2);
|
|
112
|
-
expect(rotated.xDirection.x).toBeCloseTo(0);
|
|
113
|
-
expect(rotated.xDirection.y).toBeCloseTo(1);
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
describe("scale", () => {
|
|
117
|
-
it("scales origin distance from point", () => {
|
|
118
|
-
const cs = new CoordinateSystem(new Point(2, 0, 0), Vector3d.unitZ(), Vector3d.unitX());
|
|
119
|
-
const scaled = cs.scale(Point.origin(), 2);
|
|
120
|
-
expect(scaled.origin.x).toBeCloseTo(4);
|
|
121
|
-
// Direction should not change
|
|
122
|
-
expect(scaled.mainDirection.equals(cs.mainDirection)).toBe(true);
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
describe("mirror methods", () => {
|
|
126
|
-
it("mirrorAroundPoint mirrors through point", () => {
|
|
127
|
-
const cs = new CoordinateSystem(new Point(2, 0, 0), Vector3d.unitZ(), Vector3d.unitX());
|
|
128
|
-
const mirrored = cs.mirrorAroundPoint(Point.origin());
|
|
129
|
-
expect(mirrored.origin.x).toBeCloseTo(-2);
|
|
130
|
-
});
|
|
131
|
-
it("mirrorAroundAxis mirrors through axis", () => {
|
|
132
|
-
const cs = new CoordinateSystem(new Point(2, 0, 0), Vector3d.unitZ(), Vector3d.unitX());
|
|
133
|
-
const mirrored = cs.mirrorAroundAxis(Axis.Z());
|
|
134
|
-
expect(mirrored.origin.x).toBeCloseTo(-2);
|
|
135
|
-
});
|
|
136
|
-
it("mirrorAroundPlane mirrors through plane", () => {
|
|
137
|
-
const cs = new CoordinateSystem(new Point(0, 0, 5), Vector3d.unitZ(), Vector3d.unitX());
|
|
138
|
-
const mirrored = cs.mirrorAroundPlane(Vector3d.unitZ(), Point.origin());
|
|
139
|
-
expect(mirrored.origin.z).toBeCloseTo(-5);
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
describe("getXYPlane", () => {
|
|
143
|
-
it("returns XY plane of coordinate system", () => {
|
|
144
|
-
const cs = CoordinateSystem.World();
|
|
145
|
-
const plane = cs.getXYPlane();
|
|
146
|
-
expect(plane.origin.equals(cs.origin)).toBe(true);
|
|
147
|
-
expect(plane.normal.equals(cs.mainDirection)).toBe(true);
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
describe("getXZPlane", () => {
|
|
151
|
-
it("returns XZ plane of coordinate system", () => {
|
|
152
|
-
const cs = CoordinateSystem.World();
|
|
153
|
-
const plane = cs.getXZPlane();
|
|
154
|
-
expect(plane.origin.equals(cs.origin)).toBe(true);
|
|
155
|
-
expect(plane.xDirection.equals(cs.xDirection)).toBe(true);
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
describe("getYZPlane", () => {
|
|
159
|
-
it("returns YZ plane of coordinate system", () => {
|
|
160
|
-
const cs = CoordinateSystem.World();
|
|
161
|
-
const plane = cs.getYZPlane();
|
|
162
|
-
expect(plane.origin.equals(cs.origin)).toBe(true);
|
|
163
|
-
expect(plane.xDirection.equals(cs.yDirection)).toBe(true);
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
describe("worldToLocal", () => {
|
|
167
|
-
it("converts world point to local coordinates", () => {
|
|
168
|
-
const cs = CoordinateSystem.World();
|
|
169
|
-
const world = new Point(3, 4, 5);
|
|
170
|
-
const local = cs.worldToLocal(world);
|
|
171
|
-
expect(local.x).toBeCloseTo(3);
|
|
172
|
-
expect(local.y).toBeCloseTo(4);
|
|
173
|
-
expect(local.z).toBeCloseTo(5);
|
|
174
|
-
});
|
|
175
|
-
it("handles offset origin", () => {
|
|
176
|
-
const cs = new CoordinateSystem(new Point(10, 20, 30), Vector3d.unitZ(), Vector3d.unitX());
|
|
177
|
-
const world = new Point(15, 25, 35);
|
|
178
|
-
const local = cs.worldToLocal(world);
|
|
179
|
-
expect(local.x).toBeCloseTo(5);
|
|
180
|
-
expect(local.y).toBeCloseTo(5);
|
|
181
|
-
expect(local.z).toBeCloseTo(5);
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
describe("localToWorld", () => {
|
|
185
|
-
it("converts local coordinates to world point", () => {
|
|
186
|
-
const cs = CoordinateSystem.World();
|
|
187
|
-
const local = new Point(3, 4, 5);
|
|
188
|
-
const world = cs.localToWorld(local);
|
|
189
|
-
expect(world.x).toBeCloseTo(3);
|
|
190
|
-
expect(world.y).toBeCloseTo(4);
|
|
191
|
-
expect(world.z).toBeCloseTo(5);
|
|
192
|
-
});
|
|
193
|
-
it("handles offset origin", () => {
|
|
194
|
-
const cs = new CoordinateSystem(new Point(10, 20, 30), Vector3d.unitZ(), Vector3d.unitX());
|
|
195
|
-
const local = new Point(5, 5, 5);
|
|
196
|
-
const world = cs.localToWorld(local);
|
|
197
|
-
expect(world.x).toBeCloseTo(15);
|
|
198
|
-
expect(world.y).toBeCloseTo(25);
|
|
199
|
-
expect(world.z).toBeCloseTo(35);
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
describe("worldToLocal and localToWorld roundtrip", () => {
|
|
203
|
-
it("roundtrip returns original point", () => {
|
|
204
|
-
const cs = new CoordinateSystem(new Point(10, 20, 30), new Vector3d(0, 0, 1), new Vector3d(1, 0, 0));
|
|
205
|
-
const original = new Point(50, 60, 70);
|
|
206
|
-
const local = cs.worldToLocal(original);
|
|
207
|
-
const back = cs.localToWorld(local);
|
|
208
|
-
expect(back.x).toBeCloseTo(original.x);
|
|
209
|
-
expect(back.y).toBeCloseTo(original.y);
|
|
210
|
-
expect(back.z).toBeCloseTo(original.z);
|
|
211
|
-
});
|
|
212
|
-
it("roundtrip works with rotated system", () => {
|
|
213
|
-
const cs = new CoordinateSystem(Point.origin(), new Vector3d(1, 0, 0), new Vector3d(0, 1, 0));
|
|
214
|
-
const local = new Point(3, 4, 5);
|
|
215
|
-
const world = cs.localToWorld(local);
|
|
216
|
-
const backToLocal = cs.worldToLocal(world);
|
|
217
|
-
expect(backToLocal.x).toBeCloseTo(local.x);
|
|
218
|
-
expect(backToLocal.y).toBeCloseTo(local.y);
|
|
219
|
-
expect(backToLocal.z).toBeCloseTo(local.z);
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
describe("worldToLocalVector", () => {
|
|
223
|
-
it("converts world vector to local coordinates", () => {
|
|
224
|
-
const cs = CoordinateSystem.World();
|
|
225
|
-
const world = new Vector3d(1, 0, 0);
|
|
226
|
-
const local = cs.worldToLocalVector(world);
|
|
227
|
-
expect(local.x).toBeCloseTo(1);
|
|
228
|
-
expect(local.y).toBeCloseTo(0);
|
|
229
|
-
expect(local.z).toBeCloseTo(0);
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
describe("localToWorldVector", () => {
|
|
233
|
-
it("converts local vector to world coordinates", () => {
|
|
234
|
-
const cs = CoordinateSystem.World();
|
|
235
|
-
const local = new Vector3d(1, 0, 0);
|
|
236
|
-
const world = cs.localToWorldVector(local);
|
|
237
|
-
expect(world.x).toBeCloseTo(1);
|
|
238
|
-
expect(world.y).toBeCloseTo(0);
|
|
239
|
-
expect(world.z).toBeCloseTo(0);
|
|
240
|
-
});
|
|
241
|
-
});
|
|
242
|
-
describe("getBasisMatrix", () => {
|
|
243
|
-
it("returns basis transformation matrix", () => {
|
|
244
|
-
const cs = CoordinateSystem.World();
|
|
245
|
-
const matrix = cs.getBasisMatrix();
|
|
246
|
-
const p = matrix.transformPoint(new Point(1, 0, 0));
|
|
247
|
-
expect(p.x).toBeCloseTo(1);
|
|
248
|
-
expect(p.y).toBeCloseTo(0);
|
|
249
|
-
expect(p.z).toBeCloseTo(0);
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
describe("getInverseBasisMatrix", () => {
|
|
253
|
-
it("returns inverse basis matrix", () => {
|
|
254
|
-
const cs = CoordinateSystem.World();
|
|
255
|
-
const matrix = cs.getBasisMatrix();
|
|
256
|
-
const inverse = cs.getInverseBasisMatrix();
|
|
257
|
-
const result = matrix.multiply(inverse);
|
|
258
|
-
// Should be identity
|
|
259
|
-
expect(result.get(0, 0)).toBeCloseTo(1);
|
|
260
|
-
expect(result.get(1, 1)).toBeCloseTo(1);
|
|
261
|
-
expect(result.get(2, 2)).toBeCloseTo(1);
|
|
262
|
-
});
|
|
263
|
-
});
|
|
264
|
-
describe("equals", () => {
|
|
265
|
-
it("returns true for identical systems", () => {
|
|
266
|
-
const cs1 = CoordinateSystem.World();
|
|
267
|
-
const cs2 = new CoordinateSystem(Point.origin(), Vector3d.unitZ(), Vector3d.unitX());
|
|
268
|
-
expect(cs1.equals(cs2)).toBe(true);
|
|
269
|
-
});
|
|
270
|
-
it("returns false for different systems", () => {
|
|
271
|
-
const cs1 = CoordinateSystem.World();
|
|
272
|
-
const cs2 = new CoordinateSystem(new Point(1, 0, 0), Vector3d.unitZ(), Vector3d.unitX());
|
|
273
|
-
expect(cs1.equals(cs2)).toBe(false);
|
|
274
|
-
});
|
|
275
|
-
it("supports tolerance", () => {
|
|
276
|
-
const cs1 = CoordinateSystem.World();
|
|
277
|
-
const cs2 = new CoordinateSystem(new Point(0.001, 0, 0), Vector3d.unitZ(), Vector3d.unitX());
|
|
278
|
-
expect(cs1.equals(cs2, 0.01)).toBe(true);
|
|
279
|
-
});
|
|
280
|
-
});
|
|
281
|
-
describe("fromPlane", () => {
|
|
282
|
-
it("creates coordinate system from plane", () => {
|
|
283
|
-
const plane = Plane.XY();
|
|
284
|
-
const cs = CoordinateSystem.fromPlane(plane);
|
|
285
|
-
expect(cs.origin.equals(plane.origin)).toBe(true);
|
|
286
|
-
expect(cs.mainDirection.equals(plane.normal)).toBe(true);
|
|
287
|
-
expect(cs.xDirection.equals(plane.xDirection)).toBe(true);
|
|
288
|
-
});
|
|
289
|
-
it("creates from plane string", () => {
|
|
290
|
-
const cs = CoordinateSystem.fromPlane("xy");
|
|
291
|
-
expect(cs.mainDirection.z).toBeCloseTo(1);
|
|
292
|
-
});
|
|
293
|
-
});
|
|
294
|
-
describe("fromTwoAxes", () => {
|
|
295
|
-
it("creates coordinate system from two axes", () => {
|
|
296
|
-
const cs = CoordinateSystem.fromTwoAxes(Point.origin(), Vector3d.unitZ(), Vector3d.unitX());
|
|
297
|
-
expect(cs.mainDirection.z).toBeCloseTo(1);
|
|
298
|
-
});
|
|
299
|
-
});
|
|
300
|
-
describe("clone", () => {
|
|
301
|
-
it("creates independent copy", () => {
|
|
302
|
-
const cs = CoordinateSystem.World();
|
|
303
|
-
const clone = cs.clone();
|
|
304
|
-
expect(clone.equals(cs)).toBe(true);
|
|
305
|
-
expect(clone).not.toBe(cs);
|
|
306
|
-
});
|
|
307
|
-
});
|
|
308
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|