66* LICENSE file in the root directory of this source tree.
77*/
88
9-
109'use strict' ;
1110
1211var isNumeric = require ( 'fast-isnumeric' ) ;
1312
1413var Lib = require ( '../../lib' ) ;
1514var FP_SAFE = require ( '../../constants/numerical' ) . FP_SAFE ;
1615
16+ var Registry = require ( '../../registry' ) ;
17+
1718module . exports = {
1819 getAutoRange : getAutoRange ,
1920 makePadFn : makePadFn ,
@@ -22,59 +23,77 @@ module.exports = {
2223 findExtremes : findExtremes
2324} ;
2425
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 ;
4355 var newRange = [ ] ;
44- var minmin = ax . _min [ 0 ] . val ;
45- var maxmax = ax . _max [ 0 ] . val ;
46- var mbest = 0 ;
47- var axReverse = false ;
4856
4957 var getPad = makePadFn ( ax ) ;
58+ var minArray = concatExtremes ( gd , ax , 'min' ) ;
59+ var maxArray = concatExtremes ( gd , ax , 'max' ) ;
5060
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+ }
5264
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 ++ ) {
5469 if ( minmin !== maxmax ) break ;
55- minmin = Math . min ( minmin , ax . _min [ i ] . val ) ;
70+ minmin = Math . min ( minmin , minArray [ i ] . val ) ;
5671 }
57- for ( i = 1 ; i < ax . _max . length ; i ++ ) {
72+ for ( i = 1 ; i < maxArray . length ; i ++ ) {
5873 if ( minmin !== maxmax ) break ;
59- maxmax = Math . max ( maxmax , ax . _max [ i ] . val ) ;
74+ maxmax = Math . max ( maxmax , maxArray [ i ] . val ) ;
6075 }
6176
77+ var axReverse = false ;
78+
6279 if ( ax . range ) {
6380 var rng = Lib . simpleMap ( ax . range , ax . r2l ) ;
6481 axReverse = rng [ 1 ] < rng [ 0 ] ;
6582 }
66-
6783 // one-time setting to easily reverse the axis
6884 // when plotting from code
6985 if ( ax . autorange === 'reversed' ) {
7086 axReverse = true ;
7187 ax . autorange = true ;
7288 }
7389
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 ] ;
7897 dv = maxpt . val - minpt . val ;
7998 dp = ax . _length - getPad ( minpt ) - getPad ( maxpt ) ;
8099 if ( dv > 0 && dp > 0 && dv / dp > mbest ) {
@@ -90,11 +109,9 @@ function getAutoRange(ax) {
90109 var upper = minmin + 1 ;
91110 if ( ax . rangemode === 'tozero' ) {
92111 newRange = minmin < 0 ? [ lower , 0 ] : [ 0 , upper ] ;
93- }
94- else if ( ax . rangemode === 'nonnegative' ) {
112+ } else if ( ax . rangemode === 'nonnegative' ) {
95113 newRange = [ Math . max ( 0 , lower ) , Math . max ( 0 , upper ) ] ;
96- }
97- else {
114+ } else {
98115 newRange = [ lower , upper ] ;
99116 }
100117 }
@@ -134,11 +151,9 @@ function getAutoRange(ax) {
134151 if ( ax . rangemode === 'tozero' ) {
135152 if ( newRange [ 0 ] < 0 ) {
136153 newRange = [ newRange [ 0 ] , 0 ] ;
137- }
138- else if ( newRange [ 0 ] > 0 ) {
154+ } else if ( newRange [ 0 ] > 0 ) {
139155 newRange = [ 0 , newRange [ 0 ] ] ;
140- }
141- else {
156+ } else {
142157 newRange = [ 0 , 1 ] ;
143158 }
144159 }
@@ -174,15 +189,68 @@ function makePadFn(ax) {
174189 return function getPad ( pt ) { return pt . pad + ( pt . extrapad ? extrappad : 0 ) ; } ;
175190}
176191
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 ) {
178248 if ( ! ax . _length ) ax . setScale ( ) ;
179249
180- // TODO do we really need this?
181- var hasDeps = ( ax . _min && ax . _max && ax . _min . length && ax . _max . length ) ;
182250 var axIn ;
183251
184- if ( ax . autorange && hasDeps ) {
185- ax . range = getAutoRange ( ax ) ;
252+ if ( ax . autorange ) {
253+ ax . range = getAutoRange ( gd , ax ) ;
186254
187255 ax . _r = ax . range . slice ( ) ;
188256 ax . _rl = Lib . simpleMap ( ax . _r , ax . r2l ) ;
0 commit comments