Skip to content

Commit

Permalink
add _hasOnlyLargeSploms flag
Browse files Browse the repository at this point in the history
which:
- adds only a limited number svg layer in each <g .subplot>
- use regl-line2d to draw grids
  • Loading branch information
etpinard committed Mar 28, 2018
1 parent 20f01cc commit c5cda6b
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 34 deletions.
92 changes: 58 additions & 34 deletions src/plots/cartesian/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,15 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout)
var hadGl, hasGl;
var i, k, subplotInfo, moduleName;

// when going from a large splom graph to something else,
// we need to clear <g subplot> so that the new cartesian subplot
// can have the correct layer ordering
if(oldFullLayout._hasOnlyLargeSploms && !newFullLayout._hasOnlyLargeSploms) {
for(k in oldPlots) {
subplotInfo = oldPlots[k];
if(subplotInfo.plotgroup) subplotInfo.plotgroup.remove();
}
}

for(i = 0; i < oldModules.length; i++) {
moduleName = oldModules[i].name;
Expand Down Expand Up @@ -330,7 +339,7 @@ exports.drawFramework = function(gd) {
// initialize list of overlay subplots
plotinfo.overlays = [];

makeSubplotLayer(plotinfo);
makeSubplotLayer(gd, plotinfo);

// fill in list of overlay subplots
if(plotinfo.mainplot) {
Expand All @@ -346,7 +355,7 @@ exports.drawFramework = function(gd) {
};

exports.rangePlot = function(gd, plotinfo, cdSubplot) {
makeSubplotLayer(plotinfo);
makeSubplotLayer(gd, plotinfo);
plotOne(gd, plotinfo, cdSubplot);
Plots.style(gd);
};
Expand Down Expand Up @@ -377,45 +386,58 @@ function makeSubplotData(gd) {
return subplotData;
}

function makeSubplotLayer(plotinfo) {
function makeSubplotLayer(gd, plotinfo) {
var plotgroup = plotinfo.plotgroup;
var id = plotinfo.id;
var xLayer = constants.layerValue2layerClass[plotinfo.xaxis.layer];
var yLayer = constants.layerValue2layerClass[plotinfo.yaxis.layer];
var hasOnlyLargeSploms = gd._fullLayout._hasOnlyLargeSploms;

if(!plotinfo.mainplot) {
var backLayer = ensureSingle(plotgroup, 'g', 'layer-subplot');
plotinfo.shapelayer = ensureSingle(backLayer, 'g', 'shapelayer');
plotinfo.imagelayer = ensureSingle(backLayer, 'g', 'imagelayer');

plotinfo.gridlayer = ensureSingle(plotgroup, 'g', 'gridlayer');
if(hasOnlyLargeSploms) {
// TODO could do even better
// - we don't need plot (but we would have to mock it in lsInner
// and other places
// - we don't (x|y)lines and (x|y)axislayer for most subplots
// usually just the bottom x and left y axes.
plotinfo.plot = ensureSingle(plotgroup, 'g', 'plot');
plotinfo.xlines = ensureSingle(plotgroup, 'path', 'xlines-above');
plotinfo.ylines = ensureSingle(plotgroup, 'path', 'ylines-above');
plotinfo.xaxislayer = ensureSingle(plotgroup, 'g', 'xaxislayer-above');
plotinfo.yaxislayer = ensureSingle(plotgroup, 'g', 'yaxislayer-above');
}
else {
var backLayer = ensureSingle(plotgroup, 'g', 'layer-subplot');
plotinfo.shapelayer = ensureSingle(backLayer, 'g', 'shapelayer');
plotinfo.imagelayer = ensureSingle(backLayer, 'g', 'imagelayer');

plotinfo.zerolinelayer = ensureSingle(plotgroup, 'g', 'zerolinelayer');
plotinfo.gridlayer = ensureSingle(plotgroup, 'g', 'gridlayer');
plotinfo.zerolinelayer = ensureSingle(plotgroup, 'g', 'zerolinelayer');

ensureSingle(plotgroup, 'path', 'xlines-below');
ensureSingle(plotgroup, 'path', 'ylines-below');
plotinfo.overlinesBelow = ensureSingle(plotgroup, 'g', 'overlines-below');
ensureSingle(plotgroup, 'path', 'xlines-below');
ensureSingle(plotgroup, 'path', 'ylines-below');
plotinfo.overlinesBelow = ensureSingle(plotgroup, 'g', 'overlines-below');

ensureSingle(plotgroup, 'g', 'xaxislayer-below');
ensureSingle(plotgroup, 'g', 'yaxislayer-below');
plotinfo.overaxesBelow = ensureSingle(plotgroup, 'g', 'overaxes-below');
ensureSingle(plotgroup, 'g', 'xaxislayer-below');
ensureSingle(plotgroup, 'g', 'yaxislayer-below');
plotinfo.overaxesBelow = ensureSingle(plotgroup, 'g', 'overaxes-below');

plotinfo.plot = ensureSingle(plotgroup, 'g', 'plot');
plotinfo.overplot = ensureSingle(plotgroup, 'g', 'overplot');
plotinfo.plot = ensureSingle(plotgroup, 'g', 'plot');
plotinfo.overplot = ensureSingle(plotgroup, 'g', 'overplot');

ensureSingle(plotgroup, 'path', 'xlines-above');
ensureSingle(plotgroup, 'path', 'ylines-above');
plotinfo.overlinesAbove = ensureSingle(plotgroup, 'g', 'overlines-above');
plotinfo.xlines = ensureSingle(plotgroup, 'path', 'xlines-above');
plotinfo.ylines = ensureSingle(plotgroup, 'path', 'ylines-above');

ensureSingle(plotgroup, 'g', 'xaxislayer-above');
ensureSingle(plotgroup, 'g', 'yaxislayer-above');
plotinfo.overaxesAbove = ensureSingle(plotgroup, 'g', 'overaxes-above');
ensureSingle(plotgroup, 'g', 'xaxislayer-above');
ensureSingle(plotgroup, 'g', 'yaxislayer-above');
plotinfo.overaxesAbove = ensureSingle(plotgroup, 'g', 'overaxes-above');

// set refs to correct layers as determined by 'axis.layer'
plotinfo.xlines = plotgroup.select('.xlines-' + xLayer);
plotinfo.ylines = plotgroup.select('.ylines-' + yLayer);
plotinfo.xaxislayer = plotgroup.select('.xaxislayer-' + xLayer);
plotinfo.yaxislayer = plotgroup.select('.yaxislayer-' + yLayer);
// set refs to correct layers as determined by 'axis.layer'
plotinfo.xlines = plotgroup.select('.xlines-' + xLayer);
plotinfo.ylines = plotgroup.select('.ylines-' + yLayer);
plotinfo.xaxislayer = plotgroup.select('.xaxislayer-' + xLayer);
plotinfo.yaxislayer = plotgroup.select('.yaxislayer-' + yLayer);
}
}
else {
var mainplotinfo = plotinfo.mainplotinfo;
Expand Down Expand Up @@ -450,14 +472,16 @@ function makeSubplotLayer(plotinfo) {
plotinfo.yaxislayer = mainplotgroup.select('.overaxes-' + yLayer).select('.' + yId);
}

ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.xaxis._id);
ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.yaxis._id);
plotinfo.gridlayer.selectAll('g').sort(axisIds.idSort);

// common attributes for all subplots, overlays or not

for(var i = 0; i < constants.traceLayerClasses.length; i++) {
ensureSingle(plotinfo.plot, 'g', constants.traceLayerClasses[i]);
if(!hasOnlyLargeSploms) {
ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.xaxis._id);
ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.yaxis._id);
plotinfo.gridlayer.selectAll('g').sort(axisIds.idSort);

for(var i = 0; i < constants.traceLayerClasses.length; i++) {
ensureSingle(plotinfo.plot, 'g', constants.traceLayerClasses[i]);
}
}

plotinfo.xlines
Expand Down
13 changes: 13 additions & 0 deletions src/plots/plots.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,19 @@ plots.supplyDefaults = function(gd) {
// finally, fill in the pieces of layout that may need to look at data
plots.supplyLayoutModuleDefaults(newLayout, newFullLayout, newFullData, gd._transitionData);

// turn on flag to optimize large splom-only graphs
// mostly by omitting SVG layers during Cartesian.drawFramework
if(
newFullLayout._basePlotModules.length === 1 &&
newFullLayout._basePlotModules[0].name === 'splom' &&
splomXa.length > 15 &&
splomYa.length > 15 &&
newFullLayout.shapes.length === 0 &&
newFullLayout.images.length === 0
) {
newFullLayout._hasOnlyLargeSploms = 1;
}

// TODO remove in v2.0.0
// add has-plot-type refs to fullLayout for backward compatibility
newFullLayout._hasCartesian = newFullLayout._has('cartesian');
Expand Down
114 changes: 114 additions & 0 deletions src/traces/splom/base_plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
'use strict';

var createRegl = require('regl');
var createLine = require('regl-line2d');

var Registry = require('../../registry');
var Lib = require('../../lib');
var getModuleCalcData = require('../../plots/get_data').getModuleCalcData;
var Cartesian = require('../../plots/cartesian');
var AxisIDs = require('../../plots/cartesian/axis_ids');
Expand Down Expand Up @@ -43,11 +45,16 @@ function plot(gd) {
});
});

if(fullLayout._hasOnlyLargeSploms) {
drawGrid(gd);
}

_module.plot(gd, {}, splomCalcData);
}

