-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathhelpers.js
109 lines (96 loc) · 3.38 KB
/
helpers.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/**
* Copyright 2012-2017, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
var Lib = require('../../lib');
var constants = require('./constants');
// look for either subplot or xaxis and yaxis attributes
exports.getSubplot = function getSubplot(trace) {
return trace.subplot || (trace.xaxis + trace.yaxis) || trace.geo;
};
// convenience functions for mapping all relevant axes
exports.flat = function flat(subplots, v) {
var out = new Array(subplots.length);
for(var i = 0; i < subplots.length; i++) {
out[i] = v;
}
return out;
};
exports.p2c = function p2c(axArray, v) {
var out = new Array(axArray.length);
for(var i = 0; i < axArray.length; i++) {
out[i] = axArray[i].p2c(v);
}
return out;
};
exports.getDistanceFunction = function getDistanceFunction(mode, dx, dy, dxy) {
if(mode === 'closest') return dxy || quadrature(dx, dy);
return mode === 'x' ? dx : dy;
};
exports.getClosest = function getClosest(cd, distfn, pointData) {
// do we already have a point number? (array mode only)
if(pointData.index !== false) {
if(pointData.index >= 0 && pointData.index < cd.length) {
pointData.distance = 0;
}
else pointData.index = false;
}
else {
// apply the distance function to each data point
// this is the longest loop... if this bogs down, we may need
// to create pre-sorted data (by x or y), not sure how to
// do this for 'closest'
for(var i = 0; i < cd.length; i++) {
var newDistance = distfn(cd[i]);
if(newDistance <= pointData.distance) {
pointData.index = i;
pointData.distance = newDistance;
}
}
}
return pointData;
};
// for bar charts and others with finite-size objects: you must be inside
// it to see its hover info, so distance is infinite outside.
// But make distance inside be at least 1/4 MAXDIST, and a little bigger
// for bigger bars, to prioritize scatter and smaller bars over big bars
//
// note that for closest mode, two inbox's will get added in quadrature
// args are (signed) difference from the two opposite edges
// count one edge as in, so that over continuous ranges you never get a gap
exports.inbox = function inbox(v0, v1) {
if(v0 * v1 < 0 || v0 === 0) {
return constants.MAXDIST * (0.6 - 0.3 / Math.max(3, Math.abs(v0 - v1)));
}
return Infinity;
};
function quadrature(dx, dy) {
return function(di) {
var x = dx(di),
y = dy(di);
return Math.sqrt(x * x + y * y);
};
}
/** Appends values inside array attributes corresponding to given point number
*
* @param {object} pointData : point data object (gets mutated here
* @param {object} trace : full trace object
* @param {number} ptNumber : point number
*/
exports.appendArrayPointValue = function(pointData, trace, ptNumber) {
var arrayAttrs = trace._arrayAttrs;
for(var i = 0; i < arrayAttrs.length; i++) {
var astr = arrayAttrs[i];
var key;
if(astr === 'ids') key = 'id';
else if(astr === 'location') key = 'location';
else key = astr;
if(pointData[key] === undefined) {
pointData[key] = Lib.nestedProperty(trace, astr).get()[ptNumber];
}
}
};