Comparing version 0.1.0 to 0.2.0
109
angles.js
/** | ||
* @license Angles.js v0.1.0 08/04/2016 | ||
* @license Angles.js v0.2.0 08/04/2016 | ||
* | ||
@@ -19,2 +19,13 @@ * Copyright (c) 2015, Robert Eisele (robert@xarg.org) | ||
/** | ||
* Mathematical modulo | ||
* | ||
* @param {number} x | ||
* @param {number} m | ||
* @returns {number} | ||
*/ | ||
function mod(x, m) { | ||
return (x % m + m) % m; | ||
} | ||
var Angles = { | ||
@@ -24,3 +35,3 @@ 'SCALE': 360, | ||
* Normalize an arbitrary angle to the interval [-180, 180) | ||
* | ||
* | ||
* @param {number} n | ||
@@ -32,9 +43,9 @@ * @returns {number} | ||
var c = this['SCALE']; | ||
var h = this['SCALE'] / 2; | ||
// return mod(a + 180, 360) - 180; | ||
return (n % c + c + h) % c - h; | ||
var h = c / 2; | ||
return mod(n + h, c) - h; | ||
}, | ||
/** | ||
* Normalize an arbitrary angle to the interval [0, 360) | ||
* | ||
* | ||
* @param {number} n | ||
@@ -46,9 +57,8 @@ * @returns {number} | ||
var c = this['SCALE']; | ||
var h = this['SCALE'] / 2; | ||
// return mod(a, 360); | ||
return (n % c + c) % c; | ||
return mod(n, c); | ||
}, | ||
/** | ||
* Gets the shortest direction to rotate to another angle | ||
* | ||
* | ||
* @param {number} from | ||
@@ -72,3 +82,3 @@ * @param {number} to | ||
* Checks if an angle is between two other angles | ||
* | ||
* | ||
* @param {number} n | ||
@@ -82,5 +92,5 @@ * @param {number} a | ||
var c = this['SCALE']; | ||
n = (n % c + c) % c; | ||
a = (a % c + c) % c; | ||
b = (b % c + c) % c; | ||
n = mod(n, c); | ||
a = mod(a, c); | ||
b = mod(b, c); | ||
@@ -103,3 +113,3 @@ if (a < b) | ||
* Calculate the minimal distance between two angles | ||
* | ||
* | ||
* @param {number} a | ||
@@ -112,2 +122,3 @@ * @param {number} b | ||
var m = this['SCALE']; | ||
var h = m / 2; | ||
@@ -119,3 +130,3 @@ // One-Liner: | ||
if (diff > m / 2) | ||
if (diff > h) | ||
diff = diff - m; | ||
@@ -127,3 +138,3 @@ | ||
* Calculate radians from current angle | ||
* | ||
* | ||
* @param {number} n | ||
@@ -138,3 +149,3 @@ * @returns {number} | ||
* Calculate degrees from current angle | ||
* | ||
* | ||
* @param {number} n | ||
@@ -149,3 +160,3 @@ * @returns {number} | ||
* Calculate gons from current angle | ||
* | ||
* | ||
* @param {number} n | ||
@@ -160,3 +171,3 @@ * @returns {number} | ||
* Given the sine and cosine of an angle, what is the original angle? | ||
* | ||
* | ||
* @param {number} sin | ||
@@ -174,8 +185,8 @@ * @param {number} cos | ||
} | ||
return (angle % s + s) % s; | ||
return mod(angle, s); | ||
}, | ||
/** | ||
* What is the angle of two points making a line | ||
* | ||
* @param {Array} p1 | ||
* | ||
* @param {Array} p1 | ||
* @param {Array} p2 | ||
@@ -187,9 +198,9 @@ * @returns {number} | ||
var s = this['SCALE']; | ||
var angle = (1 + Math.atan((p2[1] - p1[1]) / (p2[0] - p1[0])) / TAU) * s; | ||
var angle = (TAU + Math.atan2(p2[1] - p1[1], p2[0] - p1[0])) % TAU; | ||
return (angle % s + s) % s; | ||
return angle / TAU * s; | ||
}, | ||
/** | ||
* Returns the quadrant | ||
* | ||
* Returns the quadrant | ||
* | ||
* @param {number} x The point x-coordinate | ||
@@ -227,15 +238,11 @@ * @param {number} y The point y-coordinate | ||
var tmp = phi * s % (s / k); | ||
if (Math.abs(tmp) < EPS) { | ||
if (Math.abs(phi * s % (s / k)) < EPS) { | ||
return 0; | ||
} | ||
var tmp = Math.floor(k * shift / s + k * phi); | ||
return 1 + (tmp % k + k) % k; | ||
return 1 + mod(Math.floor(k * shift / s + k * phi), k); | ||
}, | ||
/** | ||
* Calculates the compass direction of the given angle | ||
* | ||
* | ||
* @param {number} angle | ||
@@ -251,3 +258,34 @@ * @returns {string} | ||
return DIRECTIONS[(dir % k + k) % 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} | ||
*/ | ||
'lerp': function(a, b, p, dir) { | ||
var c = this['SCALE']; | ||
a = mod(a, c); | ||
b = mod(b, c); | ||
if (a === b) | ||
return a; | ||
if (dir === 1) { | ||
if (a < b) | ||
return mod(a - p * (a - b + c), c); | ||
else | ||
return mod(a - p * (a - b), c); | ||
} else { | ||
if (a < b) | ||
return mod(a + p * (b - a), c); | ||
else | ||
return mod(a + p * (b - a + c), c); | ||
} | ||
} | ||
@@ -267,2 +305,1 @@ }; | ||
})(this); | ||
/* | ||
Angles.js v0.1.0 08/04/2016 | ||
Angles.js v0.2.0 08/04/2016 | ||
@@ -7,4 +7,4 @@ Copyright (c) 2015, Robert Eisele (robert@xarg.org) | ||
*/ | ||
'use strict';(function(h){var f=2*Math.PI,g="N NE E SE S SW W NW".split(" "),e={SCALE:360,normalizeHalf:function(a){var b=this.SCALE,c=this.SCALE/2;return(a%b+b+c)%b-c},normalize:function(a){var b=this.SCALE;return(a%b+b)%b},shortestDirection:function(a,b){return 0>this.normalizeHalf(a-b)?-1:1},between:function(a,b,c){var d=this.SCALE;a=(a%d+d)%d;b=(b%d+d)%d;c=(c%d+d)%d;return b<c?b<=a&&a<=c:b<=a||a<=c},diff:function(a,b){return Math.abs(b-a)%this.SCALE},distance:function(a,b){var c=this.SCALE,d= | ||
this.normalizeHalf(a-b);d>c/2&&(d=d-c);return Math.abs(d)},toRad:function(a){return a/this.SCALE*f},toDeg:function(a){return a/this.SCALE*360},toGon:function(a){return a/this.SCALE*400},fromSinCos:function(a,b){var c=this.SCALE,d=(1+Math.acos(b)/f)*c;0>a&&(d=c-d);return(d%c+c)%c},fromSlope:function(a,b){var c=this.SCALE;return((1+Math.atan((b[1]-a[1])/(b[0]-a[0]))/f)*c%c+c)%c},quadrant:function(a,b,c,d){var e=this.SCALE;void 0===c&&(c=4);void 0===d&&(d=0);a=(Math.atan2(b,a)+f)/f;return 1E-15>Math.abs(a* | ||
e%(e/c))?0:1+(Math.floor(c*d/e+c*a)%c+c)%c},compass:function(a){var b=g.length;return g[(Math.round(a/this.SCALE*b)%b+b)%b]}};"function"===typeof define&&define.amd?define([],function(){return e}):"object"===typeof exports?module.exports=e:h.Angles=e})(this); | ||
'use strict';(function(l){function f(a,b){return(a%b+b)%b}var g=2*Math.PI,k="N NE E SE S SW W NW".split(" "),h={SCALE:360,normalizeHalf:function(a){var b=this.SCALE,c=b/2;return f(a+c,b)-c},normalize:function(a){return f(a,this.SCALE)},shortestDirection:function(a,b){return 0>this.normalizeHalf(a-b)?-1:1},between:function(a,b,c){var e=this.SCALE;a=f(a,e);b=f(b,e);c=f(c,e);return b<c?b<=a&&a<=c:b<=a||a<=c},diff:function(a,b){return Math.abs(b-a)%this.SCALE},distance:function(a,b){var c=this.SCALE, | ||
e=c/2,d=this.normalizeHalf(a-b);d>e&&(d=d-c);return Math.abs(d)},toRad:function(a){return a/this.SCALE*g},toDeg:function(a){return a/this.SCALE*360},toGon:function(a){return a/this.SCALE*400},fromSinCos:function(a,b){var c=this.SCALE,e=(1+Math.acos(b)/g)*c;0>a&&(e=c-e);return f(e,c)},fromSlope:function(a,b){return(g+Math.atan2(b[1]-a[1],b[0]-a[0]))%g/g*this.SCALE},quadrant:function(a,b,c,e){var d=this.SCALE;void 0===c&&(c=4);void 0===e&&(e=0);a=(Math.atan2(b,a)+g)/g;return 1E-15>Math.abs(a*d%(d/c))? | ||
0:1+f(Math.floor(c*e/d+c*a),c)},compass:function(a){var b=k.length;return k[f(Math.round(a/this.SCALE*b),b)]},lerp:function(a,b,c,e){var d=this.SCALE;a=f(a,d);b=f(b,d);return a===b?a:1===e?a<b?f(a-c*(a-b+d),d):f(a-c*(a-b),d):a<b?f(a+c*(b-a),d):f(a+c*(b-a+d),d)}};"function"===typeof define&&define.amd?define([],function(){return h}):"object"===typeof exports?module.exports=h:l.Angles=h})(this); |
{ | ||
"name": "angle", | ||
"main": "angles.js", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"homepage": "https://github.com/infusion/Angles.js", | ||
@@ -6,0 +6,0 @@ "description": "A function collection for working with angles", |
{ | ||
"name": "angles", | ||
"title": "angles.js", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"homepage": "https://github.com/infusion/Angles.js", | ||
"bugs": "https://github.com/infusion/Angles.js/issues", | ||
"description": "A function collection for working with angles", | ||
"keywords": ["degree", "degrees", "convert", "radians", "direction", "geo", "compass", "cardinal", "slope", "angle", "angles", "angular", "between"], | ||
"keywords": ["degree", "degrees", "convert", "lerp", "radians", "direction", "geo", "compass", "cardinal", "slope", "angle", "angles", "angular", "between"], | ||
"author": "Robert Eisele <robert@xarg.org> (http://www.xarg.org/)", | ||
@@ -10,0 +10,0 @@ "main": "angles", |
@@ -20,2 +20,18 @@ # Angles.js | ||
Simply calculate the linear interpolation of the smaller angle. | ||
```javascript | ||
var a = -30; // 330° | ||
var b = 30; | ||
var pct = 0.5; // Percentage between a and b | ||
angles.SCALE = 360; | ||
var dir = angles.shortestDirection(a, b); // -1 => Rotate CCW | ||
console.log(angles.lerp(a, b, pct, dir)); // => 0 | ||
``` | ||
Having the scale configurable opens a lot of possibilities, like calculating clock-angles: | ||
@@ -28,4 +44,4 @@ | ||
var m = time.getMinutes(); | ||
var h = time.getHours() / 24 * 60; | ||
console.log(angles.between(s, m, h)); // true or false | ||
var h = time.getHours() / 23 * 59; | ||
console.log(angles.between(s, m, h)); // true or false, if seconds clockhand is between the minutes and hours clockhand | ||
``` | ||
@@ -57,2 +73,6 @@ | ||
lerp(a, b, p[, dir=1]) | ||
--- | ||
Calculates the linear interpolation of two angles | ||
distance(a, b) | ||
@@ -107,9 +127,9 @@ --- | ||
```html | ||
<script src="fraction.js"></script> | ||
<script src="angles.js"></script> | ||
<script> | ||
console.log(Fraction("123/456")); | ||
console.log(Angles.normalize(128)); | ||
</script> | ||
``` | ||
Using Fraction.js with require.js | ||
Using Angles.js with require.js | ||
=== | ||
@@ -119,5 +139,5 @@ ```html | ||
<script> | ||
requirejs(['fraction.js'], | ||
function(Fraction) { | ||
console.log(Fraction("123/456")); | ||
requirejs(['angles.js'], | ||
function(Angles) { | ||
console.log(Angles.normalize(128)); | ||
}); | ||
@@ -129,3 +149,3 @@ </script> | ||
=== | ||
As every library I publish, fraction.js is also built to be as small as possible after compressing it with Google Closure Compiler in advanced mode. Thus the coding style orientates a little on maxing-out the compression rate. Please make sure you keep this style if you plan to extend the library. | ||
As every library I publish, Angles.js is also built to be as small as possible after compressing it with Google Closure Compiler in advanced mode. Thus the coding style orientates a little on maxing-out the compression rate. Please make sure you keep this style if you plan to extend the library. | ||
@@ -132,0 +152,0 @@ Testing |
@@ -6,35 +6,52 @@ | ||
var tests = [ | ||
{m: angles.between, p: [38, 13, 45], r: true, s: 360}, | ||
{m: angles.between, p: [38, 40, 45], r: false, s: 360}, | ||
{m: angles.between, p: [12, 5, 18], r: true, s: 60}, | ||
{m: angles.between, p: [15, 2, 18], r: true, s: 12}, | ||
{m: angles.between, p: [38 + 360 * 3, 13 - 360 * 2, 45 + 360], r: true, s: 360}, | ||
{m: angles.toRad, p: [90], r: Math.PI / 2, s: 360}, | ||
{m: angles.toDeg, p: [Math.PI], r: 180, s: Math.PI * 2}, | ||
{m: angles.toRad, p: [180], r: Math.PI, s: 360}, | ||
{m: angles.toDeg, p: [Math.PI], r: 180, s: Math.PI * 2}, | ||
{m: angles.distance, p: [1, 359], r: 2, s: 360}, | ||
{m: angles.distance, p: [358, 1], r: 3, s: 360}, | ||
{m: angles.distance, p: [18, 25], r: 7, s: 360}, | ||
{m: angles.distance, p: [1, 359], r: 2, s: 360}, | ||
{m: angles.normalize, p: [55], r: 55, s: 360}, | ||
{m: angles.normalize, p: [55 + 360], r: 55, s: 360}, | ||
{m: angles.normalize, p: [-55], r: 305, s: 360}, | ||
{m: angles.normalize, p: [-190], r: 170, s: 360}, | ||
{m: angles.normalizeHalf, p: [55], r: 55, s: 360}, | ||
{m: angles.normalizeHalf, p: [55 + 360], r: 55, s: 360}, | ||
{m: angles.normalizeHalf, p: [-55], r: -55, s: 360}, | ||
{m: angles.normalizeHalf, p: [-190], r: 170, s: 360}, | ||
{m: angles.fromSlope, p: [[1, 1], [5, 10]], r: 66.03751102542185, s: 360}, | ||
{m: angles.fromSlope, p: [[124, 8984], [234, 10322]], r: 85.30015415271288, s: 360}, | ||
{m: angles.fromSlope, p: [[424, 8984], [234, 10322]], r: 278.0821360367614, s: 360}, | ||
{m: angles.fromSlope, p: [[345, -78445], [3475890, 8495]], r: 1.4329425927144825, s: 360}, | ||
{m: angles.shortestDirection, p: [50, 60], r: -1, s: 360}, | ||
{m: angles.shortestDirection, p: [60, 50], r: 1, s: 360}, | ||
{m: angles.shortestDirection, p: [60 + 360 * 3, 50 + 360 * 7], r: 1, s: 360}, | ||
{m: angles.shortestDirection, p: [60 - 360 * 3, 50 - 360 * 7], r: 1, s: 360}, | ||
{m: angles.fromSinCos, p: [Math.sin(0.3), Math.cos(0.3)], r: 0.3, s: Math.PI * 2}, | ||
{m: angles.fromSinCos, p: [Math.sin(-0.3), Math.cos(-0.3)], r: Math.PI * 2 - 0.3, s: Math.PI * 2}, | ||
{m: angles.fromSinCos, p: [Math.sin(0.7), Math.cos(0.7)], r: 0.7, s: Math.PI * 2}, | ||
{m: angles.fromSinCos, p: [Math.sin(-0.7), Math.cos(-0.7)], r: Math.PI * 2 - 0.7, s: Math.PI * 2} | ||
{m: 'between', p: [38, 13, 45], r: true, s: 360}, | ||
{m: 'between', p: [38, 40, 45], r: false, s: 360}, | ||
{m: 'between', p: [12, 5, 18], r: true, s: 60}, | ||
{m: 'between', p: [15, 2, 18], r: true, s: 12}, | ||
{m: 'between', p: [38 + 360 * 3, 13 - 360 * 2, 45 + 360], r: true, s: 360}, | ||
{m: 'toRad', p: [90], r: Math.PI / 2, s: 360}, | ||
{m: 'toDeg', p: [Math.PI], r: 180, s: Math.PI * 2}, | ||
{m: 'toRad', p: [180], r: Math.PI, s: 360}, | ||
{m: 'toDeg', p: [Math.PI], r: 180, s: Math.PI * 2}, | ||
{m: 'distance', p: [1, 359], r: 2, s: 360}, | ||
{m: 'distance', p: [358, 1], r: 3, s: 360}, | ||
{m: 'distance', p: [18, 25], r: 7, s: 360}, | ||
{m: 'distance', p: [1, 359], r: 2, s: 360}, | ||
{m: 'normalize', p: [55], r: 55, s: 360}, | ||
{m: 'normalize', p: [55 + 360], r: 55, s: 360}, | ||
{m: 'normalize', p: [-55], r: 305, s: 360}, | ||
{m: 'normalize', p: [-190], r: 170, s: 360}, | ||
{m: 'normalizeHalf', p: [55], r: 55, s: 360}, | ||
{m: 'normalizeHalf', p: [55 + 360], r: 55, s: 360}, | ||
{m: 'normalizeHalf', p: [-55], r: -55, s: 360}, | ||
{m: 'normalizeHalf', p: [-190], r: 170, s: 360}, | ||
{m: 'fromSlope', p: [[1, 1], [5, 10]], r: 66.03751102542182, s: 360}, | ||
{m: 'fromSlope', p: [[124, 8984], [234, 10322]], r: 85.30015415271286, s: 360}, | ||
{m: 'fromSlope', p: [[424, 8984], [234, 10322]], r: 98.08213603676147, s: 360}, | ||
{m: 'fromSlope', p: [[345, -78445], [3475890, 8495]], r: 1.4329425927144732, s: 360}, | ||
{m: 'shortestDirection', p: [50, 60], r: -1, s: 360}, | ||
{m: 'shortestDirection', p: [60, 50], r: 1, s: 360}, | ||
{m: 'shortestDirection', p: [60 + 360 * 3, 50 + 360 * 7], r: 1, s: 360}, | ||
{m: 'shortestDirection', p: [60 - 360 * 3, 50 - 360 * 7], r: 1, s: 360}, | ||
{m: 'fromSinCos', p: [Math.sin(0.3), Math.cos(0.3)], r: 0.3, s: Math.PI * 2}, | ||
{m: 'fromSinCos', p: [Math.sin(-0.3), Math.cos(-0.3)], r: Math.PI * 2 - 0.3, s: Math.PI * 2}, | ||
{m: 'fromSinCos', p: [Math.sin(0.7), Math.cos(0.7)], r: 0.7, s: Math.PI * 2}, | ||
{m: 'fromSinCos', p: [Math.sin(-0.7), Math.cos(-0.7)], r: Math.PI * 2 - 0.7, s: Math.PI * 2}, | ||
{m: 'lerp', p: [45, 135, 0.4, -1], r: 81, s: 360}, | ||
{m: 'lerp', p: [0, Math.PI * 2, 0.5], r: 0, s: Math.PI * 2}, | ||
{m: 'lerp', p: [0, Math.PI, 0.5, -1], r: Math.PI * 0.5, s: Math.PI * 2}, | ||
{m: 'lerp', p: [45, 360 + 315, 0.5, -1], r: 180, s: 360}, | ||
{m: 'lerp', p: [45, 360 + 315, 0.5, 1], r: 0, s: 360}, | ||
{m: 'lerp', p: [45, 360 + 315, 0, -1], r: 45, s: 360}, | ||
{m: 'lerp', p: [45, 360 + 315, 1, -1], r: 315, s: 360}, | ||
{m: 'lerp', p: [30, 90, 0.25, -1], r: 45, s: 360}, | ||
{m: 'lerp', p: [30, 90, 0.25, 1], r: 315, s: 360}, | ||
{m: 'lerp', p: [300, 60, 0.25, -1], r: 330, s: 360}, | ||
{m: 'lerp', p: [300, 60, 0.25, 1], r: 240, s: 360}, | ||
{m: 'lerp', p: [-30, 30, 0.5, -1], r: 0, s: 360}, | ||
{m: 'lerp', p: [-30, 30, 0.5, 1], r: 180, s: 360}, | ||
{m: 'lerp', p: [-30, 30, 0.25, -1], r: 345, s: 360}, | ||
{m: 'lerp', p: [-30, 30, 0.25, 1], r: 255, s: 360}, | ||
{m: 'lerp', p: [10, 10, 0.5, -1], r: 10, s: 360}, | ||
{m: 'lerp', p: [10, 10, 0.5, 1], r: 10, s: 360}, | ||
]; | ||
@@ -75,3 +92,3 @@ | ||
tests.push({m: angles.quadrant, p: [ | ||
tests.push({m: 'quadrant', p: [ | ||
Math.cos(i / 180 * Math.PI), | ||
@@ -81,3 +98,3 @@ Math.sin(i / 180 * Math.PI) | ||
tests.push({m: angles.compass, p: [i], r: dir, s: 360, label: 'Direction of angle ' + i}); | ||
tests.push({m: 'compass', p: [i], r: dir, s: 360, label: 'Direction of angle ' + i}); | ||
} | ||
@@ -91,10 +108,10 @@ | ||
it('Should work with test ' + (tests[i].label || "#" + i), function() { | ||
it('Should work with ' + (tests[i].label || "->" + tests[i].m + "(" + tests[i].p.join(", ") + ")"), function() { | ||
var c = tests[i]; | ||
angles.SCALE = c.s; | ||
if (typeof c.r === 'string') | ||
c.m.apply(angles, c.p).should.be.equal(c.r); | ||
if (typeof c.r !== 'number') | ||
angles[c.m].apply(angles, c.p).should.be.equal(c.r); | ||
else | ||
c.m.apply(angles, c.p).should.be.approximately(c.r, 1e-15); | ||
angles[c.m].apply(angles, c.p).should.be.approximately(c.r, 1e-15); | ||
}); | ||
@@ -104,2 +121,2 @@ | ||
} | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19039
414
158