Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stacked Area Charts #2960

Merged
merged 14 commits into from
Sep 7, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/constants/numerical.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ module.exports = {
*/
ALMOST_EQUAL: 1 - 1e-6,

/*
* If we're asked to clip a non-positive log value, how far off-screen
* do we put it?
*/
LOG_CLIP: 10,

/*
* not a number, but for displaying numbers: the "minus sign" symbol is
* wider than the regular ascii dash "-"
Expand Down
10 changes: 3 additions & 7 deletions src/plots/cartesian/set_convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var ensureNumber = Lib.ensureNumber;
var numConstants = require('../../constants/numerical');
var FP_SAFE = numConstants.FP_SAFE;
var BADNUM = numConstants.BADNUM;
var LOG_CLIP = numConstants.LOG_CLIP;

var constants = require('./constants');
var axisIds = require('./axis_ids');
Expand Down Expand Up @@ -59,20 +60,15 @@ module.exports = function setConvert(ax, fullLayout) {

var axLetter = (ax._id || 'x').charAt(0);

// clipMult: how many axis lengths past the edge do we render?
// for panning, 1-2 would suffice, but for zooming more is nice.
// also, clipping can affect the direction of lines off the edge...
var clipMult = 10;

function toLog(v, clip) {
if(v > 0) return Math.log(v) / Math.LN10;

else if(v <= 0 && clip && ax.range && ax.range.length === 2) {
// clip NaN (ie past negative infinity) to clipMult axis
// clip NaN (ie past negative infinity) to LOG_CLIP axis
// length past the negative edge
var r0 = ax.range[0],
r1 = ax.range[1];
return 0.5 * (r0 + r1 - 3 * clipMult * Math.abs(r0 - r1));
return 0.5 * (r0 + r1 - 2 * LOG_CLIP * Math.abs(r0 - r1));
}

else return BADNUM;
Expand Down
48 changes: 37 additions & 11 deletions src/traces/scatter/line_points.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@

'use strict';

var BADNUM = require('../../constants/numerical').BADNUM;
var numConstants = require('../../constants/numerical');
var BADNUM = numConstants.BADNUM;
var LOG_CLIP = numConstants.LOG_CLIP;
var LOG_CLIP_PLUS = LOG_CLIP + 0.5;
var LOG_CLIP_MINUS = LOG_CLIP - 0.5;
var Lib = require('../../lib');
var segmentsIntersect = Lib.segmentsIntersect;
var constrain = Lib.constrain;
Expand All @@ -19,6 +23,10 @@ var constants = require('./constants');
module.exports = function linePoints(d, opts) {
var xa = opts.xaxis;
var ya = opts.yaxis;
var xLog = xa.type === 'log';
var yLog = ya.type === 'log';
var xLen = xa._length;
var yLen = ya._length;
var connectGaps = opts.connectGaps;
var baseTolerance = opts.baseTolerance;
var shape = opts.shape;
Expand Down Expand Up @@ -59,7 +67,25 @@ module.exports = function linePoints(d, opts) {
if(!di) return false;
var x = xa.c2p(di.x);
var y = ya.c2p(di.y);
if(x === BADNUM || y === BADNUM) return false;

// if non-positive log values, set them VERY far off-screen
// so the line looks essentially straight from the previous point.
if(x === BADNUM) {
if(xLog) x = xa.c2p(di.x, true);
if(x === BADNUM) return false;
// If BOTH were bad log values, make the line follow a constant
// exponent rather than a constant slope
if(yLog && y === BADNUM) {
x *= Math.abs(xa._m * yLen * (xa._m > 0 ? LOG_CLIP_PLUS : LOG_CLIP_MINUS) /
(ya._m * xLen * (ya._m > 0 ? LOG_CLIP_PLUS : LOG_CLIP_MINUS)));
}
x *= 1000;
}
if(y === BADNUM) {
if(yLog) y = ya.c2p(di.y, true);
if(y === BADNUM) return false;
y *= 1000;
}
etpinard marked this conversation as resolved.
Show resolved Hide resolved
return [x, y];
}

Expand All @@ -79,16 +105,16 @@ module.exports = function linePoints(d, opts) {
var latestXFrac, latestYFrac;
// if we're off-screen, increase tolerance over baseTolerance
function getTolerance(pt, nextPt) {
var xFrac = pt[0] / xa._length;
var yFrac = pt[1] / ya._length;
var xFrac = pt[0] / xLen;
var yFrac = pt[1] / yLen;
var offScreenFraction = Math.max(0, -xFrac, xFrac - 1, -yFrac, yFrac - 1);
if(offScreenFraction && (latestXFrac !== undefined) &&
crossesViewport(xFrac, yFrac, latestXFrac, latestYFrac)
) {
offScreenFraction = 0;
}
if(offScreenFraction && nextPt &&
crossesViewport(xFrac, yFrac, nextPt[0] / xa._length, nextPt[1] / ya._length)
crossesViewport(xFrac, yFrac, nextPt[0] / xLen, nextPt[1] / yLen)
) {
offScreenFraction = 0;
}
Expand All @@ -114,10 +140,10 @@ module.exports = function linePoints(d, opts) {
// if both are outside there will be 0 or 2 intersections
// (or 1 if it's right at a corner - we'll treat that like 0)
// returns an array of intersection pts
var xEdge0 = -xa._length * maxScreensAway;
var xEdge1 = xa._length * (1 + maxScreensAway);
var yEdge0 = -ya._length * maxScreensAway;
var yEdge1 = ya._length * (1 + maxScreensAway);
var xEdge0 = -xLen * maxScreensAway;
var xEdge1 = xLen * (1 + maxScreensAway);
var yEdge0 = -yLen * maxScreensAway;
var yEdge1 = yLen * (1 + maxScreensAway);
var edges = [
[xEdge0, yEdge0, xEdge1, yEdge0],
[xEdge1, yEdge0, xEdge1, yEdge1],
Expand Down Expand Up @@ -261,8 +287,8 @@ module.exports = function linePoints(d, opts) {
}

function addPt(pt) {
latestXFrac = pt[0] / xa._length;
latestYFrac = pt[1] / ya._length;
latestXFrac = pt[0] / xLen;
latestYFrac = pt[1] / yLen;
// Are we more than maxScreensAway off-screen any direction?
// if so, clip to this box, but in such a way that on-screen
// drawing is unchanged
Expand Down
Binary file added test/image/baselines/log_lines_fills.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions test/image/mocks/log_lines_fills.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"data": [{
"x": [-1, 1.5, 2, 0, 1, 3, 4, 5, 6, 1, -1, -1, 3, 3, 0, 7, 7, -1, -1],
"y": [-1, 1.5, 1, -1, -1, 1, 1, 0, 2, 2, 0, 2, 3, 4, 5, 6, -2, -2, -1],
"mode": "markers+lines", "fill": "toself"
}, {
"x": [-1, 1.5, 2, 0, 1, 3, 4, 5, 6, 1, -1, -1, 3, 3, 0, 7, 7, -1, -1],
"y": [-1, 1.5, 1, -1, -1, 1, 1, 0, 2, 2, 0, 2, 3, 4, 5, 6, -2, -2, -1],
"mode": "markers+lines", "fill": "toself", "xaxis": "x2"
}, {
"x": [-1, 1.5, 2, 0, 1, 3, 4, 5, 6, 1, -1, -1, 3, 3, 0, 7, 7, -1, -1],
"y": [-1, 1.5, 1, -1, -1, 1, 1, 0, 2, 2, 0, 2, 3, 4, 5, 6, -2, -2, -1],
"mode": "markers+lines", "fill": "toself", "yaxis": "y2"
}, {
"x": [-1, 1.5, 2, 0, 1, 3, 4, 5, 6, 1, -1, -1, 3, 3, 0, 7, 7, -1, -1],
"y": [-1, 1.5, 1, -1, -1, 1, 1, 0, 2, 2, 0, 2, 3, 4, 5, 6, -2, -2, -1],
"mode": "markers+lines", "fill": "toself", "xaxis": "x2", "yaxis": "y2"
}, {
"x": [0.01, 0.1], "y": [0.01, 0.1],
"mode": "markers", "xaxis": "x2", "yaxis": "y2"
etpinard marked this conversation as resolved.
Show resolved Hide resolved
}],
"layout": {
"width": 800,
"height": 600,
"xaxis": {"title": "linear"},
"xaxis2": {"title": "log", "type": "log"},
"yaxis": {"title": "linear"},
"yaxis2": {"title": "log", "type": "log"},
"grid": {"columns": 2, "rows": 2},
"showlegend": false,
"title": "Lines to invalid log values"
}
}