function drag(gd) {
var cd = gd.calcdata;
var fullLayout = gd._fullLayout;

for(var i = 0; i < cd.length; i++) {
var cd0 = cd[i][0];
Expand All @@ -68,6 +75,112 @@ function drag(gd) {
scene.matrix.draw();
}
}

if(fullLayout._hasOnlyLargeSploms) {
fullLayout._modules[0].basePlotModule.drawGrid(gd);
}
}

function drawGrid(gd) {
var fullLayout = gd._fullLayout;
var regl = fullLayout._glcanvas.data()[0].regl;
var splomGrid = fullLayout._splomGrid;

if(!splomGrid) {
splomGrid = fullLayout._splomGrid = createLine(regl);
}
splomGrid.update(makeGridData(gd));
splomGrid.draw();
}

function makeGridData(gd) {
var fullLayout = gd._fullLayout;
var gs = fullLayout._size;
var fullView = [0, 0, fullLayout.width, fullLayout.height];
var splomXa = Object.keys(fullLayout._splomAxes.x);
var splomYa = Object.keys(fullLayout._splomAxes.y);
var lookup = {};
var k;

function push(prefix, ax, x0, x1, y0, y1) {
var lcolor = ax[prefix + 'color'];
var lwidth = ax[prefix + 'width'];
var key = String(lcolor + lwidth);

if(key in lookup) {
lookup[key].data.push(NaN, NaN, x0, x1, y0, y1);
} else {
lookup[key] = {
data: [x0, x1, y0, y1],
join: 'rect',
thickness: lwidth,
color: lcolor,
viewport: fullView,
range: fullView
};
}
}

for(var i = 0; i < splomXa.length; i++) {
var xa = AxisIDs.getFromId(gd, splomXa[i]);
var xVals = xa._vals;
var xShowZl = showZeroLine(xa);

for(var j = 0; j < splomYa.length; j++) {
var ya = AxisIDs.getFromId(gd, splomYa[j]);
var yVals = ya._vals;
var yShowZl = showZeroLine(ya);

// ya.l2p assumes top-to-bottom coordinate system (a la SVG),
// we need to compute bottom-to-top offsets and slopes:
var yOffset = gs.b + ya.domain[0] * gs.h;
var ym = -ya._m;
var yb = -ym * ya.r2l(ya.range[0], ya.calendar);

var x, y;

if(xa.showgrid) {
for(k = 0; k < xVals.length; k++) {
x = xa._offset + xa.l2p(xVals[k].x);
push('grid', xa, x, yOffset, x, yOffset + ya._length);
}
}
if(xShowZl) {
x = xa._offset + xa.l2p(0);
push('zeroline', xa, x, yOffset, x, yOffset + ya._length);
}
if(ya.showgrid) {
for(k = 0; k < yVals.length; k++) {
y = yOffset + yb + ym * yVals[k].x;
push('grid', ya, xa._offset, y, xa._offset + xa._length, y);
}
}
if(yShowZl) {
y = yOffset + yb + 0;
push('zeroline', ya, xa._offset, y, xa._offset + xa._length, y);
}
}
}

var gridBatches = [];
for(k in lookup) {
gridBatches.push(lookup[k]);
}

return gridBatches;
}

function showZeroLine(ax) {
var rng = Lib.simpleMap(ax.range, ax.r2l);
var p0 = ax.l2p(0);

return (
ax.zeroline &&
ax._vals && ax._vals.length &&
(rng[0] * rng[1] <= 0) &&
(ax.type === 'linear' || ax.type === '-') &&
((p0 > 1 && p0 < ax._length - 1) || !ax.showline)
);
}

function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) {
Expand All @@ -85,6 +198,7 @@ module.exports = {
drawFramework: Cartesian.drawFramework,
plot: plot,
drag: drag,
drawGrid: drawGrid,
clean: clean,
toSVG: Cartesian.toSVG
};

0 comments on commit c5cda6b

Please sign in to comment.