@js-draw/math 1.21.3 → 1.22.0
Sign up to get free protection for your applications and to get access to all the features.
- package/build-config.json +1 -1
- package/dist/cjs/Color4.js +2 -2
- package/dist/cjs/Mat33.d.ts +1 -11
- package/dist/cjs/Mat33.js +8 -24
- package/dist/cjs/Vec3.js +9 -7
- package/dist/cjs/shapes/BezierJSWrapper.js +20 -13
- package/dist/cjs/shapes/LineSegment2.js +13 -17
- package/dist/cjs/shapes/Parameterized2DShape.js +1 -1
- package/dist/cjs/shapes/Path.js +49 -47
- package/dist/cjs/shapes/Rect2.js +13 -15
- package/dist/cjs/shapes/Triangle.js +4 -5
- package/dist/cjs/utils/convexHull2Of.js +3 -3
- package/dist/mjs/Color4.mjs +2 -2
- package/dist/mjs/Mat33.d.ts +1 -11
- package/dist/mjs/Mat33.mjs +8 -24
- package/dist/mjs/Vec3.mjs +9 -7
- package/dist/mjs/shapes/BezierJSWrapper.mjs +20 -13
- package/dist/mjs/shapes/LineSegment2.mjs +13 -17
- package/dist/mjs/shapes/Parameterized2DShape.mjs +1 -1
- package/dist/mjs/shapes/Path.mjs +49 -47
- package/dist/mjs/shapes/Rect2.mjs +13 -15
- package/dist/mjs/shapes/Triangle.mjs +4 -5
- package/dist/mjs/utils/convexHull2Of.mjs +3 -3
- package/dist-test/test_imports/test-require.cjs +1 -1
- package/package.json +3 -3
- package/src/Color4.test.ts +16 -21
- package/src/Color4.ts +22 -17
- package/src/Mat33.fromCSSMatrix.test.ts +31 -45
- package/src/Mat33.test.ts +58 -96
- package/src/Mat33.ts +61 -104
- package/src/Vec2.test.ts +3 -3
- package/src/Vec3.test.ts +2 -3
- package/src/Vec3.ts +34 -58
- package/src/lib.ts +0 -2
- package/src/polynomial/solveQuadratic.test.ts +39 -13
- package/src/polynomial/solveQuadratic.ts +5 -6
- package/src/rounding/cleanUpNumber.test.ts +1 -1
- package/src/rounding/constants.ts +1 -3
- package/src/rounding/getLenAfterDecimal.ts +1 -2
- package/src/rounding/lib.ts +1 -2
- package/src/rounding/toRoundedString.test.ts +1 -1
- package/src/rounding/toStringOfSamePrecision.test.ts +1 -2
- package/src/rounding/toStringOfSamePrecision.ts +1 -1
- package/src/shapes/BezierJSWrapper.ts +54 -37
- package/src/shapes/CubicBezier.ts +3 -3
- package/src/shapes/LineSegment2.test.ts +24 -17
- package/src/shapes/LineSegment2.ts +26 -29
- package/src/shapes/Parameterized2DShape.ts +5 -4
- package/src/shapes/Path.fromString.test.ts +5 -5
- package/src/shapes/Path.test.ts +122 -120
- package/src/shapes/Path.toString.test.ts +7 -7
- package/src/shapes/Path.ts +378 -352
- package/src/shapes/PointShape2D.ts +3 -3
- package/src/shapes/QuadraticBezier.test.ts +27 -21
- package/src/shapes/QuadraticBezier.ts +4 -9
- package/src/shapes/Rect2.test.ts +44 -75
- package/src/shapes/Rect2.ts +30 -35
- package/src/shapes/Triangle.test.ts +31 -29
- package/src/shapes/Triangle.ts +17 -18
- package/src/utils/convexHull2Of.test.ts +54 -15
- package/src/utils/convexHull2Of.ts +9 -7
- package/tsconfig.json +1 -3
- package/typedoc.json +2 -2
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@js-draw/math",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.22.0",
|
4
4
|
"description": "A math library for js-draw. ",
|
5
5
|
"types": "./dist/mjs/lib.d.ts",
|
6
6
|
"main": "./dist/cjs/lib.js",
|
@@ -27,7 +27,7 @@
|
|
27
27
|
"bezier-js": "6.1.3"
|
28
28
|
},
|
29
29
|
"devDependencies": {
|
30
|
-
"@js-draw/build-tool": "^1.
|
30
|
+
"@js-draw/build-tool": "^1.22.0",
|
31
31
|
"@types/bezier-js": "4.1.0",
|
32
32
|
"@types/jest": "29.5.5",
|
33
33
|
"@types/jsdom": "21.1.3"
|
@@ -44,5 +44,5 @@
|
|
44
44
|
"svg",
|
45
45
|
"math"
|
46
46
|
],
|
47
|
-
"gitHead": "
|
47
|
+
"gitHead": "c922cf6e44d078133100e01383ba1bacdebe01bd"
|
48
48
|
}
|
package/src/Color4.test.ts
CHANGED
@@ -15,7 +15,7 @@ describe('Color4', () => {
|
|
15
15
|
expect(Color4.fromString('rgb(0, 0, 0)')).objEq(Color4.black);
|
16
16
|
expect(Color4.fromString('rgb ( 255, 0,\t 0)')).objEq(Color4.ofRGBA(1, 0, 0, 1));
|
17
17
|
expect(Color4.fromString('rgba ( 255, 0,\t 0, 0.5)')).objEq(Color4.ofRGBA(1, 0, 0, 0.5));
|
18
|
-
expect(Color4.fromString('rgba( 0, 0, 128, 0)')).objEq(Color4.ofRGBA(0, 0, 128/255, 0));
|
18
|
+
expect(Color4.fromString('rgba( 0, 0, 128, 0)')).objEq(Color4.ofRGBA(0, 0, 128 / 255, 0));
|
19
19
|
});
|
20
20
|
|
21
21
|
it('should parse transparent/none as completely transparent', () => {
|
@@ -29,13 +29,11 @@ describe('Color4', () => {
|
|
29
29
|
});
|
30
30
|
|
31
31
|
it('should mix red and green to get yellow', () => {
|
32
|
-
expect(Color4.ofRGB(1, 0, 0).mix(Color4.ofRGB(0, 1, 0), 0.3)).objEq(
|
33
|
-
Color4.ofRGB(0.7, 0.3, 0)
|
34
|
-
);
|
32
|
+
expect(Color4.ofRGB(1, 0, 0).mix(Color4.ofRGB(0, 1, 0), 0.3)).objEq(Color4.ofRGB(0.7, 0.3, 0));
|
35
33
|
});
|
36
34
|
|
37
35
|
it('should mix red with nothing and get red', () => {
|
38
|
-
expect(Color4.average([
|
36
|
+
expect(Color4.average([Color4.red])).objEq(Color4.red);
|
39
37
|
});
|
40
38
|
|
41
39
|
it('different colors should be different', () => {
|
@@ -47,14 +45,11 @@ describe('Color4', () => {
|
|
47
45
|
it('should correctly convert to hsv', () => {
|
48
46
|
expect(Color4.red.asHSV()).objEq(Vec3.of(0, 1, 1));
|
49
47
|
expect(Color4.ofRGB(0.5, 0.5, 0.5).asHSV()).objEq(Vec3.of(0, 0, 0.5));
|
50
|
-
expect(Color4.ofRGB(0.5, 0.25, 0.5).asHSV()).objEq(Vec3.of(Math.PI * 5 / 3, 0.5, 0.5), 0.1);
|
48
|
+
expect(Color4.ofRGB(0.5, 0.25, 0.5).asHSV()).objEq(Vec3.of((Math.PI * 5) / 3, 0.5, 0.5), 0.1);
|
51
49
|
});
|
52
50
|
|
53
51
|
it('fromHSV(color.asHSV) should return the original color', () => {
|
54
|
-
const testColors = [
|
55
|
-
Color4.red, Color4.green, Color4.blue,
|
56
|
-
Color4.white, Color4.black,
|
57
|
-
];
|
52
|
+
const testColors = [Color4.red, Color4.green, Color4.blue, Color4.white, Color4.black];
|
58
53
|
|
59
54
|
const testWithColor = (color: Color4) => {
|
60
55
|
expect(Color4.fromHSV(...color.asHSV().asArray())).objEq(color);
|
@@ -65,8 +60,8 @@ describe('Color4', () => {
|
|
65
60
|
}
|
66
61
|
|
67
62
|
for (let i = 0; i <= 6; i++) {
|
68
|
-
testWithColor(Color4.fromHSV(i * Math.PI / 7, 0.5, 0.5));
|
69
|
-
testWithColor(Color4.fromHSV(i * Math.PI / 6, 0.5, 0.5));
|
63
|
+
testWithColor(Color4.fromHSV((i * Math.PI) / 7, 0.5, 0.5));
|
64
|
+
testWithColor(Color4.fromHSV((i * Math.PI) / 6, 0.5, 0.5));
|
70
65
|
}
|
71
66
|
});
|
72
67
|
|
@@ -78,17 +73,17 @@ describe('Color4', () => {
|
|
78
73
|
|
79
74
|
it('should return correct contrast ratios', () => {
|
80
75
|
// Expected values from https://webaim.org/resources/contrastchecker/
|
81
|
-
const testCases: [
|
82
|
-
[
|
83
|
-
[
|
84
|
-
[
|
85
|
-
[
|
86
|
-
[
|
87
|
-
[
|
76
|
+
const testCases: [Color4, Color4, number][] = [
|
77
|
+
[Color4.white, Color4.black, 21],
|
78
|
+
[Color4.fromHex('#FF0000'), Color4.black, 5.25],
|
79
|
+
[Color4.fromHex('#FF0000'), Color4.fromHex('#0000FF'), 2.14],
|
80
|
+
[Color4.fromHex('#300000'), Color4.fromHex('#003000'), 1.26],
|
81
|
+
[Color4.fromHex('#300000'), Color4.fromHex('#003000'), 1.26],
|
82
|
+
[Color4.fromHex('#D60000'), Color4.fromHex('#003000'), 2.71],
|
88
83
|
];
|
89
84
|
|
90
|
-
for (const [
|
85
|
+
for (const [colorA, colorB, expectedContrast] of testCases) {
|
91
86
|
expect(Color4.contrastRatio(colorA, colorB)).toBeCloseTo(expectedContrast, 1);
|
92
87
|
}
|
93
88
|
});
|
94
|
-
});
|
89
|
+
});
|
package/src/Color4.ts
CHANGED
@@ -25,9 +25,8 @@ export class Color4 {
|
|
25
25
|
public readonly b: number,
|
26
26
|
|
27
27
|
/** Alpha/transparent component. ${\tt a} \in [0, 1]$. 0 = transparent */
|
28
|
-
public readonly a: number
|
29
|
-
) {
|
30
|
-
}
|
28
|
+
public readonly a: number,
|
29
|
+
) {}
|
31
30
|
|
32
31
|
/**
|
33
32
|
* Create a color from red, green, blue components. The color is fully opaque (`a = 1.0`).
|
@@ -62,7 +61,7 @@ export class Color4 {
|
|
62
61
|
const components = hexString.split('');
|
63
62
|
|
64
63
|
// Convert to RRGGBBAA or RRGGBB format
|
65
|
-
hexString = components.map(component => `${component}0`).join('');
|
64
|
+
hexString = components.map((component) => `${component}0`).join('');
|
66
65
|
}
|
67
66
|
|
68
67
|
if (hexString.length === 6) {
|
@@ -108,14 +107,21 @@ export class Color4 {
|
|
108
107
|
|
109
108
|
if (componentsList.length === 3) {
|
110
109
|
return Color4.ofRGB(
|
111
|
-
componentsList[0] / 255,
|
110
|
+
componentsList[0] / 255,
|
111
|
+
componentsList[1] / 255,
|
112
|
+
componentsList[2] / 255,
|
112
113
|
);
|
113
114
|
} else if (componentsList.length === 4) {
|
114
115
|
return Color4.ofRGBA(
|
115
|
-
componentsList[0] / 255,
|
116
|
+
componentsList[0] / 255,
|
117
|
+
componentsList[1] / 255,
|
118
|
+
componentsList[2] / 255,
|
119
|
+
componentsList[3],
|
116
120
|
);
|
117
121
|
} else {
|
118
|
-
throw new Error(
|
122
|
+
throw new Error(
|
123
|
+
`RGB string, ${text}, has wrong number of components: ${componentsList.length}`,
|
124
|
+
);
|
119
125
|
}
|
120
126
|
}
|
121
127
|
|
@@ -145,7 +151,7 @@ export class Color4 {
|
|
145
151
|
}
|
146
152
|
|
147
153
|
/** @returns true if `this` and `other` are approximately equal. */
|
148
|
-
public eq(other: Color4|null|undefined): boolean {
|
154
|
+
public eq(other: Color4 | null | undefined): boolean {
|
149
155
|
if (other == null) {
|
150
156
|
return false;
|
151
157
|
}
|
@@ -202,7 +208,7 @@ export class Color4 {
|
|
202
208
|
// - https://stackoverflow.com/a/9733420
|
203
209
|
|
204
210
|
// Normalize the components, as per above
|
205
|
-
const components = [
|
211
|
+
const components = [this.r, this.g, this.b].map((component) => {
|
206
212
|
if (component < 0.03928) {
|
207
213
|
return component / 12.92;
|
208
214
|
} else {
|
@@ -358,24 +364,23 @@ export class Color4 {
|
|
358
364
|
|
359
365
|
let rgb;
|
360
366
|
if (huePrime < 1) {
|
361
|
-
rgb = [
|
367
|
+
rgb = [chroma, secondLargestComponent, 0];
|
362
368
|
} else if (huePrime < 2) {
|
363
|
-
rgb = [
|
369
|
+
rgb = [secondLargestComponent, chroma, 0];
|
364
370
|
} else if (huePrime < 3) {
|
365
|
-
rgb = [
|
371
|
+
rgb = [0, chroma, secondLargestComponent];
|
366
372
|
} else if (huePrime < 4) {
|
367
|
-
rgb = [
|
373
|
+
rgb = [0, secondLargestComponent, chroma];
|
368
374
|
} else if (huePrime < 5) {
|
369
|
-
rgb = [
|
375
|
+
rgb = [secondLargestComponent, 0, chroma];
|
370
376
|
} else {
|
371
|
-
rgb = [
|
377
|
+
rgb = [chroma, 0, secondLargestComponent];
|
372
378
|
}
|
373
379
|
|
374
380
|
const adjustment = value - chroma;
|
375
381
|
return Color4.ofRGB(rgb[0] + adjustment, rgb[1] + adjustment, rgb[2] + adjustment);
|
376
382
|
}
|
377
383
|
|
378
|
-
|
379
384
|
/**
|
380
385
|
* Equivalent to `ofRGB(rgb.x, rgb.y, rgb.z)`.
|
381
386
|
*
|
@@ -385,7 +390,7 @@ export class Color4 {
|
|
385
390
|
return Color4.ofRGBA(rgb.x, rgb.y, rgb.z, alpha ?? 1);
|
386
391
|
}
|
387
392
|
|
388
|
-
private hexString: string|null = null;
|
393
|
+
private hexString: string | null = null;
|
389
394
|
|
390
395
|
/**
|
391
396
|
* @returns a hexadecimal color string representation of `this`, in the form `#rrggbbaa`.
|
@@ -9,58 +9,44 @@ describe('Mat33.fromCSSMatrix', () => {
|
|
9
9
|
// ⎣ 0 0 1 ⎦
|
10
10
|
const identity = Mat33.fromCSSMatrix('matrix(1, 0, 0, 1, 0, 0)');
|
11
11
|
expect(identity).objEq(Mat33.identity);
|
12
|
-
expect(Mat33.fromCSSMatrix('matrix(1, 2, 3, 4, 5, 6)')).objEq(
|
13
|
-
1, 3, 5,
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
2, 4, 6,
|
20
|
-
|
21
|
-
))
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
0, 0, 1,
|
26
|
-
)
|
27
|
-
expect(Mat33.fromCSSMatrix('matrix(
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
1.6, .3, 5,
|
34
|
-
2, 4, 6,
|
35
|
-
0, 0, 1,
|
36
|
-
));
|
37
|
-
expect(Mat33.fromCSSMatrix('matrix(1.6,2, .3E-2, 4, 5, 6)')).objEq(new Mat33(
|
38
|
-
1.6, 3e-3, 5,
|
39
|
-
2, 4, 6,
|
40
|
-
0, 0, 1,
|
41
|
-
));
|
42
|
-
expect(Mat33.fromCSSMatrix('matrix(-1, 2e6, 3E-2,-5.123, -6.5e-1, 0.01)')).objEq(new Mat33(
|
43
|
-
-1, 3E-2, -6.5e-1,
|
44
|
-
2e6, -5.123, 0.01,
|
45
|
-
0, 0, 1,
|
46
|
-
));
|
12
|
+
expect(Mat33.fromCSSMatrix('matrix(1, 2, 3, 4, 5, 6)')).objEq(
|
13
|
+
new Mat33(1, 3, 5, 2, 4, 6, 0, 0, 1),
|
14
|
+
);
|
15
|
+
expect(Mat33.fromCSSMatrix('matrix(1e2, 2, 3, 4, 5, 6)')).objEq(
|
16
|
+
new Mat33(1e2, 3, 5, 2, 4, 6, 0, 0, 1),
|
17
|
+
);
|
18
|
+
expect(Mat33.fromCSSMatrix('matrix(1.6, 2, .3, 4, 5, 6)')).objEq(
|
19
|
+
new Mat33(1.6, 0.3, 5, 2, 4, 6, 0, 0, 1),
|
20
|
+
);
|
21
|
+
expect(Mat33.fromCSSMatrix('matrix(-1, 2, 3.E-2, 4, -5.123, -6.5)')).objEq(
|
22
|
+
new Mat33(-1, 0.03, -5.123, 2, 4, -6.5, 0, 0, 1),
|
23
|
+
);
|
24
|
+
expect(Mat33.fromCSSMatrix('matrix(1.6,\n\t2, .3, 4, 5, 6)')).objEq(
|
25
|
+
new Mat33(1.6, 0.3, 5, 2, 4, 6, 0, 0, 1),
|
26
|
+
);
|
27
|
+
expect(Mat33.fromCSSMatrix('matrix(1.6,2, .3E-2, 4, 5, 6)')).objEq(
|
28
|
+
new Mat33(1.6, 3e-3, 5, 2, 4, 6, 0, 0, 1),
|
29
|
+
);
|
30
|
+
expect(Mat33.fromCSSMatrix('matrix(-1, 2e6, 3E-2,-5.123, -6.5e-1, 0.01)')).objEq(
|
31
|
+
new Mat33(-1, 3e-2, -6.5e-1, 2e6, -5.123, 0.01, 0, 0, 1),
|
32
|
+
);
|
47
33
|
});
|
48
34
|
|
49
35
|
it('should convert multi-matrix arguments into a single CSS matrix', () => {
|
50
36
|
const identity = Mat33.fromCSSMatrix('matrix(1, 0, 0, 1, 0, 0) matrix(1, 0, 0, 1, 0, 0)');
|
51
37
|
expect(identity).objEq(Mat33.identity);
|
52
38
|
|
53
|
-
expect(
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
));
|
39
|
+
expect(
|
40
|
+
Mat33.fromCSSMatrix(
|
41
|
+
'matrix(1, 0, 0, 1, 0, 0) matrix(1, 2, 3, 4, 5, 6) matrix(1, 0, 0, 1, 0, 0)',
|
42
|
+
),
|
43
|
+
).objEq(new Mat33(1, 3, 5, 2, 4, 6, 0, 0, 1));
|
58
44
|
|
59
|
-
expect(
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
));
|
45
|
+
expect(
|
46
|
+
Mat33.fromCSSMatrix(
|
47
|
+
'matrix(2,\n\t 0, 0, 2, 0, 0) matrix(1, 2, 3, 4, 5, 6) matrix(1, 0, 0, 1, 0, 0)',
|
48
|
+
),
|
49
|
+
).objEq(new Mat33(2, 6, 10, 4, 8, 12, 0, 0, 1));
|
64
50
|
});
|
65
51
|
|
66
52
|
it('should convert scale()s with a single argument', () => {
|
package/src/Mat33.test.ts
CHANGED
@@ -2,72 +2,40 @@ import Mat33 from './Mat33';
|
|
2
2
|
import { Point2, Vec2 } from './Vec2';
|
3
3
|
import Vec3 from './Vec3';
|
4
4
|
|
5
|
-
|
6
5
|
describe('Mat33 tests', () => {
|
7
6
|
it('equality', () => {
|
8
7
|
expect(Mat33.identity).objEq(Mat33.identity);
|
9
|
-
expect(new Mat33(
|
10
|
-
0.1, 0.
|
11
|
-
0.
|
12
|
-
|
13
|
-
)).objEq(new Mat33(
|
14
|
-
0.2, 0.1, 0.4,
|
15
|
-
0.5, 0.5, 0.7,
|
16
|
-
0.7, 0.8, -0.9
|
17
|
-
), 0.2);
|
8
|
+
expect(new Mat33(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, -0.9)).objEq(
|
9
|
+
new Mat33(0.2, 0.1, 0.4, 0.5, 0.5, 0.7, 0.7, 0.8, -0.9),
|
10
|
+
0.2,
|
11
|
+
);
|
18
12
|
});
|
19
13
|
|
20
14
|
it('transposition', () => {
|
21
15
|
expect(Mat33.identity.transposed()).objEq(Mat33.identity);
|
22
|
-
expect(new Mat33(
|
23
|
-
1, 2, 0,
|
24
|
-
|
25
|
-
0, 1, 0
|
26
|
-
).transposed()).objEq(new Mat33(
|
27
|
-
1, 0, 0,
|
28
|
-
2, 0, 1,
|
29
|
-
0, 0, 0
|
30
|
-
));
|
16
|
+
expect(new Mat33(1, 2, 0, 0, 0, 0, 0, 1, 0).transposed()).objEq(
|
17
|
+
new Mat33(1, 0, 0, 2, 0, 1, 0, 0, 0),
|
18
|
+
);
|
31
19
|
});
|
32
20
|
|
33
21
|
it('multiplication', () => {
|
34
|
-
const M = new Mat33(
|
35
|
-
1, 2, 3,
|
36
|
-
4, 5, 6,
|
37
|
-
7, 8, 9
|
38
|
-
);
|
22
|
+
const M = new Mat33(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
39
23
|
|
40
24
|
expect(Mat33.identity.rightMul(Mat33.identity)).objEq(Mat33.identity);
|
41
25
|
expect(M.rightMul(Mat33.identity)).objEq(M);
|
42
|
-
expect(M.rightMul(new Mat33(
|
43
|
-
1,
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
4, 10, 6,
|
49
|
-
7, 16, 9
|
50
|
-
));
|
51
|
-
expect(M.rightMul(new Mat33(
|
52
|
-
2, 0, 1,
|
53
|
-
0, 1, 0,
|
54
|
-
0, 0, 3
|
55
|
-
))).objEq(new Mat33(
|
56
|
-
2, 2, 10,
|
57
|
-
8, 5, 22,
|
58
|
-
14, 8, 34
|
59
|
-
));
|
26
|
+
expect(M.rightMul(new Mat33(1, 0, 0, 0, 2, 0, 0, 0, 1))).objEq(
|
27
|
+
new Mat33(1, 4, 3, 4, 10, 6, 7, 16, 9),
|
28
|
+
);
|
29
|
+
expect(M.rightMul(new Mat33(2, 0, 1, 0, 1, 0, 0, 0, 3))).objEq(
|
30
|
+
new Mat33(2, 2, 10, 8, 5, 22, 14, 8, 34),
|
31
|
+
);
|
60
32
|
});
|
61
33
|
|
62
34
|
it('the inverse of the identity matrix should be the identity matrix', () => {
|
63
35
|
const fuzz = 0.01;
|
64
36
|
expect(Mat33.identity.inverse()).objEq(Mat33.identity, fuzz);
|
65
37
|
|
66
|
-
const M = new Mat33(
|
67
|
-
1, 2, 3,
|
68
|
-
4, 1, 0,
|
69
|
-
2, 3, 0
|
70
|
-
);
|
38
|
+
const M = new Mat33(1, 2, 3, 4, 1, 0, 2, 3, 0);
|
71
39
|
expect(M.inverse().rightMul(M)).objEq(Mat33.identity, fuzz);
|
72
40
|
});
|
73
41
|
|
@@ -82,12 +50,12 @@ describe('Mat33 tests', () => {
|
|
82
50
|
|
83
51
|
it('z-rotation matricies should preserve the given origin', () => {
|
84
52
|
const testPairs: Array<[number, Vec2]> = [
|
85
|
-
[
|
86
|
-
[
|
87
|
-
[
|
53
|
+
[Math.PI / 2, Vec2.zero],
|
54
|
+
[-Math.PI / 2, Vec2.zero],
|
55
|
+
[-Math.PI / 2, Vec2.of(10, 10)],
|
88
56
|
];
|
89
57
|
|
90
|
-
for (const [
|
58
|
+
for (const [angle, center] of testPairs) {
|
91
59
|
expect(Mat33.zRotation(angle, center).transformVec2(center)).objEq(center);
|
92
60
|
}
|
93
61
|
});
|
@@ -111,11 +79,7 @@ describe('Mat33 tests', () => {
|
|
111
79
|
|
112
80
|
it('calling inverse on singular matricies should result in the identity matrix', () => {
|
113
81
|
const fuzz = 0.001;
|
114
|
-
const singularMat = Mat33.ofRows(
|
115
|
-
Vec3.of(0, 0, 1),
|
116
|
-
Vec3.of(0, 1, 0),
|
117
|
-
Vec3.of(0, 1, 1)
|
118
|
-
);
|
82
|
+
const singularMat = Mat33.ofRows(Vec3.of(0, 0, 1), Vec3.of(0, 1, 0), Vec3.of(0, 1, 1));
|
119
83
|
expect(singularMat.invertable()).toBe(false);
|
120
84
|
expect(singularMat.inverse()).objEq(Mat33.identity, fuzz);
|
121
85
|
});
|
@@ -123,15 +87,19 @@ describe('Mat33 tests', () => {
|
|
123
87
|
it('z-rotation matricies should be invertable', () => {
|
124
88
|
const fuzz = 0.01;
|
125
89
|
const M = Mat33.zRotation(-0.2617993877991494, Vec2.of(481, 329.5));
|
126
|
-
expect(
|
127
|
-
M.inverse().transformVec2(M.transformVec2(Vec2.unitX))
|
128
|
-
).objEq(Vec2.unitX, fuzz);
|
90
|
+
expect(M.inverse().transformVec2(M.transformVec2(Vec2.unitX))).objEq(Vec2.unitX, fuzz);
|
129
91
|
expect(M.invertable());
|
130
92
|
|
131
93
|
const starterTransform = new Mat33(
|
132
|
-
-0.2588190451025205,
|
133
|
-
0.9659258262890688,
|
134
|
-
|
94
|
+
-0.2588190451025205,
|
95
|
+
-0.9659258262890688,
|
96
|
+
923.7645204565603,
|
97
|
+
0.9659258262890688,
|
98
|
+
-0.2588190451025205,
|
99
|
+
-49.829447083761465,
|
100
|
+
0,
|
101
|
+
0,
|
102
|
+
1,
|
135
103
|
);
|
136
104
|
expect(starterTransform.invertable()).toBe(true);
|
137
105
|
|
@@ -139,32 +107,32 @@ describe('Mat33 tests', () => {
|
|
139
107
|
const fullTransformInverse = fullTransform.inverse();
|
140
108
|
expect(fullTransform.invertable()).toBe(true);
|
141
109
|
|
142
|
-
expect(
|
143
|
-
fullTransformInverse.rightMul(fullTransform)
|
144
|
-
).objEq(Mat33.identity, fuzz);
|
110
|
+
expect(fullTransformInverse.rightMul(fullTransform)).objEq(Mat33.identity, fuzz);
|
145
111
|
|
146
|
-
expect(
|
147
|
-
|
148
|
-
|
112
|
+
expect(fullTransform.transformVec2(fullTransformInverse.transformVec2(Vec2.unitX))).objEq(
|
113
|
+
Vec2.unitX,
|
114
|
+
fuzz,
|
115
|
+
);
|
149
116
|
|
150
|
-
expect(
|
151
|
-
|
152
|
-
|
117
|
+
expect(fullTransformInverse.transformVec2(fullTransform.transformVec2(Vec2.unitX))).objEq(
|
118
|
+
Vec2.unitX,
|
119
|
+
fuzz,
|
120
|
+
);
|
153
121
|
});
|
154
122
|
|
155
123
|
it('z-rotation matrix inverses should undo the z-rotation', () => {
|
156
|
-
const testCases: Array<[
|
157
|
-
[
|
158
|
-
[
|
159
|
-
[
|
160
|
-
[
|
161
|
-
[
|
162
|
-
[
|
163
|
-
[
|
124
|
+
const testCases: Array<[number, Point2]> = [
|
125
|
+
[Math.PI / 2, Vec2.zero],
|
126
|
+
[Math.PI, Vec2.of(1, 1)],
|
127
|
+
[-Math.PI, Vec2.of(1, 1)],
|
128
|
+
[-Math.PI * 2, Vec2.of(1, 1)],
|
129
|
+
[-Math.PI * 2, Vec2.of(123, 456)],
|
130
|
+
[-Math.PI / 4, Vec2.of(123, 456)],
|
131
|
+
[0.1, Vec2.of(1, 2)],
|
164
132
|
];
|
165
133
|
|
166
134
|
const fuzz = 0.00001;
|
167
|
-
for (const [
|
135
|
+
for (const [angle, center] of testCases) {
|
168
136
|
const mat = Mat33.zRotation(angle, center);
|
169
137
|
expect(mat.inverse().rightMul(mat)).objEq(Mat33.identity, fuzz);
|
170
138
|
expect(mat.rightMul(mat.inverse())).objEq(Mat33.identity, fuzz);
|
@@ -172,30 +140,24 @@ describe('Mat33 tests', () => {
|
|
172
140
|
});
|
173
141
|
|
174
142
|
it('z-rotation should preserve given origin', () => {
|
175
|
-
const testCases: Array<[
|
176
|
-
[
|
177
|
-
[
|
178
|
-
[
|
179
|
-
[
|
143
|
+
const testCases: Array<[number, Point2]> = [
|
144
|
+
[6.205048847547065, Vec2.of(75.16363373235318, 104.29870408043762)],
|
145
|
+
[1.234, Vec2.of(-56, 789)],
|
146
|
+
[-Math.PI, Vec2.of(-56, 789)],
|
147
|
+
[-Math.PI / 2, Vec2.of(-0.001, 1.0002)],
|
180
148
|
];
|
181
149
|
|
182
150
|
for (const [angle, rotationOrigin] of testCases) {
|
183
|
-
expect(Mat33.zRotation(angle, rotationOrigin).transformVec2(rotationOrigin)).objEq(
|
151
|
+
expect(Mat33.zRotation(angle, rotationOrigin).transformVec2(rotationOrigin)).objEq(
|
152
|
+
rotationOrigin,
|
153
|
+
);
|
184
154
|
}
|
185
155
|
});
|
186
156
|
|
187
157
|
it('should correctly apply a mapping to all components', () => {
|
188
158
|
expect(
|
189
|
-
new Mat33(
|
190
|
-
|
191
|
-
4, 5, 6,
|
192
|
-
7, 8, 9,
|
193
|
-
).mapEntries(component => component - 1)
|
194
|
-
).toMatchObject(new Mat33(
|
195
|
-
0, 1, 2,
|
196
|
-
3, 4, 5,
|
197
|
-
6, 7, 8,
|
198
|
-
));
|
159
|
+
new Mat33(1, 2, 3, 4, 5, 6, 7, 8, 9).mapEntries((component) => component - 1),
|
160
|
+
).toMatchObject(new Mat33(0, 1, 2, 3, 4, 5, 6, 7, 8));
|
199
161
|
});
|
200
162
|
|
201
163
|
it('getColumn should return the given column index', () => {
|