UNPKG

gpml2pvjson

Version:
263 lines 12.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.lerp = exports.compass = exports.quadrant = exports.fromSlope = exports.fromSinCos = exports.toGon = exports.toDeg = exports.toRad = exports.distance = exports.diff = exports.between = exports.shortestDirection = exports.normalize = exports.normalizeHalf = exports.degreesToRadians = exports.radiansToDegrees = void 0; var fp_1 = require("lodash/fp"); // based on code drawn from this repo: // https://github.com/infusion/Angles.js/blob/master/angles.js var TAU = 2 * Math.PI; var EPS = 1e-15; var SCALE = 2 * Math.PI; var DIRECTIONS = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"]; /** * Mathematical modulo * * @param {number} x * @param {number} m * @returns {number} */ function mod(x, m) { return ((x % m) + m) % m; } /** * Convert from radians to degrees * * @param {number} radians * @returns {number} degrees */ function radiansToDegrees(radians) { return (180 / Math.PI) * radians; } exports.radiansToDegrees = radiansToDegrees; /** * Convert from degrees to radians * * @param {number} degrees * @returns {number} radians */ function degreesToRadians(degrees) { return (Math.PI / 180) * degrees; } exports.degreesToRadians = degreesToRadians; /** * Normalize an arbitrary angle to the interval [-180, 180) * * @param {number} n * @returns {number} */ function normalizeHalf(n) { var h = SCALE / 2; return mod(n + h, SCALE) - h; } exports.normalizeHalf = normalizeHalf; /** * Normalize an arbitrary angle to the interval [0, 360) * * @param {number} n * @returns {number} */ function normalize(n) { return mod(n, SCALE); } exports.normalize = normalize; /** * Gets the shortest direction to rotate to another angle * * @param {number} from * @param {number} to * @returns {number} */ function shortestDirection(from, to) { var z = from - to; // mod(-z, 360) < mod(z, 360) <=> mod(z + 180, 360) < 180 , for all z \ 180 if (from === to) { return 0; // if (mod(-z, 360) < mod(z, 360)) { } else if (normalizeHalf(z) < 0) { return -1; // Left } else { return +1; // Right } } exports.shortestDirection = shortestDirection; /** * Checks if an angle is between two other angles * * @param {number} n * @param {number} a * @param {number} b * @returns {boolean} */ function between(n, a, b) { // Check if an angle n is between a and b n = mod(n, SCALE); a = mod(a, SCALE); b = mod(b, SCALE); if (a < b) return a <= n && n <= b; // return 0 <= n && n <= b || a <= n && n < 360; return a <= n || n <= b; } exports.between = between; /** * Calculates the angular difference between two angles * @param {number} a * @param {number} b * @returns {number} */ function diff(a, b) { return Math.abs(b - a) % SCALE; } exports.diff = diff; /** * Calculate the minimal distance between two angles * * @param {number} a * @param {number} b * @returns {number} */ function distance(a, b) { var h = SCALE / 2; // One-Liner: //return Math.min(mod(a - b, m), mod(b - a, m)); var diff = normalizeHalf(a - b); if (diff > h) diff = diff - SCALE; return Math.abs(diff); } exports.distance = distance; /** * Calculate radians from current angle * * @param {number} n * @returns {number} */ function toRad(n) { // https://en.wikipedia.org/wiki/Radian return (n / SCALE) * TAU; } exports.toRad = toRad; /** * Calculate degrees from current angle * * @param {number} n * @returns {number} */ function toDeg(n) { // https://en.wikipedia.org/wiki/Degree_(angle) return (n / SCALE) * 360; } exports.toDeg = toDeg; /** * Calculate gons from current angle * * @param {number} n * @returns {number} */ function toGon(n) { // https://en.wikipedia.org/wiki/Gradian return (n / SCALE) * 400; } exports.toGon = toGon; /** * Given the sine and cosine of an angle, what is the original angle? * * @param {number} sin * @param {number} cos * @returns {number} */ function fromSinCos(sin, cos) { var angle = (1 + Math.acos(cos) / TAU) * SCALE; if (sin < 0) { angle = SCALE - angle; } return mod(angle, SCALE); } exports.fromSinCos = fromSinCos; /** * What is the angle of two points making a line * * @param {Array} p1 * @param {Array} p2 * @returns {number} */ function fromSlope(p1, p2) { var angle = (TAU + Math.atan2(p2[1] - p1[1], p2[0] - p1[0])) % TAU; return (angle / TAU) * SCALE; } exports.fromSlope = fromSlope; /** * Returns the quadrant * * @param {number} x The point x-coordinate * @param {number} y The point y-coordinate * @param {number=} k The optional number of regions in the coordinate-system * @param {number=} shift An optional angle to rotate the coordinate system * @returns {number} */ function quadrant(x, y, k, shift) { if (fp_1.isUndefined(k)) k = 4; // How many regions? 4 = quadrant, 8 = octant, ... if (fp_1.isUndefined(shift)) shift = 0; // Rotate the coordinate system by shift° (positiv = counter-clockwise) /* shift = PI / k, k = 4: * I) 45-135 * II) 135-225 * III) 225-315 * IV) 315-360 */ /* shift = 0, k = 4: * I) 0-90 * II) 90-180 * III) 180-270 * IV) 270-360 */ var phi = (Math.atan2(y, x) + TAU) / TAU; if (Math.abs((phi * SCALE) % (SCALE / k)) < EPS) { return 0; } return 1 + mod(Math.floor((k * shift) / SCALE + k * phi), k); } exports.quadrant = quadrant; /** * Calculates the compass direction of the given angle * * @param {number} angle * @returns {string} */ function compass(course) { // 0° = N // 90° = E // 180° = S // 270° = W var k = DIRECTIONS.length; var dir = Math.round((course / SCALE) * k); return DIRECTIONS[mod(dir, k)]; } exports.compass = compass; /** * Calculates the linear interpolation of two angles * * @param {number} a Angle one * @param {number} b Angle two * @param {number} p Percentage * @param {number} dir Direction (either 1 [=CW] or -1 [=CCW]) * @returns {number} */ function lerp(a, b, p, dir) { a = mod(a, SCALE); b = mod(b, SCALE); if (a === b) return a; // dir becomes an offset if we have to add a full revolution (=scale) if (!dir) dir = -SCALE; else if ((dir === 1) === a < b) dir *= SCALE; else dir = 0; return mod(a + p * (b - a - dir), SCALE); } exports.lerp = lerp; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQW5nbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3Bpbm9mZnMvQW5nbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsZ0NBQXdDO0FBRXhDLHNDQUFzQztBQUN0Qyw4REFBOEQ7QUFFOUQsSUFBTSxHQUFHLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUM7QUFDeEIsSUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDO0FBQ2xCLElBQU0sS0FBSyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQzFCLElBQU0sVUFBVSxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBRWhFOzs7Ozs7R0FNRztBQUNILFNBQVMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ2YsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUMzQixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxPQUFlO0lBQzlDLE9BQU8sQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQztBQUNuQyxDQUFDO0FBRkQsNENBRUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLGdCQUFnQixDQUFDLE9BQWU7SUFDOUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsR0FBRyxDQUFDLEdBQUcsT0FBTyxDQUFDO0FBQ25DLENBQUM7QUFGRCw0Q0FFQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsYUFBYSxDQUFDLENBQUM7SUFDN0IsSUFBSSxDQUFDLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBQztJQUVsQixPQUFPLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUMvQixDQUFDO0FBSkQsc0NBSUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLFNBQVMsQ0FBQyxDQUFDO0lBQ3pCLE9BQU8sR0FBRyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUN2QixDQUFDO0FBRkQsOEJBRUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFnQixpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsRUFBRTtJQUN4QyxJQUFJLENBQUMsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ2xCLGlGQUFpRjtJQUVqRixJQUFJLElBQUksS0FBSyxFQUFFLEVBQUU7UUFDZixPQUFPLENBQUMsQ0FBQztRQUNULG9DQUFvQztLQUNyQztTQUFNLElBQUksYUFBYSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRTtRQUMvQixPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTztLQUNuQjtTQUFNO1FBQ0wsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVE7S0FDcEI7QUFDSCxDQUFDO0FBWkQsOENBWUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsU0FBZ0IsT0FBTyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUM3Qix5Q0FBeUM7SUFFekMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDbEIsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDbEIsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFFbEIsSUFBSSxDQUFDLEdBQUcsQ0FBQztRQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ25DLGdEQUFnRDtJQUNoRCxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUMxQixDQUFDO0FBVkQsMEJBVUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUN2QixPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQztBQUNqQyxDQUFDO0FBRkQsb0JBRUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFnQixRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDM0IsSUFBSSxDQUFDLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBQztJQUVsQixhQUFhO0lBQ2IsZ0RBQWdEO0lBRWhELElBQUksSUFBSSxHQUFHLGFBQWEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFFaEMsSUFBSSxJQUFJLEdBQUcsQ0FBQztRQUFFLElBQUksR0FBRyxJQUFJLEdBQUcsS0FBSyxDQUFDO0lBRWxDLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUN4QixDQUFDO0FBWEQsNEJBV0M7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLEtBQUssQ0FBQyxDQUFDO0lBQ3JCLHVDQUF1QztJQUN2QyxPQUFPLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxHQUFHLEdBQUcsQ0FBQztBQUMzQixDQUFDO0FBSEQsc0JBR0M7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLEtBQUssQ0FBQyxDQUFDO0lBQ3JCLCtDQUErQztJQUMvQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxHQUFHLEdBQUcsQ0FBQztBQUMzQixDQUFDO0FBSEQsc0JBR0M7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLEtBQUssQ0FBQyxDQUFDO0lBQ3JCLHdDQUF3QztJQUN4QyxPQUFPLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxHQUFHLEdBQUcsQ0FBQztBQUMzQixDQUFDO0FBSEQsc0JBR0M7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFnQixVQUFVLENBQUMsR0FBRyxFQUFFLEdBQUc7SUFDakMsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUM7SUFFL0MsSUFBSSxHQUFHLEdBQUcsQ0FBQyxFQUFFO1FBQ1gsS0FBSyxHQUFHLEtBQUssR0FBRyxLQUFLLENBQUM7S0FDdkI7SUFDRCxPQUFPLEdBQUcsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDM0IsQ0FBQztBQVBELGdDQU9DO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBZ0IsU0FBUyxDQUFDLEVBQUUsRUFBRSxFQUFFO0lBQzlCLElBQUksS0FBSyxHQUFHLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUM7SUFFbkUsT0FBTyxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUM7QUFDL0IsQ0FBQztBQUpELDhCQUlDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSCxTQUFnQixRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSztJQUNyQyxJQUFJLGdCQUFXLENBQUMsQ0FBQyxDQUFDO1FBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLGtEQUFrRDtJQUU3RSxJQUFJLGdCQUFXLENBQUMsS0FBSyxDQUFDO1FBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLHVFQUF1RTtJQUUxRzs7Ozs7T0FLRztJQUVIOzs7OztPQUtHO0lBRUgsSUFBSSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUM7SUFFekMsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxFQUFFO1FBQy9DLE9BQU8sQ0FBQyxDQUFDO0tBQ1Y7SUFFRCxPQUFPLENBQUMsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsR0FBRyxLQUFLLEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQy9ELENBQUM7QUExQkQsNEJBMEJDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixPQUFPLENBQUMsTUFBTTtJQUM1QixTQUFTO0lBQ1QsVUFBVTtJQUNWLFdBQVc7SUFDWCxXQUFXO0lBRVgsSUFBSSxDQUFDLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQztJQUUxQixJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBRTNDLE9BQU8sVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNqQyxDQUFDO0FBWEQsMEJBV0M7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILFNBQWdCLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHO0lBQy9CLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2xCLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRWxCLElBQUksQ0FBQyxLQUFLLENBQUM7UUFBRSxPQUFPLENBQUMsQ0FBQztJQUV0QixxRUFBcUU7SUFDckUsSUFBSSxDQUFDLEdBQUc7UUFBRSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUM7U0FDbEIsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQztRQUFFLEdBQUcsSUFBSSxLQUFLLENBQUM7O1FBQ3hDLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFFYixPQUFPLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUMzQyxDQUFDO0FBWkQsb0JBWUMifQ==