@@ -56,6 +56,15 @@ var autorange = require('./autorange');
5656axes . getAutoRange = autorange . getAutoRange ;
5757axes . findExtremes = autorange . findExtremes ;
5858
59+ var epsilon = 0.0001 ;
60+ function expandRange ( range ) {
61+ var delta = ( range [ 1 ] - range [ 0 ] ) * epsilon ;
62+ return [
63+ range [ 0 ] - delta ,
64+ range [ 1 ] + delta
65+ ] ;
66+ }
67+
5968/*
6069 * find the list of possible axes to reference with an xref or yref attribute
6170 * and coerce it to that list
@@ -566,8 +575,9 @@ axes.calcTicks = function calcTicks(ax) {
566575 ax . _tmin = axes . tickFirst ( ax ) ;
567576
568577 // add a tiny bit so we get ticks which may have rounded out
569- var startTick = rng [ 0 ] * 1.0001 - rng [ 1 ] * 0.0001 ;
570- var endTick = rng [ 1 ] * 1.0001 - rng [ 0 ] * 0.0001 ;
578+ var exRng = expandRange ( rng ) ;
579+ var startTick = exRng [ 0 ] ;
580+ var endTick = exRng [ 1 ] ;
571581 // check for reversed axis
572582 var axrev = ( rng [ 1 ] < rng [ 0 ] ) ;
573583
@@ -612,39 +622,42 @@ axes.calcTicks = function calcTicks(ax) {
612622
613623 if ( ax . rangebreaks ) {
614624 // replace ticks inside breaks that would get a tick
615- if ( ax . tickmode === 'auto' ) {
616- for ( var t = 0 ; t < tickVals . length ; t ++ ) {
617- var value = tickVals [ t ] . value ;
618- if ( ax . maskBreaks ( value ) === BADNUM ) {
619- // find which break we are in
620- for ( var k = 0 ; k < ax . _rangebreaks . length ; k ++ ) {
621- var brk = ax . _rangebreaks [ k ] ;
622- if ( value >= brk . min && value < brk . max ) {
623- tickVals [ t ] . value = brk . max ; // replace with break end
624- break ;
625- }
626- }
627- }
628- }
629- }
630-
631- // reduce ticks
625+ // and reduce ticks
632626 var len = tickVals . length ;
633- if ( len > 2 ) {
634- var tf2 = 2 * ( ax . tickfont ? ax . tickfont . size : 12 ) ;
627+ if ( len ) {
628+ var tf = 0 ;
629+ if ( ax . tickmode === 'auto' ) {
630+ tf =
631+ ( ax . _id . charAt ( 0 ) === 'y' ? 2 : 6 ) *
632+ ( ax . tickfont ? ax . tickfont . size : 12 ) ;
633+ }
635634
636635 var newTickVals = [ ] ;
637636 var prevPos ;
638637
639638 var dir = axrev ? 1 : - 1 ;
640639 var first = axrev ? 0 : len - 1 ;
641640 var last = axrev ? len - 1 : 0 ;
642- for ( var q = first ; dir * q <= dir * last ; q += dir ) { // apply reverse loop to pick greater values in breaks first
643- var pos = ax . c2p ( tickVals [ q ] . value ) ;
641+ for ( var q = first ; dir * q <= dir * last ; q += dir ) {
642+ var tickVal = tickVals [ q ] ;
643+ if ( ax . maskBreaks ( tickVal . value ) === BADNUM ) {
644+ tickVal . value = moveOutsideBreak ( tickVal . value , ax ) ;
645+
646+ if ( ax . _rl && (
647+ ax . _rl [ 0 ] === tickVal . value ||
648+ ax . _rl [ 1 ] === tickVal . value
649+ ) ) continue ;
650+ }
644651
645- if ( prevPos === undefined || Math . abs ( pos - prevPos ) > tf2 ) {
652+ var pos = ax . c2p ( tickVal . value ) ;
653+
654+ if ( pos === prevPos ) {
655+ if ( newTickVals [ newTickVals . length - 1 ] . value < tickVal . value ) {
656+ newTickVals [ newTickVals . length - 1 ] = tickVal ;
657+ }
658+ } else if ( prevPos === undefined || Math . abs ( pos - prevPos ) > tf ) {
646659 prevPos = pos ;
647- newTickVals . push ( tickVals [ q ] ) ;
660+ newTickVals . push ( tickVal ) ;
648661 }
649662 }
650663 tickVals = newTickVals . reverse ( ) ;
@@ -691,10 +704,9 @@ function arrayTicks(ax) {
691704 var text = ax . ticktext ;
692705 var ticksOut = new Array ( vals . length ) ;
693706 var rng = Lib . simpleMap ( ax . range , ax . r2l ) ;
694- var r0expanded = rng [ 0 ] * 1.0001 - rng [ 1 ] * 0.0001 ;
695- var r1expanded = rng [ 1 ] * 1.0001 - rng [ 0 ] * 0.0001 ;
696- var tickMin = Math . min ( r0expanded , r1expanded ) ;
697- var tickMax = Math . max ( r0expanded , r1expanded ) ;
707+ var exRng = expandRange ( rng ) ;
708+ var tickMin = Math . min ( exRng [ 0 ] , exRng [ 1 ] ) ;
709+ var tickMax = Math . max ( exRng [ 0 ] , exRng [ 1 ] ) ;
698710 var j = 0 ;
699711
700712 // without a text array, just format the given values as any other ticks
@@ -785,8 +797,7 @@ axes.autoTicks = function(ax, roughDTick) {
785797 roughDTick /= ONEAVGMONTH ;
786798 ax . dtick = 'M' + roundDTick ( roughDTick , 1 , roundBase24 ) ;
787799 } else if ( roughX2 > ONEDAY ) {
788- ax . dtick = roundDTick ( roughDTick , ONEDAY , ax . _hasDayOfWeekBreaks ? [ 1 , 7 , 14 ] : roundDays ) ;
789-
800+ ax . dtick = roundDTick ( roughDTick , ONEDAY , ax . _hasDayOfWeekBreaks ? [ 1 , 2 , 7 , 14 ] : roundDays ) ;
790801 // get week ticks on sunday
791802 // this will also move the base tick off 2000-01-01 if dtick is
792803 // 2 or 3 days... but that's a weird enough case that we'll ignore it.
@@ -934,18 +945,20 @@ axes.tickIncrement = function(x, dtick, axrev, calendar) {
934945 if ( tType === 'M' ) return Lib . incrementMonth ( x , dtSigned , calendar ) ;
935946
936947 // Log scales: Linear, Digits
937- else if ( tType === 'L' ) return Math . log ( Math . pow ( 10 , x ) + dtSigned ) / Math . LN10 ;
948+ if ( tType === 'L' ) return Math . log ( Math . pow ( 10 , x ) + dtSigned ) / Math . LN10 ;
938949
939950 // log10 of 2,5,10, or all digits (logs just have to be
940951 // close enough to round)
941- else if ( tType === 'D' ) {
952+ if ( tType === 'D' ) {
942953 var tickset = ( dtick === 'D2' ) ? roundLog2 : roundLog1 ;
943954 var x2 = x + axSign * 0.01 ;
944955 var frac = Lib . roundUp ( Lib . mod ( x2 , 1 ) , tickset , axrev ) ;
945956
946957 return Math . floor ( x2 ) +
947958 Math . log ( d3 . round ( Math . pow ( 10 , frac ) , 1 ) ) / Math . LN10 ;
948- } else throw 'unrecognized dtick ' + String ( dtick ) ;
959+ }
960+
961+ throw 'unrecognized dtick ' + String ( dtick ) ;
949962} ;
950963
951964// calculate the first tick on an axis
@@ -956,7 +969,7 @@ axes.tickFirst = function(ax) {
956969 var sRound = axrev ? Math . floor : Math . ceil ;
957970 // add a tiny extra bit to make sure we get ticks
958971 // that may have been rounded out
959- var r0 = rng [ 0 ] * 1.0001 - rng [ 1 ] * 0.0001 ;
972+ var r0 = expandRange ( rng ) [ 0 ] ;
960973 var dtick = ax . dtick ;
961974 var tick0 = r2l ( ax . tick0 ) ;
962975
@@ -3158,3 +3171,14 @@ function swapAxisAttrs(layout, key, xFullAxes, yFullAxes, dfltTitle) {
31583171function isAngular ( ax ) {
31593172 return ax . _id === 'angularaxis' ;
31603173}
3174+
3175+ function moveOutsideBreak ( v , ax ) {
3176+ var len = ax . _rangebreaks . length ;
3177+ for ( var k = 0 ; k < len ; k ++ ) {
3178+ var brk = ax . _rangebreaks [ k ] ;
3179+ if ( v >= brk . min && v < brk . max ) {
3180+ return brk . max ;
3181+ }
3182+ }
3183+ return v ;
3184+ }
0 commit comments