@@ -19,13 +19,8 @@ var binFunctions = require('./bin_functions');
1919var normFunctions = require ( './norm_functions' ) ;
2020var doAvg = require ( './average' ) ;
2121var cleanBins = require ( './clean_bins' ) ;
22- var numConstants = require ( '../../constants/numerical' ) ;
23- var oneYear = numConstants . ONEAVGYEAR ;
24- var oneMonth = numConstants . ONEAVGMONTH ;
25- var oneDay = numConstants . ONEDAY ;
26- var oneHour = numConstants . ONEHOUR ;
27- var oneMin = numConstants . ONEMIN ;
28- var oneSec = numConstants . ONESEC ;
22+ var oneMonth = require ( '../../constants/numerical' ) . ONEAVGMONTH ;
23+ var getBinSpanLabelRound = require ( './bin_label_vals' ) ;
2924
3025
3126module . exports = function calc ( gd , trace ) {
@@ -201,154 +196,6 @@ module.exports = function calc(gd, trace) {
201196 return cd ;
202197} ;
203198
204- /*
205- * make a function that will find rounded bin edges
206- * @param {number } leftGap: how far from the left edge of any bin is the closest data value?
207- * @param {number } rightGap: how far from the right edge of any bin is the closest data value?
208- * @param {Array[number] } binEdges: the actual edge values used in binning
209- * @param {object } pa: the position axis
210- * @param {string } calendar: the data calendar
211- *
212- * @return {function(v, isRightEdge) }:
213- * find the start (isRightEdge is falsy) or end (truthy) label value for a bin edge `v`
214- */
215- function getBinSpanLabelRound ( leftGap , rightGap , binEdges , pa , calendar ) {
216- // the rounding digit is the largest digit that changes in *all* of 4 regions:
217- // - inside the rightGap before binEdges[0] (shifted 10% to the left)
218- // - inside the leftGap after binEdges[0] (expanded by 10% of rightGap on each end)
219- // - same for binEdges[1]
220- var dv0 = - 1.1 * rightGap ;
221- var dv1 = - 0.1 * rightGap ;
222- var dv2 = leftGap - dv1 ;
223- var edge0 = binEdges [ 0 ] ;
224- var edge1 = binEdges [ 1 ] ;
225- var regions = [
226- [ edge0 + dv0 , edge0 + dv1 ] ,
227- [ edge0 + dv1 , edge0 + dv2 ] ,
228- [ edge1 + dv0 , edge1 + dv1 ] ,
229- [ edge1 + dv1 , edge1 + dv2 ]
230- ] ;
231- var digit = Infinity ;
232- for ( var i = 0 ; i < regions . length ; i ++ ) {
233- digit = Math . min ( digit , biggestDigitChanged ( regions [ i ] , pa , calendar ) ) ;
234- }
235-
236- if ( pa . type === 'date' && digit > oneDay ) {
237- var dashExclude = ( digit === oneYear ) ? 1 : 6 ;
238- var increment = ( digit === oneYear ) ? 'M12' : 'M1' ;
239-
240- return function ( v , isRightEdge ) {
241- var dateStr = pa . c2d ( v , oneYear , calendar ) ;
242- var dashPos = dateStr . indexOf ( '-' , dashExclude ) ;
243- if ( dashPos > 0 ) dateStr = dateStr . substr ( 0 , dashPos ) ;
244- var roundedV = pa . d2c ( dateStr , calendar ) ;
245-
246- if ( roundedV < v ) {
247- var nextV = Axes . tickIncrement ( roundedV , increment , false , calendar ) ;
248- if ( ( roundedV + nextV ) / 2 < v + leftGap ) roundedV = nextV ;
249- }
250-
251- if ( isRightEdge ) {
252- return Axes . tickIncrement ( roundedV , increment , true , calendar ) ;
253- }
254-
255- return roundedV ;
256- } ;
257- }
258-
259- return function ( v , isRightEdge ) {
260- var roundedV = digit * Math . round ( v / digit ) ;
261- // if we rounded down and we could round up and still be < leftGap
262- // (or what leftGap values round to), do that
263- // TODO: is the `digit / 2` correct or is that too much leeway?
264- if ( roundedV < v && roundedV + ( digit / 2 ) < v + leftGap ) {
265- roundedV += digit ;
266- }
267- // finally for the right edge back off one digit - but only if we can do that
268- // and not clip off any data that's potentially in the bin
269- if ( isRightEdge ) {
270- roundedV -= digit ;
271- }
272- return roundedV ;
273- } ;
274- }
275-
276- /*
277- * Find the largest digit that changes within a (calcdata) region [v1, v2]
278- * if dates, "digit" means date/time part when it's bigger than a second
279- * returns the unit value to round to this digit, eg 0.01 to round to hundredths, or
280- * 100 to round to hundreds. returns oneMonth or oneYear for month or year rounding,
281- * so that Math.min will work, rather than 'M1' and 'M12'
282- */
283- function biggestDigitChanged ( region , pa , calendar ) {
284- var v1 = region [ 0 ] ;
285- var v2 = region [ 1 ] ;
286-
287- // are we crossing zero? can't say anything.
288- // in principle this doesn't apply to dates but turns out this doesn't matter.
289- if ( v1 * v2 <= 0 ) return Infinity ;
290-
291- var dv = Math . abs ( v2 - v1 ) ;
292- var isDate = pa . type === 'date' ;
293- var digit = biggestGuaranteedDigitChanged ( dv , isDate ) ;
294- // see if a larger digit also changed
295- for ( var i = 0 ; i < 10 ; i ++ ) {
296- // numbers: next digit needs to be >10x but <100x then gets rounded down.
297- // dates: next digit can be as much as 60x (then rounded down)
298- var nextDigit = biggestGuaranteedDigitChanged ( digit * 80 , isDate ) ;
299- // if we get to years, the chain stops
300- if ( digit === nextDigit ) break ;
301- if ( didDigitChange ( nextDigit , v1 , v2 , isDate , pa , calendar ) ) digit = nextDigit ;
302- else break ;
303- }
304- return digit ;
305- }
306-
307- /*
308- * Find the largest digit that *definitely* changes in a region [v, v + dv] for any v
309- * for nonuniform date regions (months/years) pick the largest
310- */
311- function biggestGuaranteedDigitChanged ( dv , isDate ) {
312- if ( isDate && dv > oneSec ) {
313- // this is supposed to be the biggest *guaranteed* change
314- // so compare to the longest month and year across any calendar,
315- // (TODO: does 1.1 do that? I think so...)
316- // and we'll iterate back up later
317- // note: does not support rounding larger than one year. We could add
318- // that if anyone wants it, but seems unusual and not strictly necessary.
319- if ( dv > oneDay ) {
320- if ( dv > oneYear * 1.1 ) return oneYear ;
321- if ( dv > oneMonth * 1.1 ) return oneMonth ;
322- return oneDay ;
323- }
324-
325- if ( dv > oneHour ) return oneHour ;
326- if ( dv > oneMin ) return oneMin ;
327- return oneSec ;
328- }
329- return Math . pow ( 10 , Math . floor ( Math . log ( dv ) / Math . LN10 ) ) ;
330- }
331-
332- function didDigitChange ( digit , v1 , v2 , isDate , pa , calendar ) {
333- if ( isDate && digit > oneDay ) {
334- var dateParts1 = dateParts ( v1 , pa , calendar ) ;
335- var dateParts2 = dateParts ( v2 , pa , calendar ) ;
336- var parti = ( digit === oneYear ) ? 0 : 1 ;
337- return dateParts1 [ parti ] !== dateParts2 [ parti ] ;
338-
339- }
340- return Math . floor ( v2 / digit ) - Math . floor ( v1 / digit ) > 0.1 ;
341- }
342-
343- function dateParts ( v , pa , calendar ) {
344- var parts = pa . c2d ( v , oneYear , calendar ) . split ( '-' ) ;
345- if ( parts [ 0 ] === '' ) {
346- parts . unshift ( ) ;
347- parts [ 0 ] = '-' + parts [ 0 ] ;
348- }
349- return parts ;
350- }
351-
352199/*
353200 * calcAllAutoBins: we want all histograms on the same axes to share bin specs
354201 * if they're grouped or stacked. If the user has explicitly specified differing
0 commit comments