Skip to content

Commit

Permalink
added pointcloud2d (squashed)
Browse files Browse the repository at this point in the history
  • Loading branch information
monfera committed Aug 12, 2016
1 parent 7387b2b commit 98f90ad
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/index-gl2d.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ var Plotly = require('./core');

Plotly.register([
require('./scattergl'),
require('./pointcloud2d'),
require('./heatmapgl'),
require('./contourgl')
]);
Expand Down
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Plotly.register([
require('./scattergeo'),
require('./choropleth'),
require('./scattergl'),
require('./pointcloud2d'),
require('./scatterternary'),
require('./scattermapbox')
]);
Expand Down
9 changes: 9 additions & 0 deletions lib/pointcloud2d.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

module.exports = require('../src/traces/pointcloud2d');
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"gl-plot3d": "^1.5.0",
"gl-scatter2d": "^1.0.5",
"gl-scatter2d-fancy": "^1.1.1",
"gl-pointcloud2d": "gl-vis/gl-pointcloud2d",
"gl-scatter3d": "^1.0.4",
"gl-select-box": "^1.0.1",
"gl-spikes2d": "^1.0.1",
Expand Down
22 changes: 22 additions & 0 deletions src/traces/pointcloud2d/attributes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var scatterglAttrs = require('../scattergl/attributes');

module.exports = {
x: scatterglAttrs.x,
x0: scatterglAttrs.x0,
dx: scatterglAttrs.dx,
y: scatterglAttrs.y,
y0: scatterglAttrs.y0,
dy: scatterglAttrs.dy,
text: scatterglAttrs.text,
marker: scatterglAttrs.marker
};
183 changes: 183 additions & 0 deletions src/traces/pointcloud2d/convert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var createPointcloud2d = require('gl-pointcloud2d');
var isNumeric = require('fast-isnumeric');

var str2RGBArray = require('../../lib/str2rgbarray');
var getTraceColor = require('../scatter/get_trace_color');

var AXES = ['xaxis', 'yaxis'];

function Pointcloud(scene, uid) {
this.scene = scene;
this.uid = uid;

this.pickXData = [];
this.pickYData = [];
this.xData = [];
this.yData = [];
this.textLabels = [];
this.color = 'rgb(0, 0, 0)';
this.name = '';
this.hoverinfo = 'all';

this.idToIndex = [];
this.bounds = [0, 0, 0, 0];

this.pointcloudOptions = {
positions: new Float32Array(0),
size: 12,
color: [0, 0, 0, 1],
borderSize: 1,
borderColor: [0, 0, 0, 1]
};
this.pointcloud = createPointcloud2d(scene.glplot, this.pointcloudOptions);
this.pointcloud._trace = this; // scene2d requires this prop
}

var proto = Pointcloud.prototype;

proto.handlePick = function(pickResult) {

var index = this.idToIndex[pickResult.pointId];

return {
trace: this,
dataCoord: pickResult.dataCoord,
traceCoord: [
this.pickXData[index],
this.pickYData[index]
],
textLabel: Array.isArray(this.textLabels) ?
this.textLabels[index] :
this.textLabels,
color: Array.isArray(this.color) ?
this.color[index] :
this.color,
name: this.name,
hoverinfo: this.hoverinfo
};
};

/**
* Truncate a Float32Array to some length. A wrapper to support environments
* (e.g. node-webkit) that do not implement Float32Array.prototype.slice
*/
function truncate(float32ArrayIn, len) {
if(Float32Array.slice === undefined) {
var float32ArrayOut = new Float32Array(len);
for(var i = 0; i < len; i++) float32ArrayOut[i] = float32ArrayIn[i];
return float32ArrayOut;
}

return float32ArrayIn.slice(0, len);
}

proto.update = function(options) {

this.textLabels = options.text;
this.name = options.name;
this.hoverinfo = options.hoverinfo;
this.bounds = [Infinity, Infinity, -Infinity, -Infinity];

this.updateFast(options);

this.color = getTraceColor(options, {});
};

