gpml2pvjson
Version:
convert GPML (XML) to pvjson (json)
244 lines • 11.8 kB
JavaScript
import { isUndefined } from "lodash/fp";
// based on code drawn from this repo:
// https://github.com/infusion/Angles.js/blob/master/angles.js
const TAU = 2 * Math.PI;
const EPS = 1e-15;
const SCALE = 2 * Math.PI;
const 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
*/
export function radiansToDegrees(radians) {
return (180 / Math.PI) * radians;
}
/**
* Convert from degrees to radians
*
* @param {number} degrees
* @returns {number} radians
*/
export function degreesToRadians(degrees) {
return (Math.PI / 180) * degrees;
}
/**
* Normalize an arbitrary angle to the interval [-180, 180)
*
* @param {number} n
* @returns {number}
*/
export function normalizeHalf(n) {
var h = SCALE / 2;
return mod(n + h, SCALE) - h;
}
/**
* Normalize an arbitrary angle to the interval [0, 360)
*
* @param {number} n
* @returns {number}
*/
export function normalize(n) {
return mod(n, SCALE);
}
/**
* Gets the shortest direction to rotate to another angle
*
* @param {number} from
* @param {number} to
* @returns {number}
*/
export 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
}
}
/**
* Checks if an angle is between two other angles
*
* @param {number} n
* @param {number} a
* @param {number} b
* @returns {boolean}
*/
export 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;
}
/**
* Calculates the angular difference between two angles
* @param {number} a
* @param {number} b
* @returns {number}
*/
export function diff(a, b) {
return Math.abs(b - a) % SCALE;
}
/**
* Calculate the minimal distance between two angles
*
* @param {number} a
* @param {number} b
* @returns {number}
*/
export 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);
}
/**
* Calculate radians from current angle
*
* @param {number} n
* @returns {number}
*/
export function toRad(n) {
// https://en.wikipedia.org/wiki/Radian
return (n / SCALE) * TAU;
}
/**
* Calculate degrees from current angle
*
* @param {number} n
* @returns {number}
*/
export function toDeg(n) {
// https://en.wikipedia.org/wiki/Degree_(angle)
return (n / SCALE) * 360;
}
/**
* Calculate gons from current angle
*
* @param {number} n
* @returns {number}
*/
export function toGon(n) {
// https://en.wikipedia.org/wiki/Gradian
return (n / SCALE) * 400;
}
/**
* Given the sine and cosine of an angle, what is the original angle?
*
* @param {number} sin
* @param {number} cos
* @returns {number}
*/
export function fromSinCos(sin, cos) {
var angle = (1 + Math.acos(cos) / TAU) * SCALE;
if (sin < 0) {
angle = SCALE - angle;
}
return mod(angle, SCALE);
}
/**
* What is the angle of two points making a line
*
* @param {Array} p1
* @param {Array} p2
* @returns {number}
*/
export function fromSlope(p1, p2) {
var angle = (TAU + Math.atan2(p2[1] - p1[1], p2[0] - p1[0])) % TAU;
return (angle / TAU) * SCALE;
}
/**
* 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}
*/
export function quadrant(x, y, k, shift) {
if (isUndefined(k))
k = 4; // How many regions? 4 = quadrant, 8 = octant, ...
if (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);
}
/**
* Calculates the compass direction of the given angle
*
* @param {number} angle
* @returns {string}
*/
export 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)];
}
/**
* 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}
*/
export 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);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQW5nbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3Bpbm9mZnMvQW5nbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUV4QyxzQ0FBc0M7QUFDdEMsOERBQThEO0FBRTlELE1BQU0sR0FBRyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQ3hCLE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQztBQUNsQixNQUFNLEtBQUssR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQztBQUMxQixNQUFNLFVBQVUsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztBQUVoRTs7Ozs7O0dBTUc7QUFDSCxTQUFTLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNmLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDM0IsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLE9BQWU7SUFDOUMsT0FBTyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDO0FBQ25DLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxPQUFlO0lBQzlDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLEdBQUcsQ0FBQyxHQUFHLE9BQU8sQ0FBQztBQUNuQyxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsYUFBYSxDQUFDLENBQUM7SUFDN0IsSUFBSSxDQUFDLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBQztJQUVsQixPQUFPLEdBQUcsQ0FBQyxDQUFD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