diff --git a/inst/htmlwidgets/scatterplotThree.js b/inst/htmlwidgets/scatterplotThree.js
index 7652ae9..b7cd3d8 100644
--- a/inst/htmlwidgets/scatterplotThree.js
+++ b/inst/htmlwidgets/scatterplotThree.js
@@ -1,4 +1,3 @@
-/* Standard HTML widgets interface */
HTMLWidgets.widget(
{
name: "scatterplotThree",
@@ -38,7 +37,7 @@ HTMLWidgets.widget(
* animate() internal threejs animation function
* render() internal threejs draw function
* update() internal vertex update function
- * update_lines() internal lines update function
+ * update_lines(lcol) internal lines update function
* ... other miscellaneous internal functions
*
* The htmlwidgets interface resides in the init() function.
@@ -242,10 +241,10 @@ Widget.scatter = function(w, h)
if(I[0].object.type == "Points")
{
idx = I.map(function(x) {
- return I[0].object.geometry.attributes.color.array[x.index * 4 + 3] > 0.1;
+ return I[0].object.geometry.attributes.color.array[x.object.indices[x.index] * 4 + 3] > 0.1;
}).indexOf(true);
if(idx < 0) return;
- i = "" + I[idx].index;
+ i = "" + I[idx].object.indices[I[idx].index];
} else
{
idx = I[0].object.index;
@@ -323,10 +322,83 @@ Widget.scatter = function(w, h)
}
}
- _this.brush = function(i)
+/* TODO clean this up; consolidate vertex and line color setting code
+ */
+ _this.brush = function(vertices)
{
if(!_this.options.brush) return;
- console.log("brush " + i); // XXX
+ if(!vertices && !_this.brushed) return; // nothing to do
+ if(!vertices) // reset brush and return
+ {
+ for(var j = 0; j < _this.pointgroup.children.length; j++)
+ {
+ if(_this.pointgroup.children[j].type == "Mesh") // spheres
+ {
+ k = _this.pointgroup.children[j].index; // the vertex id
+ _this.pointgroup.children[j].material.color = new THREE.Color(_this.datacolor[k]);
+ } else if(_this.pointgroup.children[j].type == "Points") // buffered
+ {
+ for(var i = 0; i < _this.pointgroup.children[j].geometry.attributes.position.array.length / 3; i++)
+ {
+ k = _this.pointgroup.children[j].indices[i]; // vertex id
+ var col = new THREE.Color(_this.datacolor[k]);
+ _this.pointgroup.children[j].geometry.attributes.color.array[i * 4] = col.r;
+ _this.pointgroup.children[j].geometry.attributes.color.array[i * 4 + 1] = col.g;
+ _this.pointgroup.children[j].geometry.attributes.color.array[i * 4 + 2] = col.b;
+ }
+ _this.pointgroup.children[j].geometry.attributes.color.needsUpdate = true;
+ }
+ }
+ update_lines(null);
+ _this.brushed = null;
+ return;
+ }
+ var off = new THREE.Color("lightgray"); // XXX make option
+ var on = new THREE.Color("red");
+ if(! Array.isArray(vertices)) vertices = [vertices]; // XXX why does this become a string?
+ var k;
+ for(var j = 0; j < _this.pointgroup.children.length; j++)
+ {
+ if(_this.pointgroup.children[j].type == "Mesh") // spheres
+ {
+ k = _this.pointgroup.children[j].index; // the vertex id
+ if(vertices.indexOf(k + "") >= 0) _this.pointgroup.children[j].material.color = on;
+ else _this.pointgroup.children[j].material.color = off;
+ } else if(_this.pointgroup.children[j].type == "Points") // buffered
+ {
+ for(var i = 0; i < _this.pointgroup.children[j].geometry.attributes.position.array.length / 3; i++)
+ {
+ k = _this.pointgroup.children[j].indices[i]; // vertex id
+ if(vertices.indexOf(k + "") >= 0)
+ {
+ _this.pointgroup.children[j].geometry.attributes.color.array[i * 4] = on.r;
+ _this.pointgroup.children[j].geometry.attributes.color.array[i * 4 + 1] = on.g;
+ _this.pointgroup.children[j].geometry.attributes.color.array[i * 4 + 2] = on.b;
+ } else
+ {
+ _this.pointgroup.children[j].geometry.attributes.color.array[i * 4] = off.r;
+ _this.pointgroup.children[j].geometry.attributes.color.array[i * 4 + 1] = off.g;
+ _this.pointgroup.children[j].geometry.attributes.color.array[i * 4 + 2] = off.b;
+ }
+ }
+ _this.pointgroup.children[j].geometry.attributes.color.needsUpdate = true;
+ }
+ }
+ // now brush edges
+ var s = _this.scene;
+ if(_this.options.from.length <= s) s = 0;
+ var lcol = [];
+ lcol.length = _this.options.from[s].length;
+ lcol.fill("#" + off.getHexString());
+ for(var j = 0; j < lcol.length; j++)
+ {
+ if(vertices.indexOf(_this.options.from[s][j] + "") >= 0) lcol[j] = "#" + on.getHexString();
+ if(vertices.indexOf(_this.options.to[s][j] + "") >= 0) lcol[j] = "#" + on.getHexString();
+ }
+ update_lines(lcol);
+
+
+ _this.brushed = true;
};
// create_plot
@@ -426,6 +498,7 @@ Widget.scatter = function(w, h)
if(_this.renderer.GL)
{
_this.N = x.vertices[0].length / 3; // number of vertices
+
if(x.fpl) _this.fps = x.fpl;
if(x.fps) _this.fps = x.fps; // alternative notation
if(!_this.fps) _this.fps = 200; // default frames per scene
@@ -489,17 +562,17 @@ Widget.scatter = function(w, h)
}
for(var j=0; j < unique_pch.length; j++)
{
- npoints = 0;
+ var pchpoints = 0;
for (var i = 0; i < _this.N; i++)
{
- if(x.pch[i] == unique_pch[j]) npoints++;
+ if(x.pch[i] == unique_pch[j]) pchpoints++;
}
var geometry = new THREE.BufferGeometry();
- var positions = new Float32Array(npoints * 3);
- var colors = new Float32Array(npoints * 4);
- var sizes = new Float32Array(npoints);
- var indices = new Int32Array(npoints);
- var col = new THREE.Color("steelblue");
+ var positions = new Float32Array(pchpoints * 3);
+ var colors = new Float32Array(pchpoints * 4);
+ var sizes = new Float32Array(pchpoints);
+ var indices = new Int32Array(pchpoints);
+ var col = new THREE.Color("orange");
scale = 0.3;
// generic pch sprite (text)
var canvas = document.createElement("canvas");
@@ -534,10 +607,11 @@ Widget.scatter = function(w, h)
var k = 0;
for (var i = 0; i < _this.N; i++)
{
- if(Array.isArray(x.size)) sizes[i] = x.size[i] * scalefactor;
- else sizes[i] = scale * scalefactor;
if(x.pch[i] == unique_pch[j])
{
+ npoints++;
+ if(Array.isArray(x.size)) sizes[k] = x.size[i] * scalefactor;
+ else sizes[k] = scale * scalefactor;
if(x.labels && Array.isArray(x.labels)) geometry.labels.push(x.labels[i]);
else geometry.labels.push("");
indices[k] = i; // track vertex index
@@ -746,7 +820,7 @@ Widget.scatter = function(w, h)
*/
if(x.from && _this.renderer.GL)
{
- update_lines();
+ update_lines(null);
}
if(x.vertices.length > 1) _this.frame = 0; // animate
_this.idle = false;
@@ -865,12 +939,12 @@ Widget.scatter = function(w, h)
if(_this.scene >= _this.options.vertices.length - 1) _this.frame = -1; // done!
else _this.frame = 0; // more scenes to animate, reset frame counter
}
- if(_this.options.from) update_lines();
+ if(_this.options.from) update_lines(null);
}
}
/* buffered lines */
- function update_lines()
+ function update_lines(l)
{
var s = _this.scene;
if(_this.options.from.length <= s) s = 0;
@@ -883,7 +957,11 @@ Widget.scatter = function(w, h)
var from = _this.options.from[s][i];
var to = _this.options.to[s][i];
var c1, c2;
- if(_this.options.lcol)
+ if(l)
+ {
+ c1 = new THREE.Color(l[i]);
+ c2 = c1;
+ } else if(_this.options.lcol)
{
if(Array.isArray(_this.options.lcol))
{