proto.updateFast = function(options) {
var x = this.xData = this.pickXData = options.x;
var y = this.yData = this.pickYData = options.y;

var len = x.length,
idToIndex = new Array(len),
positions = new Float32Array(2 * len),
bounds = this.bounds,
pId = 0,
ptr = 0;

var xx, yy;

// TODO add 'very fast' mode that bypasses this loop
// TODO bypass this on modebar +/- zoom
for(var i = 0; i < len; ++i) {
xx = x[i];
yy = y[i];

// check for isNaN is faster but doesn't skip over nulls
if(!isNumeric(xx) || !isNumeric(yy)) continue;

idToIndex[pId++] = i;

positions[ptr++] = xx;
positions[ptr++] = yy;

bounds[0] = Math.min(bounds[0], xx);
bounds[1] = Math.min(bounds[1], yy);
bounds[2] = Math.max(bounds[2], xx);
bounds[3] = Math.max(bounds[3], yy);
}

positions = truncate(positions, ptr);
this.idToIndex = idToIndex;

var markerSize;

this.pointcloudOptions.positions = positions;

var markerColor = str2RGBArray(options.marker.color),
borderColor = str2RGBArray(options.marker.line.color),
opacity = options.opacity * options.marker.opacity;

markerColor[3] *= opacity;
this.pointcloudOptions.color = markerColor;

borderColor[3] *= opacity;
this.pointcloudOptions.borderColor = borderColor;

markerSize = options.marker.size;
this.pointcloudOptions.size = markerSize;
this.pointcloudOptions.borderSize = options.marker.line.width;

this.pointcloud.update(this.pointcloudOptions);

// add item for autorange routine
this.expandAxesFast(bounds, markerSize);
};

proto.expandAxesFast = function(bounds, markerSize) {
var pad = markerSize || 10;
var ax, min, max;

for(var i = 0; i < 2; i++) {
ax = this.scene[AXES[i]];

min = ax._min;
if(!min) min = [];
min.push({ val: bounds[i], pad: pad });

max = ax._max;
if(!max) max = [];
max.push({ val: bounds[i + 2], pad: pad });
}
};

proto.dispose = function() {
this.pointcloud.dispose();
};

function createPointcloud(scene, data) {
var plot = new Pointcloud(scene, data.uid);
plot.update(data);
return plot;
}

module.exports = createPointcloud;
33 changes: 33 additions & 0 deletions src/traces/pointcloud2d/defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/


'use strict';

var Lib = require('../../lib');

var handleXYDefaults = require('../scatter/xy_defaults');
var handleMarkerDefaults = require('../scatter/marker_defaults');

var attributes = require('./attributes');

module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
function coerce(attr, dflt) {
return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
}

var len = handleXYDefaults(traceIn, traceOut, coerce);
if(!len) {
traceOut.visible = false;
return;
}

coerce('text');

handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce);
};
31 changes: 31 additions & 0 deletions src/traces/pointcloud2d/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var Pointcloud2d = {};

Pointcloud2d.attributes = require('./attributes');
Pointcloud2d.supplyDefaults = require('./defaults');

// reuse the Scatter3D 'dummy' calc step so that legends know what to do
Pointcloud2d.calc = require('../scatter3d/calc');
Pointcloud2d.plot = require('./convert');

Pointcloud2d.moduleType = 'trace';
Pointcloud2d.name = 'pointcloud2d';
Pointcloud2d.basePlotModule = require('../../plots/gl2d');
Pointcloud2d.categories = ['gl2d', 'showLegend'];
Pointcloud2d.meta = {
description: [
'The data visualized as a point cloud set in `x` and `y`',
'using the WebGl plotting engine.'
].join(' ')
};

module.exports = Pointcloud2d;

0 comments on commit 98f90ad

Please sign in to comment.