@immugio/three-math-extensions 0.3.4 → 0.3.6
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/CHANGELOG.md +17 -1
- package/cjs/Line2D.js +90 -13
- package/docs/classes/BoundingBox.md +121 -121
- package/docs/classes/Line2D.md +1366 -1366
- package/docs/classes/Line3D.md +831 -831
- package/docs/classes/Polygon.md +297 -297
- package/docs/classes/Rectangle.md +291 -291
- package/docs/classes/Size2.md +55 -55
- package/docs/classes/Vec2.md +282 -282
- package/docs/classes/Vec3.md +338 -338
- package/docs/interfaces/Point2.md +30 -30
- package/docs/interfaces/Point3.md +41 -41
- package/docs/modules.md +209 -209
- package/eslint.config.mjs +111 -111
- package/esm/Line2D.js +90 -13
- package/package.json +62 -62
- package/src/BoundingBox.ts +13 -13
- package/src/Line2D.ts +951 -857
- package/src/Line3D.ts +586 -586
- package/src/MathConstants.ts +1 -1
- package/src/Point2.ts +3 -3
- package/src/Point3.ts +4 -4
- package/src/Polygon.ts +286 -286
- package/src/Rectangle.ts +92 -92
- package/src/Size2.ts +3 -3
- package/src/Vec2.ts +124 -124
- package/src/Vec3.ts +167 -167
- package/src/containsPoint.ts +65 -65
- package/src/directions.ts +9 -9
- package/src/directions2d.ts +7 -7
- package/src/ensurePolygonClockwise.ts +9 -9
- package/src/extendOrTrimPolylinesAtIntersections.ts +10 -10
- package/src/getPolygonArea.ts +21 -21
- package/src/index.ts +24 -24
- package/src/isContinuousClosedShape.ts +24 -24
- package/src/isPointInPolygon.ts +23 -23
- package/src/isPolygonClockwise.ts +15 -15
- package/src/normalizeAngleDegrees.ts +6 -6
- package/src/normalizeAngleRadians.ts +14 -14
- package/src/offsetPolyline.ts +26 -26
- package/src/polygonPerimeter.ts +13 -13
- package/src/sortLinesByConnections.ts +45 -45
- package/types/Line2D.d.ts +12 -5
package/src/Rectangle.ts
CHANGED
|
@@ -1,93 +1,93 @@
|
|
|
1
|
-
import { Polygon } from "./Polygon";
|
|
2
|
-
import { Vec2 } from "./Vec2";
|
|
3
|
-
import { Point2 } from "./Point2";
|
|
4
|
-
|
|
5
|
-
export class Rectangle {
|
|
6
|
-
|
|
7
|
-
constructor(public leftX: number, public rightX: number, public topY: number, public bottomY: number) { }
|
|
8
|
-
|
|
9
|
-
public clone(): Rectangle {
|
|
10
|
-
return new Rectangle(this.leftX, this.rightX, this.topY, this.bottomY);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
public get size(): Vec2 {
|
|
14
|
-
return new Vec2(
|
|
15
|
-
this.rightX - this.leftX,
|
|
16
|
-
this.topY - this.bottomY
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
public get center(): Vec2 {
|
|
21
|
-
return new Vec2(
|
|
22
|
-
(this.leftX + this.rightX) / 2,
|
|
23
|
-
(this.topY + this.bottomY) / 2
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
public get offset(): Vec2 {
|
|
28
|
-
return new Vec2(
|
|
29
|
-
(this.leftX + this.rightX) / -2,
|
|
30
|
-
(this.topY + this.bottomY) / -2
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
public overlaps(other: Rectangle): boolean {
|
|
35
|
-
// Proof is by contradiction. Any one of four conditions guarantees that NO OVERLAP CAN EXIST.
|
|
36
|
-
const result = this.bottomY >= other.topY || this.topY <= other.bottomY || this.rightX <= other.leftX || this.leftX >= other.rightX;
|
|
37
|
-
|
|
38
|
-
return !result;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public get hasSize(): boolean {
|
|
42
|
-
return this.rightX - this.leftX > 1 && this.topY - this.bottomY > 1;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
public translate(diff: Point2): Rectangle {
|
|
46
|
-
this.leftX += diff.x;
|
|
47
|
-
this.rightX += diff.x;
|
|
48
|
-
this.topY += diff.y;
|
|
49
|
-
this.bottomY += diff.y;
|
|
50
|
-
|
|
51
|
-
return this;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
public centerOnOrigin(): Rectangle {
|
|
55
|
-
const center = this.center;
|
|
56
|
-
this.leftX -= center.x;
|
|
57
|
-
this.rightX -= center.x;
|
|
58
|
-
this.topY -= center.y;
|
|
59
|
-
this.bottomY -= center.y;
|
|
60
|
-
|
|
61
|
-
return this;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
public toPolygon(): Polygon {
|
|
65
|
-
return new Polygon(this.toPoints());
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* The polygon is always constructed as "clockwise", assuming X axis to the right and Y axis down.
|
|
70
|
-
*/
|
|
71
|
-
public toPoints(): Vec2[] {
|
|
72
|
-
return [
|
|
73
|
-
new Vec2(this.leftX, Math.min(this.topY, this.bottomY)),
|
|
74
|
-
new Vec2(this.rightX, Math.min(this.topY, this.bottomY)),
|
|
75
|
-
new Vec2(this.rightX, Math.max(this.topY, this.bottomY)),
|
|
76
|
-
new Vec2(this.leftX, Math.max(this.topY, this.bottomY)),
|
|
77
|
-
];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
public flipVertical(xCenter: number): Rectangle {
|
|
81
|
-
const left = xCenter - (this.rightX - xCenter);
|
|
82
|
-
const right = xCenter - (this.leftX - xCenter);
|
|
83
|
-
|
|
84
|
-
this.leftX = left;
|
|
85
|
-
this.rightX = right;
|
|
86
|
-
|
|
87
|
-
return this;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
public equals(other: Rectangle): boolean {
|
|
91
|
-
return !!other && this.leftX === other.leftX && this.rightX === other.rightX && this.topY === other.topY && this.bottomY === other.bottomY;
|
|
92
|
-
}
|
|
1
|
+
import { Polygon } from "./Polygon";
|
|
2
|
+
import { Vec2 } from "./Vec2";
|
|
3
|
+
import { Point2 } from "./Point2";
|
|
4
|
+
|
|
5
|
+
export class Rectangle {
|
|
6
|
+
|
|
7
|
+
constructor(public leftX: number, public rightX: number, public topY: number, public bottomY: number) { }
|
|
8
|
+
|
|
9
|
+
public clone(): Rectangle {
|
|
10
|
+
return new Rectangle(this.leftX, this.rightX, this.topY, this.bottomY);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public get size(): Vec2 {
|
|
14
|
+
return new Vec2(
|
|
15
|
+
this.rightX - this.leftX,
|
|
16
|
+
this.topY - this.bottomY
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public get center(): Vec2 {
|
|
21
|
+
return new Vec2(
|
|
22
|
+
(this.leftX + this.rightX) / 2,
|
|
23
|
+
(this.topY + this.bottomY) / 2
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public get offset(): Vec2 {
|
|
28
|
+
return new Vec2(
|
|
29
|
+
(this.leftX + this.rightX) / -2,
|
|
30
|
+
(this.topY + this.bottomY) / -2
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public overlaps(other: Rectangle): boolean {
|
|
35
|
+
// Proof is by contradiction. Any one of four conditions guarantees that NO OVERLAP CAN EXIST.
|
|
36
|
+
const result = this.bottomY >= other.topY || this.topY <= other.bottomY || this.rightX <= other.leftX || this.leftX >= other.rightX;
|
|
37
|
+
|
|
38
|
+
return !result;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public get hasSize(): boolean {
|
|
42
|
+
return this.rightX - this.leftX > 1 && this.topY - this.bottomY > 1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public translate(diff: Point2): Rectangle {
|
|
46
|
+
this.leftX += diff.x;
|
|
47
|
+
this.rightX += diff.x;
|
|
48
|
+
this.topY += diff.y;
|
|
49
|
+
this.bottomY += diff.y;
|
|
50
|
+
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public centerOnOrigin(): Rectangle {
|
|
55
|
+
const center = this.center;
|
|
56
|
+
this.leftX -= center.x;
|
|
57
|
+
this.rightX -= center.x;
|
|
58
|
+
this.topY -= center.y;
|
|
59
|
+
this.bottomY -= center.y;
|
|
60
|
+
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public toPolygon(): Polygon {
|
|
65
|
+
return new Polygon(this.toPoints());
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The polygon is always constructed as "clockwise", assuming X axis to the right and Y axis down.
|
|
70
|
+
*/
|
|
71
|
+
public toPoints(): Vec2[] {
|
|
72
|
+
return [
|
|
73
|
+
new Vec2(this.leftX, Math.min(this.topY, this.bottomY)),
|
|
74
|
+
new Vec2(this.rightX, Math.min(this.topY, this.bottomY)),
|
|
75
|
+
new Vec2(this.rightX, Math.max(this.topY, this.bottomY)),
|
|
76
|
+
new Vec2(this.leftX, Math.max(this.topY, this.bottomY)),
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public flipVertical(xCenter: number): Rectangle {
|
|
81
|
+
const left = xCenter - (this.rightX - xCenter);
|
|
82
|
+
const right = xCenter - (this.leftX - xCenter);
|
|
83
|
+
|
|
84
|
+
this.leftX = left;
|
|
85
|
+
this.rightX = right;
|
|
86
|
+
|
|
87
|
+
return this;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public equals(other: Rectangle): boolean {
|
|
91
|
+
return !!other && this.leftX === other.leftX && this.rightX === other.rightX && this.topY === other.topY && this.bottomY === other.bottomY;
|
|
92
|
+
}
|
|
93
93
|
}
|
package/src/Size2.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export class Size2 {
|
|
2
|
-
constructor(public width: number, public height: number) {
|
|
3
|
-
}
|
|
1
|
+
export class Size2 {
|
|
2
|
+
constructor(public width: number, public height: number) {
|
|
3
|
+
}
|
|
4
4
|
}
|
package/src/Vec2.ts
CHANGED
|
@@ -1,125 +1,125 @@
|
|
|
1
|
-
import { Vector2 } from "three";
|
|
2
|
-
import { Vec3 } from "./Vec3";
|
|
3
|
-
import { Point2 } from "./Point2";
|
|
4
|
-
import { normalizeAngleRadians } from "./normalizeAngleRadians";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Vec2 represents a 2D vector. It extends `Vector2` from the `threejs` library.
|
|
8
|
-
*/
|
|
9
|
-
export class Vec2 extends Vector2 {
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Creates a new Vec2 instance from an {x, y} object.
|
|
13
|
-
* @param point - The {x, y} instance.
|
|
14
|
-
* @returns A new Vec2 instance.
|
|
15
|
-
*/
|
|
16
|
-
public static fromPoint(point: Point2): Vec2 {
|
|
17
|
-
return new Vec2(point?.x, point?.y);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Creates a new Vec2[] array from arguments of {x, y} objects.
|
|
22
|
-
* @param points - The ...{x, y} instances.
|
|
23
|
-
*/
|
|
24
|
-
public static fromPoints(...points: Point2[]): Vec2[] {
|
|
25
|
-
return points?.map(p => Vec2.fromPoint(p)) ?? [];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Moves this Vec2 instance towards the target Vec2 by the given amount.
|
|
30
|
-
* @param target - The target Vec2.
|
|
31
|
-
* @param amount - The distance to move.
|
|
32
|
-
* @returns This Vec2 instance.
|
|
33
|
-
*/
|
|
34
|
-
public moveTowards(target: Vector2, amount: number): this {
|
|
35
|
-
const move = target.clone().sub(this).normalize().multiplyScalar(amount);
|
|
36
|
-
this.add(move);
|
|
37
|
-
return this;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Adds y amount to this Vec3 instance and return this
|
|
42
|
-
* @param y
|
|
43
|
-
*/
|
|
44
|
-
public addY(y: number): this {
|
|
45
|
-
this.y += y;
|
|
46
|
-
return this;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Adds x amount to this Vec3 instance and return this
|
|
51
|
-
* @param x
|
|
52
|
-
*/
|
|
53
|
-
public addX(x: number): this {
|
|
54
|
-
this.x += x;
|
|
55
|
-
return this;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Rounds the x and y values of this Vec2 instance if they are close to an integer value.
|
|
60
|
-
* @param max - The maximum difference between the value and the nearest integer.
|
|
61
|
-
* @returns This Vec2 instance.
|
|
62
|
-
*/
|
|
63
|
-
public roundIfCloseToInteger(max: number = 0.000000000001): this {
|
|
64
|
-
if (Math.abs(this.x - Math.round(this.x)) < max) {
|
|
65
|
-
this.x = Math.round(this.x);
|
|
66
|
-
}
|
|
67
|
-
if (Math.abs(this.y - Math.round(this.y)) < max) {
|
|
68
|
-
this.y = Math.round(this.y);
|
|
69
|
-
}
|
|
70
|
-
if (Object.is(this.x, -0)) {
|
|
71
|
-
this.x = 0;
|
|
72
|
-
}
|
|
73
|
-
if (Object.is(this.y, -0)) {
|
|
74
|
-
this.y = 0;
|
|
75
|
-
}
|
|
76
|
-
return this;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Projects this Vec2 instance to a Vec3 instance in 3D space. Vec2.y becomes Vec3.z. and Vec3.y is provided as an argument.
|
|
81
|
-
* @param y - The y value of the new Vec3 instance.
|
|
82
|
-
* @returns A new Vec3 instance.
|
|
83
|
-
*/
|
|
84
|
-
public in3DSpace(y: number = 0): Vec3 {
|
|
85
|
-
return new Vec3(this.x, y, this.y);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Determines if this Vec2 instance is near the target Vec2.
|
|
90
|
-
* maxDistance is the maximum distance between the two vectors within which they are considered `near`.
|
|
91
|
-
*/
|
|
92
|
-
public isNear(v: Vector2, maxDistance: number = undefined): boolean {
|
|
93
|
-
if (!maxDistance) {
|
|
94
|
-
return this.equals(v);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return this.distanceTo(v) <= maxDistance;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Returns the angle between this vector and positive x-axis, the return value is between 0 and 2PI
|
|
102
|
-
*/
|
|
103
|
-
public signedAngle(): number {
|
|
104
|
-
const signed_angle = Math.atan2(this.y, this.x) - Math.atan2(0, 1);
|
|
105
|
-
return normalizeAngleRadians(signed_angle);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* check if the angle between the two vectors is close enough to 0 or 180 degrees (same or opposite direction) within the given tolerance
|
|
110
|
-
* @param other Vector2
|
|
111
|
-
* @param toleranceRadians number angle tolerance in radians
|
|
112
|
-
*/
|
|
113
|
-
public parallelTo(other: Vector2, toleranceRadians: number = 0): boolean {
|
|
114
|
-
const v1 = this.clone().normalize(); // Normalize both vectors to remove magnitude influence
|
|
115
|
-
const v2 = other.clone().normalize();
|
|
116
|
-
|
|
117
|
-
const dotProduct = v1.dot(v2); // Calculate the dot product to find the cosine of the angle between the vectors
|
|
118
|
-
|
|
119
|
-
// Calculate the angle in radians
|
|
120
|
-
const angle = Math.acos(dotProduct);
|
|
121
|
-
|
|
122
|
-
// Check if the angle is within the tolerance of 0 or 180 degrees (Math.PI)
|
|
123
|
-
return Math.abs(angle) <= toleranceRadians || Math.abs(angle - Math.PI) <= toleranceRadians;
|
|
124
|
-
}
|
|
1
|
+
import { Vector2 } from "three";
|
|
2
|
+
import { Vec3 } from "./Vec3";
|
|
3
|
+
import { Point2 } from "./Point2";
|
|
4
|
+
import { normalizeAngleRadians } from "./normalizeAngleRadians";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Vec2 represents a 2D vector. It extends `Vector2` from the `threejs` library.
|
|
8
|
+
*/
|
|
9
|
+
export class Vec2 extends Vector2 {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Creates a new Vec2 instance from an {x, y} object.
|
|
13
|
+
* @param point - The {x, y} instance.
|
|
14
|
+
* @returns A new Vec2 instance.
|
|
15
|
+
*/
|
|
16
|
+
public static fromPoint(point: Point2): Vec2 {
|
|
17
|
+
return new Vec2(point?.x, point?.y);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Creates a new Vec2[] array from arguments of {x, y} objects.
|
|
22
|
+
* @param points - The ...{x, y} instances.
|
|
23
|
+
*/
|
|
24
|
+
public static fromPoints(...points: Point2[]): Vec2[] {
|
|
25
|
+
return points?.map(p => Vec2.fromPoint(p)) ?? [];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Moves this Vec2 instance towards the target Vec2 by the given amount.
|
|
30
|
+
* @param target - The target Vec2.
|
|
31
|
+
* @param amount - The distance to move.
|
|
32
|
+
* @returns This Vec2 instance.
|
|
33
|
+
*/
|
|
34
|
+
public moveTowards(target: Vector2, amount: number): this {
|
|
35
|
+
const move = target.clone().sub(this).normalize().multiplyScalar(amount);
|
|
36
|
+
this.add(move);
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Adds y amount to this Vec3 instance and return this
|
|
42
|
+
* @param y
|
|
43
|
+
*/
|
|
44
|
+
public addY(y: number): this {
|
|
45
|
+
this.y += y;
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Adds x amount to this Vec3 instance and return this
|
|
51
|
+
* @param x
|
|
52
|
+
*/
|
|
53
|
+
public addX(x: number): this {
|
|
54
|
+
this.x += x;
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Rounds the x and y values of this Vec2 instance if they are close to an integer value.
|
|
60
|
+
* @param max - The maximum difference between the value and the nearest integer.
|
|
61
|
+
* @returns This Vec2 instance.
|
|
62
|
+
*/
|
|
63
|
+
public roundIfCloseToInteger(max: number = 0.000000000001): this {
|
|
64
|
+
if (Math.abs(this.x - Math.round(this.x)) < max) {
|
|
65
|
+
this.x = Math.round(this.x);
|
|
66
|
+
}
|
|
67
|
+
if (Math.abs(this.y - Math.round(this.y)) < max) {
|
|
68
|
+
this.y = Math.round(this.y);
|
|
69
|
+
}
|
|
70
|
+
if (Object.is(this.x, -0)) {
|
|
71
|
+
this.x = 0;
|
|
72
|
+
}
|
|
73
|
+
if (Object.is(this.y, -0)) {
|
|
74
|
+
this.y = 0;
|
|
75
|
+
}
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Projects this Vec2 instance to a Vec3 instance in 3D space. Vec2.y becomes Vec3.z. and Vec3.y is provided as an argument.
|
|
81
|
+
* @param y - The y value of the new Vec3 instance.
|
|
82
|
+
* @returns A new Vec3 instance.
|
|
83
|
+
*/
|
|
84
|
+
public in3DSpace(y: number = 0): Vec3 {
|
|
85
|
+
return new Vec3(this.x, y, this.y);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Determines if this Vec2 instance is near the target Vec2.
|
|
90
|
+
* maxDistance is the maximum distance between the two vectors within which they are considered `near`.
|
|
91
|
+
*/
|
|
92
|
+
public isNear(v: Vector2, maxDistance: number = undefined): boolean {
|
|
93
|
+
if (!maxDistance) {
|
|
94
|
+
return this.equals(v);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return this.distanceTo(v) <= maxDistance;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Returns the angle between this vector and positive x-axis, the return value is between 0 and 2PI
|
|
102
|
+
*/
|
|
103
|
+
public signedAngle(): number {
|
|
104
|
+
const signed_angle = Math.atan2(this.y, this.x) - Math.atan2(0, 1);
|
|
105
|
+
return normalizeAngleRadians(signed_angle);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* check if the angle between the two vectors is close enough to 0 or 180 degrees (same or opposite direction) within the given tolerance
|
|
110
|
+
* @param other Vector2
|
|
111
|
+
* @param toleranceRadians number angle tolerance in radians
|
|
112
|
+
*/
|
|
113
|
+
public parallelTo(other: Vector2, toleranceRadians: number = 0): boolean {
|
|
114
|
+
const v1 = this.clone().normalize(); // Normalize both vectors to remove magnitude influence
|
|
115
|
+
const v2 = other.clone().normalize();
|
|
116
|
+
|
|
117
|
+
const dotProduct = v1.dot(v2); // Calculate the dot product to find the cosine of the angle between the vectors
|
|
118
|
+
|
|
119
|
+
// Calculate the angle in radians
|
|
120
|
+
const angle = Math.acos(dotProduct);
|
|
121
|
+
|
|
122
|
+
// Check if the angle is within the tolerance of 0 or 180 degrees (Math.PI)
|
|
123
|
+
return Math.abs(angle) <= toleranceRadians || Math.abs(angle - Math.PI) <= toleranceRadians;
|
|
124
|
+
}
|
|
125
125
|
}
|