@@ -25,14 +25,14 @@ module.exports = function(gd, plotinfo, cdheatmaps) {
2525 }
2626} ;
2727
28- // From http://www.xarg.org/2010/03/generate-client-side-png-files-using-javascript/
2928function plotOne ( gd , plotinfo , cd ) {
30- var trace = cd [ 0 ] . trace ,
31- uid = trace . uid ,
32- xa = plotinfo . xaxis ,
33- ya = plotinfo . yaxis ,
34- fullLayout = gd . _fullLayout ,
35- id = 'hm' + uid ;
29+ var cd0 = cd [ 0 ] ;
30+ var trace = cd0 . trace ;
31+ var uid = trace . uid ;
32+ var xa = plotinfo . xaxis ;
33+ var ya = plotinfo . yaxis ;
34+ var fullLayout = gd . _fullLayout ;
35+ var id = 'hm' + uid ;
3636
3737 // in case this used to be a contour map
3838 fullLayout . _paper . selectAll ( '.contour' + uid ) . remove ( ) ;
@@ -45,23 +45,21 @@ function plotOne(gd, plotinfo, cd) {
4545 return ;
4646 }
4747
48- var z = cd [ 0 ] . z ,
49- x = cd [ 0 ] . x ,
50- y = cd [ 0 ] . y ,
51- isContour = Registry . traceIs ( trace , 'contour' ) ,
52- zsmooth = isContour ? 'best' : trace . zsmooth ,
53-
54- // get z dims
55- m = z . length ,
56- n = maxRowLength ( z ) ,
57- xrev = false ,
58- left ,
59- right ,
60- temp ,
61- yrev = false ,
62- top ,
63- bottom ,
64- i ;
48+ var z = cd0 . z ;
49+ var x = cd0 . x ;
50+ var y = cd0 . y ;
51+ var xc = cd0 . xCenter ;
52+ var yc = cd0 . yCenter ;
53+ var isContour = Registry . traceIs ( trace , 'contour' ) ;
54+ var zsmooth = isContour ? 'best' : trace . zsmooth ;
55+
56+ // get z dims
57+ var m = z . length ;
58+ var n = maxRowLength ( z ) ;
59+ var xrev = false ;
60+ var yrev = false ;
61+
62+ var left , right , temp , top , bottom , i ;
6563
6664 // TODO: if there are multiple overlapping categorical heatmaps,
6765 // or if we allow category sorting, then the categories may not be
@@ -113,11 +111,10 @@ function plotOne(gd, plotinfo, cd) {
113111 // for contours with heatmap fill, we generate the boundaries based on
114112 // brick centers but then use the brick edges for drawing the bricks
115113 if ( isContour ) {
116- // TODO: for 'best' smoothing, we really should use the given brick
117- // centers as well as brick bounds in calculating values, in case of
118- // nonuniform brick sizes
119- x = cd [ 0 ] . xfill ;
120- y = cd [ 0 ] . yfill ;
114+ xc = x ;
115+ yc = y ;
116+ x = cd0 . xfill ;
117+ y = cd0 . yfill ;
121118 }
122119
123120 // make an image that goes at most half a screen off either side, to keep
@@ -201,15 +198,15 @@ function plotOne(gd, plotinfo, cd) {
201198
202199 // get interpolated bin value. Returns {bin0:closest bin, frac:fractional dist to next, bin1:next bin}
203200 function findInterp ( pixel , pixArray ) {
204- var maxbin = pixArray . length - 2 ,
205- bin = Lib . constrain ( Lib . findBin ( pixel , pixArray ) , 0 , maxbin ) ,
206- pix0 = pixArray [ bin ] ,
207- pix1 = pixArray [ bin + 1 ] ,
208- interp = Lib . constrain ( bin + ( pixel - pix0 ) / ( pix1 - pix0 ) - 0.5 , 0 , maxbin ) ,
209- bin0 = Math . round ( interp ) ,
210- frac = Math . abs ( interp - bin0 ) ;
211-
212- if ( ! interp || interp === maxbin || ! frac ) {
201+ var maxBin = pixArray . length - 2 ;
202+ var bin = Lib . constrain ( Lib . findBin ( pixel , pixArray ) , 0 , maxBin ) ;
203+ var pix0 = pixArray [ bin ] ;
204+ var pix1 = pixArray [ bin + 1 ] ;
205+ var interp = Lib . constrain ( bin + ( pixel - pix0 ) / ( pix1 - pix0 ) - 0.5 , 0 , maxBin ) ;
206+ var bin0 = Math . round ( interp ) ;
207+ var frac = Math . abs ( interp - bin0 ) ;
208+
209+ if ( ! interp || interp === maxBin || ! frac ) {
213210 return {
214211 bin0 : bin0 ,
215212 bin1 : bin0 ,
@@ -223,6 +220,36 @@ function plotOne(gd, plotinfo, cd) {
223220 } ;
224221 }
225222
223+ function findInterpFromCenters ( pixel , centerPixArray ) {
224+ // if(pixel <= centerPixArray[0]) return {bin0: 0, bin1: 0, frac: 0};
225+ var maxBin = centerPixArray . length - 1 ;
226+ // if(pixel >= centerPixArray[lastCenter]) return {bin0: lastCenter, bin1: lastCenter, frac: 0};
227+
228+ var bin = Lib . constrain ( Lib . findBin ( pixel , centerPixArray ) , 0 , maxBin ) ;
229+ var pix0 = centerPixArray [ bin ] ;
230+ var pix1 = centerPixArray [ bin + 1 ] ;
231+ var frac = ( ( pixel - pix0 ) / ( pix1 - pix0 ) ) || 0 ;
232+ if ( frac <= 0 ) {
233+ return {
234+ bin0 : bin ,
235+ bin1 : bin ,
236+ frac : 0
237+ } ;
238+ }
239+ if ( frac < 0.5 ) {
240+ return {
241+ bin0 : bin ,
242+ bin1 : bin + 1 ,
243+ frac : frac
244+ } ;
245+ }
246+ return {
247+ bin0 : bin + 1 ,
248+ bin1 : bin ,
249+ frac : 1 - frac
250+ } ;
251+ }
252+
226253 // build the pixel map brick-by-brick
227254 // cruise through z-matrix row-by-row
228255 // build a brick at each z-matrix value
@@ -303,24 +330,26 @@ function plotOne(gd, plotinfo, cd) {
303330 }
304331
305332 if ( zsmooth === 'best' ) {
306- var xPixArray = new Array ( x . length ) ,
307- yPixArray = new Array ( y . length ) ,
308- xinterpArray = new Array ( imageWidth ) ,
309- yinterp ,
310- r0 ,
311- r1 ;
333+ var xForPx = xc || x ;
334+ var yForPx = yc || y ;
335+ var xPixArray = new Array ( xForPx . length ) ;
336+ var yPixArray = new Array ( yForPx . length ) ;
337+ var xinterpArray = new Array ( imageWidth ) ;
338+ var findInterpX = xc ? findInterpFromCenters : findInterp ;
339+ var findInterpY = yc ? findInterpFromCenters : findInterp ;
340+ var yinterp , r0 , r1 ;
312341
313342 // first make arrays of x and y pixel locations of brick boundaries
314- for ( i = 0 ; i < x . length ; i ++ ) xPixArray [ i ] = Math . round ( xa . c2p ( x [ i ] ) - left ) ;
315- for ( i = 0 ; i < y . length ; i ++ ) yPixArray [ i ] = Math . round ( ya . c2p ( y [ i ] ) - top ) ;
343+ for ( i = 0 ; i < xForPx . length ; i ++ ) xPixArray [ i ] = Math . round ( xa . c2p ( xForPx [ i ] ) - left ) ;
344+ for ( i = 0 ; i < yForPx . length ; i ++ ) yPixArray [ i ] = Math . round ( ya . c2p ( yForPx [ i ] ) - top ) ;
316345
317346 // then make arrays of interpolations
318347 // (bin0=closest, bin1=next, frac=fractional dist.)
319- for ( i = 0 ; i < imageWidth ; i ++ ) xinterpArray [ i ] = findInterp ( i , xPixArray ) ;
348+ for ( i = 0 ; i < imageWidth ; i ++ ) xinterpArray [ i ] = findInterpX ( i , xPixArray ) ;
320349
321350 // now do the interpolations and fill the png
322351 for ( j = 0 ; j < imageHeight ; j ++ ) {
323- yinterp = findInterp ( j , yPixArray ) ;
352+ yinterp = findInterpY ( j , yPixArray ) ;
324353 r0 = z [ yinterp . bin0 ] ;
325354 r1 = z [ yinterp . bin1 ] ;
326355 for ( i = 0 ; i < imageWidth ; i ++ , pxIndex += 4 ) {
0 commit comments