@@ -21,21 +21,21 @@ module.exports = function calcAutorange(gd) {
2121 var xRefType = Axes . getRefType ( shape . xref ) ;
2222 var yRefType = Axes . getRefType ( shape . yref ) ;
2323
24- // paper and axis domain referenced shapes don't affect autorange
25- // TODO: implement autorange calculation for array ref shapes
26- if ( xRefType !== 'array' && shape . xref !== 'paper' && xRefType !== 'domain' ) {
24+ if ( xRefType === 'array' ) {
25+ calcArrayRefAutorange ( gd , shape , 'x' ) ;
26+ } else if ( shape . xref !== 'paper' && xRefType !== 'domain' ) {
27+ // paper and axis domain referenced shapes don't affect autorange
2728 ax = Axes . getFromId ( gd , shape . xref ) ;
28-
2929 bounds = shapeBounds ( ax , shape , constants . paramIsX ) ;
3030 if ( bounds ) {
3131 shape . _extremes [ ax . _id ] = Axes . findExtremes ( ax , bounds , calcXPaddingOptions ( shape ) ) ;
3232 }
3333 }
3434
35- // TODO: implement autorange calculation for array ref shapes
36- if ( yRefType !== 'array' && shape . yref !== 'paper' && yRefType !== 'domain' ) {
35+ if ( yRefType === 'array' ) {
36+ calcArrayRefAutorange ( gd , shape , 'y' ) ;
37+ } else if ( shape . yref !== 'paper' && yRefType !== 'domain' ) {
3738 ax = Axes . getFromId ( gd , shape . yref ) ;
38-
3939 bounds = shapeBounds ( ax , shape , constants . paramIsY ) ;
4040 if ( bounds ) {
4141 shape . _extremes [ ax . _id ] = Axes . findExtremes ( ax , bounds , calcYPaddingOptions ( shape ) ) ;
@@ -44,6 +44,50 @@ module.exports = function calcAutorange(gd) {
4444 }
4545} ;
4646
47+ function calcArrayRefAutorange ( gd , shape , dim ) {
48+ var refs = shape [ dim + 'ref' ] ;
49+ var paramsToUse = dim === 'x' ? constants . paramIsX : constants . paramIsY ;
50+ var paddingOpts = dim === 'x' ? calcXPaddingOptions ( shape ) : calcYPaddingOptions ( shape ) ;
51+
52+ function addToAxisGroup ( ref , val ) {
53+ if ( ref === 'paper' || Axes . getRefType ( ref ) === 'domain' ) return ;
54+ if ( ! axisGroups [ ref ] ) axisGroups [ ref ] = [ ] ;
55+ axisGroups [ ref ] . push ( val ) ;
56+ }
57+
58+ // group coordinates by axis reference so we can calculate the extremes for each axis
59+ var axisGroups = { } ;
60+ if ( shape . type === 'path' && shape . path ) {
61+ var segments = shape . path . match ( constants . segmentRE ) || [ ] ;
62+ var refIndex = 0 ;
63+ for ( var i = 0 ; i < segments . length ; i ++ ) {
64+ var segment = segments [ i ] ;
65+ var command = segment . charAt ( 0 ) ;
66+ var drawnIndex = paramsToUse [ command ] . drawn ;
67+
68+ if ( drawnIndex === undefined ) continue ;
69+
70+ var params = segment . slice ( 1 ) . match ( constants . paramRE ) ;
71+ if ( params && params . length > drawnIndex ) {
72+ addToAxisGroup ( refs [ refIndex ] , params [ drawnIndex ] ) ;
73+ refIndex ++ ;
74+ }
75+ }
76+ } else {
77+ addToAxisGroup ( refs [ 0 ] , shape [ dim + '0' ] ) ;
78+ addToAxisGroup ( refs [ 1 ] , shape [ dim + '1' ] ) ;
79+ }
80+
81+ // For each axis, convert coordinates to data values then calculate extremes
82+ for ( var axId in axisGroups ) {
83+ var ax = Axes . getFromId ( gd , axId ) ;
84+ if ( ! ax ) continue ;
85+ var convertVal = ( ax . type === 'category' || ax . type === 'multicategory' ) ? ax . r2c : ax . d2c ;
86+ if ( ax . type === 'date' ) convertVal = helpers . decodeDate ( convertVal ) ;
87+ shape . _extremes [ ax . _id ] = Axes . findExtremes ( ax , axisGroups [ axId ] . map ( convertVal ) , paddingOpts ) ;
88+ }
89+ }
90+
4791function calcXPaddingOptions ( shape ) {
4892 return calcPaddingOptions ( shape . line . width , shape . xsizemode , shape . x0 , shape . x1 , shape . path , false ) ;
4993}
0 commit comments