UNPKG

12.9 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var fp_1 = require("lodash/fp");
4// based on code drawn from this repo:
5// https://github.com/infusion/Angles.js/blob/master/angles.js
6var TAU = 2 * Math.PI;
7var EPS = 1e-15;
8var SCALE = 2 * Math.PI;
9var 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 */
17function 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 */
26function radiansToDegrees(radians) {
27 return 180 / Math.PI * radians;
28}
29exports.radiansToDegrees = radiansToDegrees;
30/**
31 * Convert from degrees to radians
32 *
33 * @param {number} degrees
34 * @returns {number} radians
35 */
36function degreesToRadians(degrees) {
37 return Math.PI / 180 * degrees;
38}
39exports.degreesToRadians = degreesToRadians;
40/**
41 * Normalize an arbitrary angle to the interval [-180, 180)
42 *
43 * @param {number} n
44 * @returns {number}
45 */
46function normalizeHalf(n) {
47 var h = SCALE / 2;
48 return mod(n + h, SCALE) - h;
49}
50exports.normalizeHalf = normalizeHalf;
51/**
52 * Normalize an arbitrary angle to the interval [0, 360)
53 *
54 * @param {number} n
55 * @returns {number}
56 */
57function normalize(n) {
58 return mod(n, SCALE);
59}
60exports.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 */
68function 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}
82exports.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 */
91function 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}
101exports.between = between;
102/**
103 * Calculates the angular difference between two angles
104 * @param {number} a
105 * @param {number} b
106 * @returns {number}
107 */
108function diff(a, b) {
109 return Math.abs(b - a) % SCALE;
110}
111exports.diff = diff;
112/**
113 * Calculate the minimal distance between two angles
114 *
115 * @param {number} a
116 * @param {number} b
117 * @returns {number}
118 */
119function 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}
128exports.distance = distance;
129/**
130 * Calculate radians from current angle
131 *
132 * @param {number} n
133 * @returns {number}
134 */
135function toRad(n) {
136 // https://en.wikipedia.org/wiki/Radian
137 return n / SCALE * TAU;
138}
139exports.toRad = toRad;
140/**
141 * Calculate degrees from current angle
142 *
143 * @param {number} n
144 * @returns {number}
145 */
146function toDeg(n) {
147 // https://en.wikipedia.org/wiki/Degree_(angle)
148 return n / SCALE * 360;
149}
150exports.toDeg = toDeg;
151/**
152 * Calculate gons from current angle
153 *
154 * @param {number} n
155 * @returns {number}
156 */
157function toGon(n) {
158 // https://en.wikipedia.org/wiki/Gradian
159 return n / SCALE * 400;
160}
161exports.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 */
169function 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}
176exports.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 */
184function fromSlope(p1, p2) {
185 var angle = (TAU + Math.atan2(p2[1] - p1[1], p2[0] - p1[0])) % TAU;
186 return angle / TAU * SCALE;
187}
188exports.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 */
198function 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}
221exports.quadrant = quadrant;
222/**
223 * Calculates the compass direction of the given angle
224 *
225 * @param {number} angle
226 * @returns {string}
227 */
228function 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}
237exports.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 */
247function 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}
261exports.lerp = lerp;
262//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQW5nbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3Bpbm9mZnMvQW5nbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxnQ0FBd0M7QUFFeEMsc0NBQXNDO0FBQ3RDLDhEQUE4RDtBQUU5RCxJQUFNLEdBQUcsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQztBQUN4QixJQUFNLEdBQUcsR0FBRyxLQUFLLENBQUM7QUFDbEIsSUFBTSxLQUFLLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUM7QUFDMUIsSUFBTSxVQUFVLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFFaEU7Ozs7OztLQU1LO0FBQ0wsYUFBYSxDQUFDLEVBQUUsQ0FBQztJQUNmLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3pCLENBQUM7QUFFRDs7Ozs7T0FLSTtBQUNKLDBCQUFpQyxPQUFlO0lBQzlDLE1BQU0sQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEVBQUUsR0FBRyxPQUFPLENBQUM7QUFDakMsQ0FBQztBQUZELDRDQUVDO0FBRUQ7Ozs7O09BS0k7QUFDSiwwQkFBaUMsT0FBZTtJQUM5QyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxHQUFHLEdBQUcsT0FBTyxDQUFDO0FBQ2pDLENBQUM7QUFGRCw0Q0FFQztBQUVEOzs7OztPQUtJO0FBQ0osdUJBQThCLENBQUM7SUFDN0IsSUFBSSxDQUFDLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBQztJQUVsQixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQy9CLENBQUM7QUFKRCxzQ0FJQztBQUVE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
\No newline at end of file