6
6
* LICENSE file in the root directory of this source tree.
7
7
*/
8
8
9
-
10
9
'use strict' ;
11
10
12
11
var isNumeric = require ( 'fast-isnumeric' ) ;
13
12
14
13
var Lib = require ( '../../lib' ) ;
15
14
var FP_SAFE = require ( '../../constants/numerical' ) . FP_SAFE ;
16
15
16
+ var Registry = require ( '../../registry' ) ;
17
+
17
18
module . exports = {
18
19
getAutoRange : getAutoRange ,
19
20
makePadFn : makePadFn ,
@@ -22,59 +23,77 @@ module.exports = {
22
23
findExtremes : findExtremes
23
24
} ;
24
25
25
- // Find the autorange for this axis
26
- //
27
- // assumes ax._min and ax._max have already been set by calling axes.expand
28
- // using calcdata from all traces. These are arrays of objects:
29
- // {
30
- // val: calcdata value,
31
- // pad: extra pixels beyond this value,
32
- // extrapad: bool, does this point want 5% extra padding
33
- // }
34
- //
35
- // Returns an array of [min, max]. These are calcdata for log and category axes
36
- // and data for linear and date axes.
37
- //
38
- // TODO: we want to change log to data as well, but it's hard to do this
39
- // maintaining backward compatibility. category will always have to use calcdata
40
- // though, because otherwise values between categories (or outside all categories)
41
- // would be impossible.
42
- function getAutoRange ( ax ) {
26
+ /**
27
+ * getAutoRange
28
+ *
29
+ * Collects all _extremes values corresponding to a given axis
30
+ * and computes its auto range.
31
+ *
32
+ * getAutoRange uses return values from findExtremes where:
33
+ *
34
+ * {
35
+ * val: calcdata value,
36
+ * pad: extra pixels beyond this value,
37
+ * extrapad: bool, does this point want 5% extra padding
38
+ * }
39
+ *
40
+ * @param {object } gd:
41
+ * graph div object with filled in fullData and fullLayout,
42
+ * @param {object } ax:
43
+ * full axis object
44
+ * @return {array }
45
+ * an array of [min, max]. These are calcdata for log and category axes
46
+ * and data for linear and date axes.
47
+ *
48
+ * TODO: we want to change log to data as well, but it's hard to do this
49
+ * maintaining backward compatibility. category will always have to use calcdata
50
+ * though, because otherwise values between categories (or outside all categories)
51
+ * would be impossible.
52
+ */
53
+ function getAutoRange ( gd , ax ) {
54
+ var i , j ;
43
55
var newRange = [ ] ;
44
- var minmin = ax . _min [ 0 ] . val ;
45
- var maxmax = ax . _max [ 0 ] . val ;
46
- var mbest = 0 ;
47
- var axReverse = false ;
48
56
49
57
var getPad = makePadFn ( ax ) ;
58
+ var minArray = concatExtremes ( gd , ax , 'min' ) ;
59
+ var maxArray = concatExtremes ( gd , ax , 'max' ) ;
50
60
51
- var i , j , minpt , maxpt , minbest , maxbest , dp , dv ;
61
+ if ( minArray . length === 0 || maxArray . length === 0 ) {
62
+ return Lib . simpleMap ( ax . range , ax . r2l ) ;
63
+ }
52
64
53
- for ( i = 1 ; i < ax . _min . length ; i ++ ) {
65
+ var minmin = minArray [ 0 ] . val ;
66
+ var maxmax = maxArray [ 0 ] . val ;
67
+
68
+ for ( i = 1 ; i < minArray . length ; i ++ ) {
54
69
if ( minmin !== maxmax ) break ;
55
- minmin = Math . min ( minmin , ax . _min [ i ] . val ) ;
70
+ minmin = Math . min ( minmin , minArray [ i ] . val ) ;
56
71
}
57
- for ( i = 1 ; i < ax . _max . length ; i ++ ) {
72
+ for ( i = 1 ; i < maxArray . length ; i ++ ) {
58
73
if ( minmin !== maxmax ) break ;
59
- maxmax = Math . max ( maxmax , ax . _max [ i ] . val ) ;
74
+ maxmax = Math . max ( maxmax , maxArray [ i ] . val ) ;
60
75
}
61
76
77
+ var axReverse = false ;
78
+
62
79
if ( ax . range ) {
63
80
var rng = Lib . simpleMap ( ax . range , ax . r2l ) ;
64
81
axReverse = rng [ 1 ] < rng [ 0 ] ;
65
82
}
66
-
67
83
// one-time setting to easily reverse the axis
68
84
// when plotting from code
69
85
if ( ax . autorange === 'reversed' ) {
70
86
axReverse = true ;
71
87
ax . autorange = true ;
72
88
}
73
89
74
- for ( i = 0 ; i < ax . _min . length ; i ++ ) {
75
- minpt = ax . _min [ i ] ;
76
- for ( j = 0 ; j < ax . _max . length ; j ++ ) {
77
- maxpt = ax . _max [ j ] ;
90
+ var mbest = 0 ;
91
+ var minpt , maxpt , minbest , maxbest , dp , dv ;
92
+
93
+ for ( i = 0 ; i < minArray . length ; i ++ ) {
94
+ minpt = minArray [ i ] ;
95
+ for ( j = 0 ; j < maxArray . length ; j ++ ) {
96
+ maxpt = maxArray [ j ] ;
78
97
dv = maxpt . val - minpt . val ;
79
98
dp = ax . _length - getPad ( minpt ) - getPad ( maxpt ) ;
80
99
if ( dv > 0 && dp > 0 && dv / dp > mbest ) {
@@ -90,11 +109,9 @@ function getAutoRange(ax) {
90
109
var upper = minmin + 1 ;
91
110
if ( ax . rangemode === 'tozero' ) {
92
111
newRange = minmin < 0 ? [ lower , 0 ] : [ 0 , upper ] ;
93
- }
94
- else if ( ax . rangemode === 'nonnegative' ) {
112
+ } else if ( ax . rangemode === 'nonnegative' ) {
95
113
newRange = [ Math . max ( 0 , lower ) , Math . max ( 0 , upper ) ] ;
96
- }
97
- else {
114
+ } else {
98
115
newRange = [ lower , upper ] ;
99
116
}
100
117
}
@@ -134,11 +151,9 @@ function getAutoRange(ax) {
134
151
if ( ax . rangemode === 'tozero' ) {
135
152
if ( newRange [ 0 ] < 0 ) {
136
153
newRange = [ newRange [ 0 ] , 0 ] ;
137
- }
138
- else if ( newRange [ 0 ] > 0 ) {
154
+ } else if ( newRange [ 0 ] > 0 ) {
139
155
newRange = [ 0 , newRange [ 0 ] ] ;
140
- }
141
- else {
156
+ } else {
142
157
newRange = [ 0 , 1 ] ;
143
158
}
144
159
}
@@ -174,15 +189,68 @@ function makePadFn(ax) {
174
189
return function getPad ( pt ) { return pt . pad + ( pt . extrapad ? extrappad : 0 ) ; } ;
175
190
}
176
191
177
- function doAutoRange ( ax ) {
192
+ function concatExtremes ( gd , ax , ext ) {
193
+ var i ;
194
+ var out = [ ] ;
195
+
196
+ var fullData = gd . _fullData ;
197
+
198
+ // should be general enough for 3d, polar etc.
199
+
200
+ for ( i = 0 ; i < fullData . length ; i ++ ) {
201
+ var trace = fullData [ i ] ;
202
+ var extremes = trace . _extremes ;
203
+
204
+ if ( trace . visible === true ) {
205
+ if ( Registry . traceIs ( trace , 'cartesian' ) ) {
206
+ var axId = ax . _id ;
207
+ if ( extremes [ axId ] ) {
208
+ out = out . concat ( extremes [ axId ] [ ext ] ) ;
209
+ }
210
+ } else if ( Registry . traceIs ( trace , 'polar' ) ) {
211
+ if ( trace . subplot === ax . _subplot ) {
212
+ out = out . concat ( extremes [ ax . _name ] [ ext ] ) ;
213
+ }
214
+ }
215
+ }
216
+ }
217
+
218
+ var fullLayout = gd . _fullLayout ;
219
+ var annotations = fullLayout . annotations ;
220
+ var shapes = fullLayout . shapes ;
221
+
222
+ if ( Array . isArray ( annotations ) ) {
223
+ out = out . concat ( concatComponentExtremes ( annotations , ax , ext ) ) ;
224
+ }
225
+ if ( Array . isArray ( shapes ) ) {
226
+ out = out . concat ( concatComponentExtremes ( shapes , ax , ext ) ) ;
227
+ }
228
+
229
+ return out ;
230
+ }
231
+
232
+ function concatComponentExtremes ( items , ax , ext ) {
233
+ var out = [ ] ;
234
+ var axId = ax . _id ;
235
+ var letter = axId . charAt ( 0 ) ;
236
+
237
+ for ( var i = 0 ; i < items . length ; i ++ ) {
238
+ var d = items [ i ] ;
239
+ var extremes = d . _extremes ;
240
+ if ( d . visible && d [ letter + 'ref' ] === axId && extremes [ axId ] ) {
241
+ out = out . concat ( extremes [ axId ] [ ext ] ) ;
242
+ }
243
+ }
244
+ return out ;
245
+ }
246
+
247
+ function doAutoRange ( gd , ax ) {
178
248
if ( ! ax . _length ) ax . setScale ( ) ;
179
249
180
- // TODO do we really need this?
181
- var hasDeps = ( ax . _min && ax . _max && ax . _min . length && ax . _max . length ) ;
182
250
var axIn ;
183
251
184
- if ( ax . autorange && hasDeps ) {
185
- ax . range = getAutoRange ( ax ) ;
252
+ if ( ax . autorange ) {
253
+ ax . range = getAutoRange ( gd , ax ) ;
186
254
187
255
ax . _r = ax . range . slice ( ) ;
188
256
ax . _rl = Lib . simpleMap ( ax . _r , ax . r2l ) ;
0 commit comments