@js-draw/math 1.21.3 → 1.23.1
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.d.ts +24 -1
- package/dist/cjs/Color4.js +35 -3
- package/dist/cjs/Mat33.d.ts +21 -11
- package/dist/cjs/Mat33.js +28 -24
- package/dist/cjs/Vec3.d.ts +12 -3
- package/dist/cjs/Vec3.js +20 -9
- package/dist/cjs/lib.d.ts +3 -0
- package/dist/cjs/lib.js +3 -0
- package/dist/cjs/shapes/BezierJSWrapper.d.ts +2 -0
- package/dist/cjs/shapes/BezierJSWrapper.js +22 -13
- package/dist/cjs/shapes/LineSegment2.js +13 -17
- package/dist/cjs/shapes/Parameterized2DShape.js +1 -1
- package/dist/cjs/shapes/Path.d.ts +1 -0
- package/dist/cjs/shapes/Path.js +50 -47
- package/dist/cjs/shapes/QuadraticBezier.d.ts +19 -2
- package/dist/cjs/shapes/QuadraticBezier.js +26 -3
- package/dist/cjs/shapes/Rect2.d.ts +13 -0
- package/dist/cjs/shapes/Rect2.js +35 -16
- package/dist/cjs/shapes/Triangle.js +4 -5
- package/dist/cjs/utils/convexHull2Of.js +3 -3
- package/dist/mjs/Color4.d.ts +24 -1
- package/dist/mjs/Color4.mjs +35 -3
- package/dist/mjs/Mat33.d.ts +21 -11
- package/dist/mjs/Mat33.mjs +28 -24
- package/dist/mjs/Vec3.d.ts +12 -3
- package/dist/mjs/Vec3.mjs +20 -9
- package/dist/mjs/lib.d.ts +3 -0
- package/dist/mjs/lib.mjs +3 -0
- package/dist/mjs/shapes/BezierJSWrapper.d.ts +2 -0
- package/dist/mjs/shapes/BezierJSWrapper.mjs +22 -13
- package/dist/mjs/shapes/LineSegment2.mjs +13 -17
- package/dist/mjs/shapes/Parameterized2DShape.mjs +1 -1
- package/dist/mjs/shapes/Path.d.ts +1 -0
- package/dist/mjs/shapes/Path.mjs +50 -47
- package/dist/mjs/shapes/QuadraticBezier.d.ts +19 -2
- package/dist/mjs/shapes/QuadraticBezier.mjs +26 -3
- package/dist/mjs/shapes/Rect2.d.ts +13 -0
- package/dist/mjs/shapes/Rect2.mjs +35 -16
- 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 +21 -21
- package/src/Color4.ts +61 -18
- package/src/Mat33.fromCSSMatrix.test.ts +32 -46
- package/src/Mat33.test.ts +64 -102
- package/src/Mat33.ts +81 -104
- package/src/Vec2.test.ts +3 -3
- package/src/Vec3.test.ts +2 -3
- package/src/Vec3.ts +46 -61
- package/src/lib.ts +3 -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 +56 -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 +379 -352
- package/src/shapes/PointShape2D.ts +3 -3
- package/src/shapes/QuadraticBezier.test.ts +27 -21
- package/src/shapes/QuadraticBezier.ts +26 -11
- package/src/shapes/Rect2.test.ts +44 -75
- package/src/shapes/Rect2.ts +47 -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/src/shapes/Triangle.ts
CHANGED
@@ -5,7 +5,7 @@ import Abstract2DShape from './Abstract2DShape';
|
|
5
5
|
import LineSegment2 from './LineSegment2';
|
6
6
|
import Rect2 from './Rect2';
|
7
7
|
|
8
|
-
type TriangleBoundary = [
|
8
|
+
type TriangleBoundary = [LineSegment2, LineSegment2, LineSegment2];
|
9
9
|
|
10
10
|
export default class Triangle extends Abstract2DShape {
|
11
11
|
/**
|
@@ -27,30 +27,26 @@ export default class Triangle extends Abstract2DShape {
|
|
27
27
|
return new Triangle(vertex1, vertex2, vertex3);
|
28
28
|
}
|
29
29
|
|
30
|
-
public get vertices(): [
|
31
|
-
return [
|
30
|
+
public get vertices(): [Point2, Point2, Point2] {
|
31
|
+
return [this.vertex1, this.vertex2, this.vertex3];
|
32
32
|
}
|
33
33
|
|
34
|
-
public map(mapping: (vertex: Vec3)=>Vec3): Triangle {
|
35
|
-
return new Triangle(
|
36
|
-
mapping(this.vertex1),
|
37
|
-
mapping(this.vertex2),
|
38
|
-
mapping(this.vertex3),
|
39
|
-
);
|
34
|
+
public map(mapping: (vertex: Vec3) => Vec3): Triangle {
|
35
|
+
return new Triangle(mapping(this.vertex1), mapping(this.vertex2), mapping(this.vertex3));
|
40
36
|
}
|
41
37
|
|
42
38
|
// Transform, treating this as composed of 2D points.
|
43
39
|
public transformed2DBy(affineTransform: Mat33) {
|
44
|
-
return this.map(vertex => affineTransform.transformVec2(vertex));
|
40
|
+
return this.map((vertex) => affineTransform.transformVec2(vertex));
|
45
41
|
}
|
46
42
|
|
47
43
|
// Transforms this by a linear transform --- verticies are treated as
|
48
44
|
// 3D points.
|
49
45
|
public transformedBy(linearTransform: Mat33) {
|
50
|
-
return this.map(vertex => linearTransform.transformVec3(vertex));
|
46
|
+
return this.map((vertex) => linearTransform.transformVec3(vertex));
|
51
47
|
}
|
52
48
|
|
53
|
-
#sides: TriangleBoundary|undefined = undefined;
|
49
|
+
#sides: TriangleBoundary | undefined = undefined;
|
54
50
|
|
55
51
|
/**
|
56
52
|
* Returns the sides of this triangle, as an array of `LineSegment2`s.
|
@@ -67,7 +63,7 @@ export default class Triangle extends Abstract2DShape {
|
|
67
63
|
const side2 = new LineSegment2(this.vertex2, this.vertex3);
|
68
64
|
const side3 = new LineSegment2(this.vertex3, this.vertex1);
|
69
65
|
|
70
|
-
const sides: TriangleBoundary = [
|
66
|
+
const sides: TriangleBoundary = [side1, side2, side3];
|
71
67
|
this.#sides = sides;
|
72
68
|
return sides;
|
73
69
|
}
|
@@ -76,15 +72,17 @@ export default class Triangle extends Abstract2DShape {
|
|
76
72
|
const result: Point2[] = [];
|
77
73
|
|
78
74
|
for (const edge of this.getEdges()) {
|
79
|
-
edge.intersectsLineSegment(lineSegment)
|
80
|
-
.forEach(point => result.push(point));
|
75
|
+
edge.intersectsLineSegment(lineSegment).forEach((point) => result.push(point));
|
81
76
|
}
|
82
77
|
|
83
78
|
return result;
|
84
79
|
}
|
85
80
|
|
86
81
|
/** @inheritdoc */
|
87
|
-
public override containsPoint(
|
82
|
+
public override containsPoint(
|
83
|
+
point: Vec3,
|
84
|
+
epsilon: number = Abstract2DShape.smallValue,
|
85
|
+
): boolean {
|
88
86
|
// Project `point` onto normals to each of this' sides.
|
89
87
|
// Uses the Separating Axis Theorem (https://en.wikipedia.org/wiki/Hyperplane_separation_theorem#Use_in_collision_detection)
|
90
88
|
const sides = this.getEdges();
|
@@ -103,7 +101,8 @@ export default class Triangle extends Abstract2DShape {
|
|
103
101
|
|
104
102
|
const projPoint = orthog.dot(point);
|
105
103
|
|
106
|
-
const inProjection =
|
104
|
+
const inProjection =
|
105
|
+
projPoint >= minProjVertex - epsilon && projPoint <= maxProjVertex + epsilon;
|
107
106
|
if (!inProjection) {
|
108
107
|
return false;
|
109
108
|
}
|
@@ -120,7 +119,7 @@ export default class Triangle extends Abstract2DShape {
|
|
120
119
|
*/
|
121
120
|
public override signedDistance(point: Vec3): number {
|
122
121
|
const sides = this.getEdges();
|
123
|
-
const distances = sides.map(side => side.distance(point));
|
122
|
+
const distances = sides.map((side) => side.distance(point));
|
124
123
|
const distance = Math.min(...distances);
|
125
124
|
|
126
125
|
// If the point is in this' interior, signedDistance must return a negative
|
@@ -4,40 +4,79 @@ import convexHull2Of from './convexHull2Of';
|
|
4
4
|
|
5
5
|
describe('convexHull2Of', () => {
|
6
6
|
it.each([
|
7
|
-
[
|
7
|
+
[[Vec2.of(1, 1)], [Vec2.of(1, 1)]],
|
8
8
|
|
9
9
|
// Line
|
10
|
-
[
|
10
|
+
[
|
11
|
+
[Vec2.of(1, 1), Vec2.of(2, 2)],
|
12
|
+
[Vec2.of(1, 1), Vec2.of(2, 2)],
|
13
|
+
],
|
11
14
|
|
12
15
|
// Just a triangle
|
13
|
-
[
|
16
|
+
[
|
17
|
+
[Vec2.of(1, 1), Vec2.of(4, 2), Vec2.of(3, 3)],
|
18
|
+
[Vec2.of(1, 1), Vec2.of(4, 2), Vec2.of(3, 3)],
|
19
|
+
],
|
14
20
|
|
15
21
|
// Triangle with an extra point
|
16
|
-
[
|
22
|
+
[
|
23
|
+
[Vec2.of(1, 1), Vec2.of(2, 20), Vec2.of(3, 5), Vec2.of(4, 3)],
|
24
|
+
[Vec2.of(1, 1), Vec2.of(4, 3), Vec2.of(2, 20)],
|
25
|
+
],
|
17
26
|
|
18
27
|
// Points within a triangle
|
19
28
|
[
|
20
|
-
[
|
21
|
-
|
29
|
+
[
|
30
|
+
Vec2.of(28, 5),
|
31
|
+
Vec2.of(4, 5),
|
32
|
+
Vec2.of(-100, -100),
|
33
|
+
Vec2.of(7, 120),
|
34
|
+
Vec2.of(1, 8),
|
35
|
+
Vec2.of(100, -100),
|
36
|
+
Vec2.of(2, 4),
|
37
|
+
Vec2.of(3, 4),
|
38
|
+
Vec2.of(4, 5),
|
39
|
+
],
|
40
|
+
[Vec2.of(-100, -100), Vec2.of(100, -100), Vec2.of(7, 120)],
|
22
41
|
],
|
23
42
|
|
24
43
|
// Points within a triangle (repeated vertex)
|
25
44
|
[
|
26
|
-
[
|
27
|
-
|
45
|
+
[
|
46
|
+
Vec2.of(28, 5),
|
47
|
+
Vec2.of(4, 5),
|
48
|
+
Vec2.of(-100, -100),
|
49
|
+
Vec2.of(-100, -100),
|
50
|
+
Vec2.of(7, 120),
|
51
|
+
Vec2.of(1, 8),
|
52
|
+
Vec2.of(100, -100),
|
53
|
+
Vec2.of(2, 4),
|
54
|
+
Vec2.of(3, 4),
|
55
|
+
Vec2.of(4, 5),
|
56
|
+
],
|
57
|
+
[Vec2.of(-100, -100), Vec2.of(100, -100), Vec2.of(7, 120)],
|
28
58
|
],
|
29
59
|
|
30
60
|
// Points within a square
|
31
61
|
[
|
32
|
-
[
|
33
|
-
|
62
|
+
[
|
63
|
+
Vec2.of(28, 5),
|
64
|
+
Vec2.of(4, 5),
|
65
|
+
Vec2.of(-100, -100),
|
66
|
+
Vec2.of(100, 100),
|
67
|
+
Vec2.of(7, 100),
|
68
|
+
Vec2.of(1, 8),
|
69
|
+
Vec2.of(-100, 100),
|
70
|
+
Vec2.of(100, -100),
|
71
|
+
Vec2.of(2, 4),
|
72
|
+
Vec2.of(3, 4),
|
73
|
+
Vec2.of(4, 5),
|
74
|
+
],
|
75
|
+
[Vec2.of(-100, -100), Vec2.of(100, -100), Vec2.of(100, 100), Vec2.of(-100, 100)],
|
34
76
|
],
|
35
77
|
|
36
|
-
[
|
37
|
-
Rect2.unitSquare.corners,
|
38
|
-
[ Vec2.of(1, 0), Vec2.of(1, 1), Vec2.of(0, 1), Vec2.of(0, 0) ],
|
39
|
-
]
|
78
|
+
[Rect2.unitSquare.corners, [Vec2.of(1, 0), Vec2.of(1, 1), Vec2.of(0, 1), Vec2.of(0, 0)]],
|
40
79
|
])('should compute the convex hull of a set of points (%j)', (points, expected) => {
|
41
80
|
expect(convexHull2Of(points)).toMatchObject(expected);
|
42
81
|
});
|
43
|
-
});
|
82
|
+
});
|
@@ -13,11 +13,11 @@ const convexHull2Of = (points: Point2[]) => {
|
|
13
13
|
|
14
14
|
// 1. Start with a vertex on the hull
|
15
15
|
const lowestPoint = points.reduce(
|
16
|
-
(lowest, current) => current.y < lowest.y ? current : lowest,
|
17
|
-
points[0]
|
16
|
+
(lowest, current) => (current.y < lowest.y ? current : lowest),
|
17
|
+
points[0],
|
18
18
|
);
|
19
|
-
const vertices = [
|
20
|
-
let toProcess = [...points.filter(p => !p.eq(lowestPoint))];
|
19
|
+
const vertices = [lowestPoint];
|
20
|
+
let toProcess = [...points.filter((p) => !p.eq(lowestPoint))];
|
21
21
|
let lastBaseDirection = Vec2.of(-1, 0);
|
22
22
|
|
23
23
|
// 2. Find the point with greatest angle from the vertex:
|
@@ -29,7 +29,9 @@ const convexHull2Of = (points: Point2[]) => {
|
|
29
29
|
while (toProcess.length > 0) {
|
30
30
|
const lastVertex = vertices[vertices.length - 1];
|
31
31
|
|
32
|
-
let smallestDotProductSoFar: number = lastBaseDirection.dot(
|
32
|
+
let smallestDotProductSoFar: number = lastBaseDirection.dot(
|
33
|
+
lowestPoint.minus(lastVertex).normalizedOrZero(),
|
34
|
+
);
|
33
35
|
let furthestPointSoFar = lowestPoint;
|
34
36
|
for (const point of toProcess) {
|
35
37
|
// Maximizing the angle is the same as minimizing the dot product:
|
@@ -46,7 +48,7 @@ const convexHull2Of = (points: Point2[]) => {
|
|
46
48
|
smallestDotProductSoFar = currentDotProduct;
|
47
49
|
}
|
48
50
|
}
|
49
|
-
toProcess = toProcess.filter(p => !p.eq(furthestPointSoFar));
|
51
|
+
toProcess = toProcess.filter((p) => !p.eq(furthestPointSoFar));
|
50
52
|
|
51
53
|
const newBaseDirection = furthestPointSoFar.minus(lastVertex).normalized();
|
52
54
|
|
@@ -68,4 +70,4 @@ const convexHull2Of = (points: Point2[]) => {
|
|
68
70
|
return vertices;
|
69
71
|
};
|
70
72
|
|
71
|
-
export default convexHull2Of;
|
73
|
+
export default convexHull2Of;
|
package/tsconfig.json
CHANGED
package/typedoc.json
CHANGED