@js-draw/math 1.21.2 → 1.22.0
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/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', () => {
|