From 12b879f424bcdd49822f33378c740063370bb4be Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Sat, 16 Feb 2013 21:36:58 -0500 Subject: [PATCH] Fix issue 176, which involved duplicated x-values in stacked graphs --- auto_tests/tests/Util.js | 16 ++++++++++++++++ auto_tests/tests/error_bars.js | 22 ++++------------------ auto_tests/tests/stacked.js | 26 ++++++++++++++++++++++++++ dygraph-canvas.js | 10 +++++++++- dygraph.js | 11 +++++++---- 5 files changed, 62 insertions(+), 23 deletions(-) diff --git a/auto_tests/tests/Util.js b/auto_tests/tests/Util.js index 2b308b3..2d652ed 100644 --- a/auto_tests/tests/Util.js +++ b/auto_tests/tests/Util.js @@ -79,3 +79,19 @@ Util.makeNumbers = function(ary) { } return ret; }; + + +/** + * Sample a pixel from the canvas. + * Returns an [r, g, b, a] tuple where each values is in [0, 255]. + */ +Util.samplePixel = function(canvas, x, y) { + var ctx = canvas.getContext("2d"); // bypasses Proxy if applied. + + // TODO(danvk): Any performance issues with this? + var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + + var i = 4 * (x + imageData.width * y); + var d = imageData.data; + return [d[i], d[i+1], d[i+2], d[i+3]]; +}; diff --git a/auto_tests/tests/error_bars.js b/auto_tests/tests/error_bars.js index 5144363..e57898b 100644 --- a/auto_tests/tests/error_bars.js +++ b/auto_tests/tests/error_bars.js @@ -124,22 +124,8 @@ errorBarsTestCase.prototype.testErrorBarsCorrectColors = function() { // 249-299: empty (white) // TODO(danvk): test the edges of these regions. - var ctx = g.hidden_.getContext("2d"); // bypass Proxy - var imageData = ctx.getImageData(0, 0, 400, 300); - - assertEquals(400, imageData.width); - assertEquals(300, imageData.height); - - // returns an (r, g, b, alpha) tuple for the pixel. - // values are in [0, 255]. - var getPixel = function(imageData, x, y) { - var i = 4 * (x + imageData.width * y); - var d = imageData.data; - return [d[i], d[i+1], d[i+2], d[i+3]]; - }; - - assertEquals([0, 0, 255, 38], getPixel(imageData, 200, 75)); - assertEquals([0, 0, 255, 38], getPixel(imageData, 200, 125)); - assertEquals([0, 255, 0, 38], getPixel(imageData, 200, 175)); - assertEquals([0, 255, 0, 38], getPixel(imageData, 200, 225)); + assertEquals([0, 0, 255, 38], Util.samplePixel(g.hidden_, 200, 75)); + assertEquals([0, 0, 255, 38], Util.samplePixel(g.hidden_, 200, 125)); + assertEquals([0, 255, 0, 38], Util.samplePixel(g.hidden_, 200, 175)); + assertEquals([0, 255, 0, 38], Util.samplePixel(g.hidden_, 200, 225)); } diff --git a/auto_tests/tests/stacked.js b/auto_tests/tests/stacked.js index 706f56f..de41733 100644 --- a/auto_tests/tests/stacked.js +++ b/auto_tests/tests/stacked.js @@ -94,3 +94,29 @@ stackedTestCase.prototype.testSelectionValues = function() { g.setSelection(0, 'Y2'); assertEquals("0: Y1: 1 Y2: 1", Util.getLegend()); }; + +// Regression test for http://code.google.com/p/dygraphs/issues/detail?id=176 +stackedTestCase.prototype.testDuplicatedXValue = function() { + var opts = { + stackedGraph: true, + fillAlpha: 0.15, + colors: ['#00ff00'], + width: 400, + height: 300 + }; + var data = "X,Y1\n" + + "0,1\n" + + "1,1\n" + + "2,1\n" + + "2,1\n" + // duplicate x-value! + "3,1\n" + ; + + var graph = document.getElementById("graph"); + g = new Dygraph(graph, data, opts); + + assert(g.yAxisRange()[1] < 2); + + assertEquals([0, 255, 0, 38], Util.samplePixel(g.hidden_, 200, 250)); + assertEquals([0, 255, 0, 38], Util.samplePixel(g.hidden_, 317, 250)); +} diff --git a/dygraph-canvas.js b/dygraph-canvas.js index b647b7a..99ad493 100644 --- a/dygraph-canvas.js +++ b/dygraph-canvas.js @@ -731,13 +731,21 @@ DygraphCanvasRenderer._fillPlotter = function(e) { 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + fillAlpha + ')'; ctx.fillStyle = err_color; ctx.beginPath(); - while(iter.hasNext) { + var last_x, is_first = true; + while (iter.hasNext) { var point = iter.next(); if (!Dygraph.isOK(point.y)) { prevX = NaN; continue; } if (stackedGraph) { + if (!is_first && last_x == point.xval) { + continue; + } else { + is_first = false; + last_x = point.xval; + } + currBaseline = baseline[point.canvasx]; var lastY; if (currBaseline === undefined) { diff --git a/dygraph.js b/dygraph.js index ceaac17..1d247ac 100644 --- a/dygraph.js +++ b/dygraph.js @@ -2279,9 +2279,8 @@ Dygraph.prototype.gatherDatasets_ = function(rolledSeries, dateWindow) { series[j][1][2]]; } } else if (this.attr_("stackedGraph")) { - var l = series.length; - var actual_y; - for (j = 0; j < l; j++) { + var actual_y, last_x; + for (j = 0; j < series.length; j++) { // If one data set has a NaN, let all subsequent stacked // sets inherit the NaN -- only start at 0 for the first set. var x = series[j][0]; @@ -2295,7 +2294,11 @@ Dygraph.prototype.gatherDatasets_ = function(rolledSeries, dateWindow) { continue; } - cumulative_y[x] += actual_y; + if (j === 0 || last_x != x) { + cumulative_y[x] += actual_y; + // If an x-value is repeated, we ignore the duplicates. + } + last_x = x; series[j] = [x, cumulative_y[x]]; -- 2.7.4