1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | var fp_1 = require("lodash/fp");
|
4 | // based on code drawn from this repo:
|
5 | // https://github.com/infusion/Angles.js/blob/master/angles.js
|
6 | var TAU = 2 * Math.PI;
|
7 | var EPS = 1e-15;
|
8 | var SCALE = 2 * Math.PI;
|
9 | var DIRECTIONS = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"];
|
10 | /**
|
11 | * Mathematical modulo
|
12 | *
|
13 | * @param {number} x
|
14 | * @param {number} m
|
15 | * @returns {number}
|
16 | */
|
17 | function mod(x, m) {
|
18 | return (x % m + m) % m;
|
19 | }
|
20 | /**
|
21 | * Convert from radians to degrees
|
22 | *
|
23 | * @param {number} radians
|
24 | * @returns {number} degrees
|
25 | */
|
26 | function radiansToDegrees(radians) {
|
27 | return 180 / Math.PI * radians;
|
28 | }
|
29 | exports.radiansToDegrees = radiansToDegrees;
|
30 | /**
|
31 | * Convert from degrees to radians
|
32 | *
|
33 | * @param {number} degrees
|
34 | * @returns {number} radians
|
35 | */
|
36 | function degreesToRadians(degrees) {
|
37 | return Math.PI / 180 * degrees;
|
38 | }
|
39 | exports.degreesToRadians = degreesToRadians;
|
40 | /**
|
41 | * Normalize an arbitrary angle to the interval [-180, 180)
|
42 | *
|
43 | * @param {number} n
|
44 | * @returns {number}
|
45 | */
|
46 | function normalizeHalf(n) {
|
47 | var h = SCALE / 2;
|
48 | return mod(n + h, SCALE) - h;
|
49 | }
|
50 | exports.normalizeHalf = normalizeHalf;
|
51 | /**
|
52 | * Normalize an arbitrary angle to the interval [0, 360)
|
53 | *
|
54 | * @param {number} n
|
55 | * @returns {number}
|
56 | */
|
57 | function normalize(n) {
|
58 | return mod(n, SCALE);
|
59 | }
|
60 | exports.normalize = normalize;
|
61 | /**
|
62 | * Gets the shortest direction to rotate to another angle
|
63 | *
|
64 | * @param {number} from
|
65 | * @param {number} to
|
66 | * @returns {number}
|
67 | */
|
68 | function shortestDirection(from, to) {
|
69 | var z = from - to;
|
70 | // mod(-z, 360) < mod(z, 360) <=> mod(z + 180, 360) < 180 , for all z \ 180
|
71 | if (from === to) {
|
72 | return 0;
|
73 | // if (mod(-z, 360) < mod(z, 360)) {
|
74 | }
|
75 | else if (normalizeHalf(z) < 0) {
|
76 | return -1; // Left
|
77 | }
|
78 | else {
|
79 | return +1; // Right
|
80 | }
|
81 | }
|
82 | exports.shortestDirection = shortestDirection;
|
83 | /**
|
84 | * Checks if an angle is between two other angles
|
85 | *
|
86 | * @param {number} n
|
87 | * @param {number} a
|
88 | * @param {number} b
|
89 | * @returns {boolean}
|
90 | */
|
91 | function between(n, a, b) {
|
92 | // Check if an angle n is between a and b
|
93 | n = mod(n, SCALE);
|
94 | a = mod(a, SCALE);
|
95 | b = mod(b, SCALE);
|
96 | if (a < b)
|
97 | return a <= n && n <= b;
|
98 | // return 0 <= n && n <= b || a <= n && n < 360;
|
99 | return a <= n || n <= b;
|
100 | }
|
101 | exports.between = between;
|
102 | /**
|
103 | * Calculates the angular difference between two angles
|
104 | * @param {number} a
|
105 | * @param {number} b
|
106 | * @returns {number}
|
107 | */
|
108 | function diff(a, b) {
|
109 | return Math.abs(b - a) % SCALE;
|
110 | }
|
111 | exports.diff = diff;
|
112 | /**
|
113 | * Calculate the minimal distance between two angles
|
114 | *
|
115 | * @param {number} a
|
116 | * @param {number} b
|
117 | * @returns {number}
|
118 | */
|
119 | function distance(a, b) {
|
120 | var h = SCALE / 2;
|
121 | // One-Liner:
|
122 | //return Math.min(mod(a - b, m), mod(b - a, m));
|
123 | var diff = normalizeHalf(a - b);
|
124 | if (diff > h)
|
125 | diff = diff - SCALE;
|
126 | return Math.abs(diff);
|
127 | }
|
128 | exports.distance = distance;
|
129 | /**
|
130 | * Calculate radians from current angle
|
131 | *
|
132 | * @param {number} n
|
133 | * @returns {number}
|
134 | */
|
135 | function toRad(n) {
|
136 | // https://en.wikipedia.org/wiki/Radian
|
137 | return n / SCALE * TAU;
|
138 | }
|
139 | exports.toRad = toRad;
|
140 | /**
|
141 | * Calculate degrees from current angle
|
142 | *
|
143 | * @param {number} n
|
144 | * @returns {number}
|
145 | */
|
146 | function toDeg(n) {
|
147 | // https://en.wikipedia.org/wiki/Degree_(angle)
|
148 | return n / SCALE * 360;
|
149 | }
|
150 | exports.toDeg = toDeg;
|
151 | /**
|
152 | * Calculate gons from current angle
|
153 | *
|
154 | * @param {number} n
|
155 | * @returns {number}
|
156 | */
|
157 | function toGon(n) {
|
158 | // https://en.wikipedia.org/wiki/Gradian
|
159 | return n / SCALE * 400;
|
160 | }
|
161 | exports.toGon = toGon;
|
162 | /**
|
163 | * Given the sine and cosine of an angle, what is the original angle?
|
164 | *
|
165 | * @param {number} sin
|
166 | * @param {number} cos
|
167 | * @returns {number}
|
168 | */
|
169 | function fromSinCos(sin, cos) {
|
170 | var angle = (1 + Math.acos(cos) / TAU) * SCALE;
|
171 | if (sin < 0) {
|
172 | angle = SCALE - angle;
|
173 | }
|
174 | return mod(angle, SCALE);
|
175 | }
|
176 | exports.fromSinCos = fromSinCos;
|
177 | /**
|
178 | * What is the angle of two points making a line
|
179 | *
|
180 | * @param {Array} p1
|
181 | * @param {Array} p2
|
182 | * @returns {number}
|
183 | */
|
184 | function fromSlope(p1, p2) {
|
185 | var angle = (TAU + Math.atan2(p2[1] - p1[1], p2[0] - p1[0])) % TAU;
|
186 | return angle / TAU * SCALE;
|
187 | }
|
188 | exports.fromSlope = fromSlope;
|
189 | /**
|
190 | * Returns the quadrant
|
191 | *
|
192 | * @param {number} x The point x-coordinate
|
193 | * @param {number} y The point y-coordinate
|
194 | * @param {number=} k The optional number of regions in the coordinate-system
|
195 | * @param {number=} shift An optional angle to rotate the coordinate system
|
196 | * @returns {number}
|
197 | */
|
198 | function quadrant(x, y, k, shift) {
|
199 | if (fp_1.isUndefined(k))
|
200 | k = 4; // How many regions? 4 = quadrant, 8 = octant, ...
|
201 | if (fp_1.isUndefined(shift))
|
202 | shift = 0; // Rotate the coordinate system by shift° (positiv = counter-clockwise)
|
203 | /* shift = PI / k, k = 4:
|
204 | * I) 45-135
|
205 | * II) 135-225
|
206 | * III) 225-315
|
207 | * IV) 315-360
|
208 | */
|
209 | /* shift = 0, k = 4:
|
210 | * I) 0-90
|
211 | * II) 90-180
|
212 | * III) 180-270
|
213 | * IV) 270-360
|
214 | */
|
215 | var phi = (Math.atan2(y, x) + TAU) / TAU;
|
216 | if (Math.abs(phi * SCALE % (SCALE / k)) < EPS) {
|
217 | return 0;
|
218 | }
|
219 | return 1 + mod(Math.floor(k * shift / SCALE + k * phi), k);
|
220 | }
|
221 | exports.quadrant = quadrant;
|
222 | /**
|
223 | * Calculates the compass direction of the given angle
|
224 | *
|
225 | * @param {number} angle
|
226 | * @returns {string}
|
227 | */
|
228 | function compass(course) {
|
229 | // 0° = N
|
230 | // 90° = E
|
231 | // 180° = S
|
232 | // 270° = W
|
233 | var k = DIRECTIONS.length;
|
234 | var dir = Math.round(course / SCALE * k);
|
235 | return DIRECTIONS[mod(dir, k)];
|
236 | }
|
237 | exports.compass = compass;
|
238 | /**
|
239 | * Calculates the linear interpolation of two angles
|
240 | *
|
241 | * @param {number} a Angle one
|
242 | * @param {number} b Angle two
|
243 | * @param {number} p Percentage
|
244 | * @param {number} dir Direction (either 1 [=CW] or -1 [=CCW])
|
245 | * @returns {number}
|
246 | */
|
247 | function lerp(a, b, p, dir) {
|
248 | a = mod(a, SCALE);
|
249 | b = mod(b, SCALE);
|
250 | if (a === b)
|
251 | return a;
|
252 | // dir becomes an offset if we have to add a full revolution (=scale)
|
253 | if (!dir)
|
254 | dir = -SCALE;
|
255 | else if (dir === 1 === a < b)
|
256 | dir *= SCALE;
|
257 | else
|
258 | dir = 0;
|
259 | return mod(a + p * (b - a - dir), SCALE);
|
260 | }
|
261 | exports.lerp = lerp;
|
262 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQW5nbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3Bpbm9mZnMvQW5nbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxnQ0FBd0M7QUFFeEMsc0NBQXNDO0FBQ3RDLDhEQUE4RDtBQUU5RCxJQUFNLEdBQUcsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQztBQUN4QixJQUFNLEdBQUcsR0FBRyxLQUFLLENBQUM7QUFDbEIsSUFBTSxLQUFLLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUM7QUFDMUIsSUFBTSxVQUFVLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFFaEU7Ozs7OztLQU1LO0FBQ0wsYUFBYSxDQUFDLEVBQUUsQ0FBQztJQUNmLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3pCLENBQUM7QUFFRDs7Ozs7T0FLSTtBQUNKLDBCQUFpQyxPQUFlO0lBQzlDLE1BQU0sQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEVBQUUsR0FBRyxPQUFPLENBQUM7QUFDakMsQ0FBQztBQUZELDRDQUVDO0FBRUQ7Ozs7O09BS0k7QUFDSiwwQkFBaUMsT0FBZTtJQUM5QyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxHQUFHLEdBQUcsT0FBTyxDQUFDO0FBQ2pDLENBQUM7QUFGRCw0Q0FFQztBQUVEOzs7OztPQUtJO0FBQ0osdUJBQThCLENBQUM7SUFDN0IsSUFBSSxDQUFDLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBQztJQUVsQixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQy9CLENBQUM7QUFKRCxzQ0FJQztBQUVEOzs7OztPQUtJO0FBQ0osbUJBQTBCLENBQUM7SUFDekIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDdkIsQ0FBQztBQUZELDhCQUVDO0FBRUQ7Ozs7OztPQU1JO0FBQ0osMkJBQWtDLElBQUksRUFBRSxFQUFFO0lBQ3hDLElBQUksQ0FBQyxHQUFHLElBQUksR0FBRyxFQUFFLENBQUM7SUFDbEIsaUZBQWlGO0lBRWpGLEVBQUUsQ0FBQyxDQUFDLElBQUksS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ2hCLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDVCxvQ0FBb0M7SUFDdEMsQ0FBQztJQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNoQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPO0lBQ3BCLENBQUM7SUFBQyxJQUFJLENBQUMsQ0FBQztRQUNOLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVE7SUFDckIsQ0FBQztBQUNILENBQUM7QUFaRCw4Q0FZQztBQUVEOzs7Ozs7O09BT0k7QUFDSixpQkFBd0IsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQzdCLHlDQUF5QztJQUV6QyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNsQixDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNsQixDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUVsQixFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNuQyxnREFBZ0Q7SUFDaEQsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUMxQixDQUFDO0FBVkQsMEJBVUM7QUFFRDs7Ozs7T0FLSTtBQUNKLGNBQXFCLENBQUMsRUFBRSxDQUFDO0lBQ3ZCLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUM7QUFDakMsQ0FBQztBQUZELG9CQUVDO0FBRUQ7Ozs7OztPQU1JO0FBQ0osa0JBQXlCLENBQUMsRUFBRSxDQUFDO0lBQzNCLElBQUksQ0FBQyxHQUFHLEtBQUssR0FBRyxDQUFDLENBQUM7SUFFbEIsYUFBYTtJQUNiLGdEQUFnRDtJQUVoRCxJQUFJLElBQUksR0FBRyxhQUFhLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBRWhDLEVBQUUsQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUM7UUFBQyxJQUFJLEdBQUcsSUFBSSxHQUFHLEtBQUssQ0FBQztJQUVsQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUN4QixDQUFDO0FBWEQsNEJBV0M7QUFFRDs7Ozs7T0FLSTtBQUNKLGVBQXNCLENBQUM7SUFDckIsdUNBQXVDO0lBQ3ZDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsS0FBSyxHQUFHLEdBQUcsQ0FBQztBQUN6QixDQUFDO0FBSEQsc0JBR0M7QUFFRDs7Ozs7T0FLSTtBQUNKLGVBQXNCLENBQUM7SUFDckIsK0NBQStDO0lBQy9DLE1BQU0sQ0FBQyxDQUFDLEdBQUcsS0FBSyxHQUFHLEdBQUcsQ0FBQztBQUN6QixDQUFDO0FBSEQsc0JBR0M7QUFFRDs7Ozs7T0FLSTtBQUNKLGVBQXNCLENBQUM7SUFDckIsd0NBQXdDO0lBQ3hDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsS0FBSyxHQUFHLEdBQUcsQ0FBQztBQUN6QixDQUFDO0FBSEQsc0JBR0M7QUFFRDs7Ozs7O09BTUk7QUFDSixvQkFBMkIsR0FBRyxFQUFFLEdBQUc7SUFDakMsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUM7SUFFL0MsRUFBRSxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDWixLQUFLLEdBQUcsS0FBSyxHQUFHLEtBQUssQ0FBQztJQUN4QixDQUFDO0lBQ0QsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDM0IsQ0FBQztBQVBELGdDQU9DO0FBRUQ7Ozs7OztPQU1JO0FBQ0osbUJBQTBCLEVBQUUsRUFBRSxFQUFFO0lBQzlCLElBQUksS0FBSyxHQUFHLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUM7SUFFbkUsTUFBTSxDQUFDLEtBQUssR0FBRyxHQUFHLEdBQUcsS0FBSyxDQUFDO0FBQzdCLENBQUM7QUFKRCw4QkFJQztBQUVEOzs7Ozs7OztPQVFJO0FBQ0osa0JBQXlCLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUs7SUFDckMsRUFBRSxDQUFDLENBQUMsZ0JBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxrREFBa0Q7SUFFN0UsRUFBRSxDQUFDLENBQUMsZ0JBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyx1RUFBdUU7SUFFMUc7Ozs7O2FBS0c7SUFFSDs7Ozs7YUFLRztJQUVILElBQUksR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDO0lBRXpDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLEtBQUssR0FBRyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDOUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNYLENBQUM7SUFFRCxNQUFNLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxLQUFLLEdBQUcsS0FBSyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM3RCxDQUFDO0FBMUJELDRCQTBCQztBQUVEOzs7OztPQUtJO0FBQ0osaUJBQXdCLE1BQU07SUFDNUIsU0FBUztJQUNULFVBQVU7SUFDVixXQUFXO0lBQ1gsV0FBVztJQUVYLElBQUksQ0FBQyxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUM7SUFFMUIsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBRXpDLE1BQU0sQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2pDLENBQUM7QUFYRCwwQkFXQztBQUVEOzs7Ozs7OztPQVFJO0FBQ0osY0FBcUIsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBRztJQUMvQixDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNsQixDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUVsQixFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUV0QixxRUFBcUU7SUFDckUsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFBQyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUM7SUFDdkIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUFDLEdBQUcsSUFBSSxLQUFLLENBQUM7SUFDM0MsSUFBSTtRQUFDLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFFYixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQzNDLENBQUM7QUFaRCxvQkFZQyJ9 |
\ | No newline at end of file |