-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathRotation.ts
104 lines (87 loc) · 2.82 KB
/
Rotation.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import { Utils } from "./Utils";
export class Rotation {
private static DIRS: { [id: string]: number } = {'sw': -135, 'w': -90, 'nw': -45, 'n': 0, 'ne': 45, 'e': 90, 'se': 135, 's': 180};
constructor(private _degrees: number) {
}
static from(direction: string): Rotation {
return new Rotation(Rotation.DIRS[direction] || 0);
}
get name(): string {
for (const [key, value] of Object.entries(Rotation.DIRS)) {
if (Utils.equals(value, this.degrees)) {
return key;
}
}
return 'n';
}
get degrees(): number {
return this._degrees;
}
get radians(): number {
return this.degrees / 180 * Math.PI;
}
add(that: Rotation): Rotation {
let sum = this.degrees + that.degrees;
if (sum <= -180)
sum += 360;
if (sum > 180)
sum -= 360;
return new Rotation(sum);
}
delta(that: Rotation): Rotation {
let a = this.degrees;
let b = that.degrees;
let dist = b-a;
if (Math.abs(dist) > 180) {
if (a < 0)
a += 360;
if (b < 0)
b += 360;
dist = b-a;
}
return new Rotation(dist);
}
normalize(): Rotation {
let dir = this.degrees;
if (Utils.equals(dir, -90))
dir = 0;
else if (dir < -90)
dir += 180;
else if (dir > 90)
dir -= 180;
return new Rotation(dir);
}
isVertical(): boolean {
return this.degrees % 180 == 0;
}
quarterDirection(relativeTo: Rotation): Rotation {
const deltaDir = relativeTo.delta(this).degrees;
const deg = deltaDir < 0 ? Math.ceil((deltaDir-45)/90) : Math.floor((deltaDir+45)/90);
return new Rotation(deg*90);
}
halfDirection(relativeTo: Rotation, splitAxis: Rotation): Rotation {
const deltaDir = relativeTo.delta(this).degrees;
let deg;
if (splitAxis.isVertical()) {
if (deltaDir < 0 && deltaDir >= -180)
deg = -90;
else
deg = 90;
} else {
if (deltaDir < 90 && deltaDir >= -90)
deg = 0;
else
deg = 180;
}
return new Rotation(deg);
}
nearestRoundedInDirection(relativeTo: Rotation, direction: number) {
const ceiledOrFlooredOrientation = relativeTo.round(direction);
const differenceInOrientation = Math.abs(ceiledOrFlooredOrientation.degrees - this.degrees) % 90;
return this.add(new Rotation(Math.sign(direction)*differenceInOrientation));
}
private round(direction: number): Rotation {
const deg = this.degrees / 45;
return new Rotation((direction >= 0 ? Math.ceil(deg) : Math.floor(deg)) * 45);
}
}