Skip to content

Commit 4d20388

Browse files
committed
move a few things to lib/angles.js + add isPtInsideSector
1 parent eb9307e commit 4d20388

File tree

3 files changed

+117
-41
lines changed

3 files changed

+117
-41
lines changed

src/lib/angles.js

+103-9
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,119 @@
1010

1111
var PI = Math.PI;
1212

13-
exports.deg2rad = function(deg) {
13+
function deg2rad(deg) {
1414
return deg / 180 * PI;
15-
};
15+
}
1616

17-
exports.rad2deg = function(rad) {
17+
function rad2deg(rad) {
1818
return rad / PI * 180;
19-
};
19+
}
2020

21-
exports.wrap360 = function(deg) {
21+
function wrap360(deg) {
2222
var out = deg % 360;
2323
return out < 0 ? out + 360 : out;
24-
};
24+
}
2525

26-
exports.wrap180 = function(deg) {
26+
function wrap180(deg) {
2727
if(Math.abs(deg) > 180) deg -= Math.round(deg / 360) * 360;
2828
return deg;
29-
};
29+
}
3030

31-
exports.isFullCircle = function(sector) {
31+
/* is sector a full circle?
32+
* ... this comes up a lot in SVG path-drawing routines
33+
*
34+
* @param {2-item array} sector sector angles in *degrees*
35+
* @return {boolean}
36+
*/
37+
function isFullCircle(sector) {
3238
var arc = Math.abs(sector[1] - sector[0]);
3339
return arc === 360;
40+
}
41+
42+
/* angular delta between angle 'a' and 'b'
43+
*
44+
* solution taken from: https://stackoverflow.com/a/2007279
45+
*
46+
* @param {number} a : first angle in *radians*
47+
* @param {number} b : second angle in *radians*
48+
* @return {number} angular delta in *radians*
49+
*/
50+
function angleDelta(a, b) {
51+
var d = b - a;
52+
return Math.atan2(Math.sin(d), Math.cos(d));
53+
}
54+
55+
/* angular distance between angle 'a' and 'b'
56+
*
57+
* @param {number} a : first angle in *radians*
58+
* @param {number} b : second angle in *radians*
59+
* @return {number} angular distance in *radians*
60+
*/
61+
function angleDist(a, b) {
62+
return Math.abs(angleDelta(a, b));
63+
}
64+
65+
/* is angle inside sector?
66+
*
67+
* @param {number} a : angle to test in *radians*
68+
* @param {2-item array} sector : sector angles in *degrees*
69+
* @param {boolean}
70+
*/
71+
function isAngleInsideSector(a, sector) {
72+
if(isFullCircle(sector)) return true;
73+
74+
var s0, s1;
75+
76+
if(sector[0] < sector[1]) {
77+
s0 = sector[0];
78+
s1 = sector[1];
79+
} else {
80+
s0 = sector[1];
81+
s1 = sector[0];
82+
}
83+
84+
s0 = wrap360(s0);
85+
s1 = wrap360(s1);
86+
if(s0 > s1) s1 += 360;
87+
88+
var a0 = wrap360(rad2deg(a));
89+
var a1 = a0 + 360;
90+
91+
return (a0 >= s0 && a0 <= s1) || (a1 >= s0 && a1 <= s1);
92+
}
93+
94+
/* is pt (r,a) inside sector?
95+
*
96+
* @param {number} r : pt's radial coordinate
97+
* @param {number} a : pt's angular coordinate in *radians*
98+
* @param {2-item array} rRng : sector's radial range
99+
* @param {2-item array} sector : sector angles in *degrees*
100+
* @return {boolean}
101+
*/
102+
function isPtInsideSector(r, a, rRng, sector) {
103+
if(!isAngleInsideSector(a, sector)) return false;
104+
105+
var r0, r1;
106+
107+
if(rRng[0] < rRng[1]) {
108+
r0 = rRng[0];
109+
r1 = rRng[1];
110+
} else {
111+
r0 = rRng[1];
112+
r1 = rRng[0];
113+
}
114+
115+
return r >= r0 && r <= r1;
116+
}
117+
118+
module.exports = {
119+
deg2rad: deg2rad,
120+
rad2deg: rad2deg,
121+
wrap360: wrap360,
122+
wrap180: wrap180,
123+
angleDelta: angleDelta,
124+
angleDist: angleDist,
125+
isFullCircle: isFullCircle,
126+
isAngleInsideSector: isAngleInsideSector,
127+
isPtInsideSector: isPtInsideSector
34128
};

src/lib/index.js

+4
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,11 @@ lib.deg2rad = anglesModule.deg2rad;
8787
lib.rad2deg = anglesModule.rad2deg;
8888
lib.wrap360 = anglesModule.wrap360;
8989
lib.wrap180 = anglesModule.wrap180;
90+
lib.angleDelta = anglesModule.angleDelta;
91+
lib.angleDist = anglesModule.angleDist;
9092
lib.isFullCircle = anglesModule.isFullCircle;
93+
lib.isAngleInsideSector = anglesModule.isAngleInsideSector;
94+
lib.isPtInsideSector = anglesModule.isPtInsideSector;
9195

9296
var geom2dModule = require('./geometry2d');
9397
lib.segmentsIntersect = geom2dModule.segmentsIntersect;

src/plots/polar/polar.js

+10-32
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ var rad2deg = Lib.rad2deg;
3838
var wrap360 = Lib.wrap360;
3939
var wrap180 = Lib.wrap180;
4040
var isFullCircle = Lib.isFullCircle;
41+
var isAngleInsideSector = Lib.isAngleInsideSector;
42+
var angleDelta = Lib.angleDelta;
4143

4244
function Polar(gd, id) {
4345
this.id = id;
@@ -501,7 +503,9 @@ proto.updateAngularAxis = function(fullLayout, polarLayout) {
501503
// the range w.r.t sector, so that sectors that cross 360 can
502504
// show all their ticks.
503505
if(ax.type === 'category') {
504-
ax._tickFilter = function(d) { return isAngleInSector(t2g(d), sector); };
506+
ax._tickFilter = function(d) {
507+
return isAngleInsideSector(t2g(d), sector);
508+
};
505509
}
506510

507511
ax._transfn = function(d) {
@@ -1194,16 +1198,12 @@ proto.updateAngularDrag = function(fullLayout, polarLayout) {
11941198

11951199
proto.isPtInside = function(d) {
11961200
var sector = this.sector;
1197-
var thetag = this.angularAxis.c2g(d.theta);
1198-
1199-
if(!isAngleInSector(thetag, sector)) {
1200-
return false;
1201-
}
1202-
12031201
var vangles = this.vangles;
1202+
var thetag = this.angularAxis.c2g(d.theta);
12041203
var radialAxis = this.radialAxis;
12051204
var radialRange = radialAxis.range;
12061205
var r = radialAxis.c2r(d.r);
1206+
var rRng = radialAxis.range;
12071207

12081208
var r0, r1;
12091209
if(radialRange[1] >= radialRange[0]) {
@@ -1214,6 +1214,7 @@ proto.isPtInside = function(d) {
12141214
r1 = radialRange[0];
12151215
}
12161216

1217+
return Lib.isPtInsideSector(r, thetag, rRng, sector);
12171218
if(vangles) {
12181219
var polygonIn = polygonTester(makePolygon(r0, sector, vangles));
12191220
var polygonOut = polygonTester(makePolygon(r1, sector, vangles));
@@ -1291,35 +1292,12 @@ function computeSectorBBox(sector) {
12911292
return [x0, y0, x1, y1];
12921293
}
12931294

1294-
function isAngleInSector(rad, sector) {
1295-
if(isFullCircle(sector)) return true;
1296-
1297-
var s0 = wrap360(sector[0]);
1298-
var s1 = wrap360(sector[1]);
1299-
if(s0 > s1) s1 += 360;
1300-
1301-
var deg = wrap360(rad2deg(rad));
1302-
var nextTurnDeg = deg + 360;
1303-
1304-
return (deg >= s0 && deg <= s1) ||
1305-
(nextTurnDeg >= s0 && nextTurnDeg <= s1);
1306-
}
1307-
13081295
function snapToVertexAngle(a, vangles) {
1309-
function angleDeltaAbs(va) {
1310-
return Math.abs(angleDelta(a, va));
1311-
}
1312-
1313-
var ind = findIndexOfMin(vangles, angleDeltaAbs);
1296+
var fn = function(v) { return Lib.angleDist(a, v); };
1297+
var ind = findIndexOfMin(vangles, fn);
13141298
return vangles[ind];
13151299
}
13161300

1317-
// taken from https://stackoverflow.com/a/2007279
1318-
function angleDelta(a, b) {
1319-
var d = b - a;
1320-
return Math.atan2(Math.sin(d), Math.cos(d));
1321-
}
1322-
13231301
function findIndexOfMin(arr, fn) {
13241302
fn = fn || Lib.identity;
13251303

0 commit comments

Comments
 (0)