How can I determine if a point is hidden on a 3D Scatterplot (Plotly.js)? - d3.js

I'm using Plotly.js to draw a 3-D scatter plot . On zoom , I want to check which points are visible . Can this be done on svg level ? or any plotly expert ?
Snippet:
var myPlot = document.getElementById("myDiv");
var trace = {
x: [1, 7, 2, 4,1],
y: [12, 9, 15, 12,2],
z: [1, 2, 4, 8,4],
// x: [1,2],
//y: [12,15],
//z: [1, 4],
mode: 'markers' ,
type: 'scatter3d' ,
marker: {size:5 }
}
var data = [trace];
var layout = {
margin: {
l: 0,
r: 0,
b: 0,
t: 0} ,
//title: {text: 'ReOptim8 Scatter Plot'},
scene: {
yaxis:{title: 'X-axis'},
xaxis:{title: 'y-axis'},
zaxis:{title: 'z-axis'},
camera: {eye: {x:1.25, y:1.25, z:1.25}}
}
};
var config = {
displayModebar : true,
displaylogo: false,
responsive: true
};
Plotly.plot( myPlot, data, layout, config );
Code pen link below :
https://codepen.io/aniwar/pen/wLOzZv

Related

Object3D.lookAt() in instanced meshes not as expected?

I'm building a particle system in which particles have directions they are pointing at and I want to reflect that in an instance mesh I use to present them, but something is not quite working... It seems that the center of rotation and/or the up axis are not quite right, and despite me console logging stuff I could not find the problem. Here's the code:
const Particles = (particleSystem: TparticleSystem) => {
const mesh = useRef<THREE.InstancedMesh>(null);
const light = useRef<THREE.PointLight>(null);
const dummy = useMemo(() => new THREE.Object3D(), []);
const pyramid = useMemo(() => {
return {
vertices: [1, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, -1, 0, 2, 0],
indices: [0, 1, 2, 2, 3, 0, 0, 4, 1, 1, 4, 2, 2, 4, 3, 3, 4, 0],
};
}, []);
useFrame(() => {
if (particleSystem !== undefined) {
particleSystem.update();
particleSystem.move();
particleSystem.particles.forEach((particle: Tparticle, index: number) => {
dummy.position.set(particle.pos.x, particle.pos.y, particle.pos.z);
dummy.lookAt(vec().copy(particle.pos).add(particle.dir)); // rotating weird
dummy.scale.set(1, 2, 1);
dummy.updateMatrix();
// And apply the matrix to the instanced item
if (mesh.current) mesh.current.setMatrixAt(index, dummy.matrix);
});
if (mesh.current) mesh.current.instanceMatrix.needsUpdate = true;
}
});
return (
<>
<pointLight ref={light} distance={40} intensity={3} color="lightblue" />
{particleSystem !== undefined && (
<instancedMesh ref={mesh} args={[, , particleSystem.num]}>
<polyhedronBufferGeometry
args={[pyramid.vertices, pyramid.indices, 1, 0]}
/>
<meshBasicMaterial
color="#2596be"
wireframe={Math.random() > 0.5 ? true : false}
/>
</instancedMesh>
)}
</>
);
};
I feel like maybe this is something to do with local and world coordinates, but I don't quite understand it.
Oh! and this vec stuff is just
const vec = function (x = 0, y = 0, z = 0) {
return new THREE.Vector3(x, y, z);
};

Handsontable cross calculations

I have a handontable demo.
document.addEventListener("DOMContentLoaded", function() {
var
example = document.getElementById('example1'),
hot1;
hot1 = new Handsontable(example, {
data: [
['', '', '', ''],
[1, 2, 3, '=SUM(A2:C2)'],
[1, 2, 3],
],
width: 584,
height: 320,
rowHeaders: true,
formulas: true,
colHeaders: true,
columns: [1, 2, 3, 4],
columnSummary: function () {
var summary = [];
for (var i = 0; i < 4; i++) {
summary.push({
ranges: [[1, 2]],
destinationRow: 0,
destinationColumn: i,
type: 'sum',
forceNumeric: true,
sourceColumn: i
});
}
return summary;
}
});
});
It caclulates:
Sum of column and puts a result in the first raw.
Sum of rows (except first one) and puts it in the column "D"
I need to calculate correct total of the totals, which is the cell D1.
After loading and changing any cell calculation of D1 has to work properly.
Thank you for any ideas.
The option columnSummary should not be applied on the 4th column (the column of SUM results). Try to apply you code of columnSummary option only for the first three columns :
for (var i = 0; i < 3; i++) //Instead of i < 4
And use in the row one what you use to calculate the sum on your other rows :
data: [
['', '', '', '=SUM(A1:C1)'],
[1, 2, 3, '=SUM(A2:C2)'],
[1, 2, 3, '=SUM(A3:C3)'],
],
You will see that it works like a charm : JSFiddle.

Highcharts - draw line chart with summed values but show breakup on hover

I am using Highcharts - Line - Ajax.
Let's say I have two series of data - 'Headcount 1' and 'Headcount 2'. I want to draw a line graph of 'Headcount', which is the sum of the 2 series. However, when someone hovers on one data point, I want to show the individual values in the callout. Is this possible? How can I do this?
e.g.
H1 = (1, 2, 3)
H2 = (5, 6, 7)
Ht = (6, 8, 10)
I will draw a line graph with Ht. If I hover on '6' on the chart, the callout should show the values of H1 = 1 and H2 = 5
You can set the visibility for series H1 and H2 to false,
series: [{
name: 'H1',
data: [1, 2, 3],
visible: false,
showInLegend: false
}, {
name: 'H2',
data: [5, 6, 7],
visible: false,
showInLegend: false
}, {
name: 'H',
data: [6, 8, 10]
}]
and edit tooltip formatter to display what you want
tooltip: {
formatter: function() {
var s = '<b>' + this.x + '</b>';
var chart = this.points[0].series.chart; //get the chart object
var categories = chart.xAxis[0].categories; //get the categories array
var index = 0;
while(this.x !== categories[index]){index++;} //compute the index of corr y value in each data arrays
$.each(chart.series, function(i, series) { //loop through series array
if (series.name !== 'H') {
s += '<br/>'+ series.name +': ' +
series.data[index].y +'m'; //use index to get the y value
}
});
return s;
},
shared: true
}
Have a look at jsfiddle.net/s190ebby/27/
Yes
Points can have custom property, taking care that the names do not shadow highcharts variable names.
var data = [{
y: 6,
h1Value: 1,
h2Value: 5
},{
y: 8,
h1Value: 2,
h2Value: 6
}];
Set your series to this data in your config object, by series: data
Customise the tooltip as:
tooltip: {
pointFormat: '<b>H Value</b>: {point.y}<br/>
<b>H1 Value</b>: {point.h1Value}<br/>
<b>H2 Value</b>: {point.h2Value}'
}

Adding custom non-uniform labels to a Y-axis of a stacked area chart in NVD3

I want a stacked area chart of several datasets. possibly unusually I want to use the y axis to clarify what each set represents and its starting value.
i.e. The Y-axis doesn't need to be a regular tick over the range of the data.
for the sets:
[
{key: 'the first set', values: [x: 0, y: 4]},
{key: 'the second set', values: [x: 0, y: 10]},
]
the y-axis should have a tick at 4 labelled: 'the first set: 4', and another at 10 labelled: 'the second set: 10'
nv.addGraph(function() {
var chart = nv.models.stackedAreaChart()
.showLegend(false)
.showControls(false);
var data = [
{
key: 'first',
values: [
{ x: 0, y: 2 },
{ x: 2, y: 4 },
{ x: 4, y: 6 },
{ x: 6, y: 8 }
]
},
{
key: 'second',
values: [
{ x: 0, y: 4 },
{ x: 2, y: 6 },
{ x: 4, y: 8 },
{ x: 6, y: 10 }
]
}
];
var firstItemsLabels = ['', 'first', 'second', ''];
var firstItemsValues = [0, 2, 4, 10];
//the below doesn't seem to make any difference
//var firstItemsLabels = ['first', 'second'];
//var firstItemsValues = [2, 4];
chart.yAxis.tickValues(firstItemsLabels);
chart.yAxis.tickFormat(function(d, i) {
console.log('getting tick format for d: "' + d + '" at i ' + i);
console.log('for i: ' + i + ' = ' + firstItemsValues[i]);
var result = firstItemsValues[i];
return result;
});
d3.select('#chart svg')
.datum(data)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.13/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.css" rel="stylesheet">
<div id="chart">
<svg></svg>
</div>
I thought that the code in this snippet should achieve that but it doesn't
The console log output from that snippet...
getting tick format for d: "" at i 0
for i: 0 = 0
getting tick format for d: "first" at i 1
for i: 1 = 2
Error: Invalid value for <g> attribute transform="translate(0,NaN)
getting tick format for d: "0" at i undefined
for i: undefined = undefined
getting tick format for d: "18" at i undefined
for i: undefined = undefined
...confuses me because tickformat is looking for a value of 18 at one point which isn't in the dataset.
Am I trying to achieve something impossible? If not, since I'm clearly doing it wrong, how can it be done?
If I understand your goal correctly, you can use:
chart.yAxis.tickValues([4,10]);
chart.yAxis.tickFormat(function(d, i) {
if (d === 4 || d == 10) {
return "the first set: " + d
}
});
See this Plunk for a working example:
http://plnkr.co/edit/sdM14ebvv8cYCvOtX8em?p=preview

jqplot tooltipContentEditor displays wrong x and y values

I have a jqplot line graph with this line:
`var line = [[1,0.493],
[1,1.286],
[2,0.305],
[2,0.516],
[2,0.551],
[2,0.595],
[2,0.609],
[2,0.644],
[2,0.65],
[2,1.249],
[2,1.265],
[4,0.443],
[5,0.288],
[5,0.477],
[5,0.559],
[5,0.562],
[6,0.543],
[7,0.513],
[7,0.549],
[8,0.442],
[8,0.467],
[8,0.468],
[8,0.597],
[8,0.857]];`
Im using tooltipContentEditor to display the x and y values of the point on hover. I need the values displayed to be exact.
Here is the code Im using: http://jsfiddle.net/ZQh38/1/
The problem:
Sometimes, the x and y values displayed are incorrect. For example, the last points at (6, 0.5) and (7, 0.5)
The values are only displayed with 1 decimal, which needs to be 3.
So, the question is, how do I get the exact y values?
Ive also tried to use the pointIndex, which does NOT match with the values in the line.
Thanks for your help!
Here is the solution to your problem: jsFiddle example
I made changes to your highlighter option.
/*
Drawing graphs
*/
var Statistics = {
scatter: false,
trendline: false,
enableLabels: true,
showAverage: false,
colour: null,
//Graph properties
scatterPlot: function(on){
Statistics.scatter = on;
},
showTrendline: function(on){
$.jqplot.config.enablePlugins = on;
Statistics.trendline = on;
},
disableLabels: function(yes){
Statistics.enableLabels = (!yes);
},
shouldDrawScatter: function(){
return (!Statistics.scatter);
},
useLabels: function(){
return Statistics.enableLabels;
},
getTrendline: function(){
return Statistics.trendline;
},
//Drawing
drawLabels: function(){
document.getElementById('ylabel').innerHTML = Statistics.ylabel;
document.getElementById('xlabel').innerHTML = Statistics.xlabel;
},
generateGraph: function(){
var line = [[1,0.493],
[1,1.286],
[2,0.305],
[2,0.516],
[2,0.551],
[2,0.595],
[2,0.609],
[2,0.644],
[2,0.65],
[2,1.249],
[2,1.265],
[4,0.443],
[5,0.288],
[5,0.477],
[5,0.559],
[5,0.562],
[6,0.543],
[7,0.513],
[7,0.549],
[8,0.442],
[8,0.467],
[8,0.468],
[8,0.597],
[8,0.857]];
var plot = $.jqplot('chart', [line], {
animate: true,
grid:{backgroundColor: 'white'},
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
ticks: [1, 2, 3, 4, 5, 6, 7],
tickOptions: {
fontFamily: '"Helvetica", cursive',
fontSize: '12pt'
}
},
yaxis: {
tickOptions: {
fontFamily: '"Helvetica", cursive',
fontSize: '12pt'
},
max: 2,
min: 0
}
},
series:[{
color: "#594A42",
lineWidth: 2.5,
shadow: false,
fillColor: "#594A42",
markerOptions: {
style:'filledCircle',
color: "#594A42",
shadow: false,
size: 10
},
showLine: false,
trendline: {
color: '#999'
},
rendererOptions:{
animation: {
speed: 2000 //Speeding up animation
}
}
}],
highlighter: {
show: true,
fadeTooltip: true,
sizeAdjust: 6,
tooltipContentEditor: function(str, pointIndex, index, plot){
var splitted = plot._plotData[1][index];
var x = splitted[0];
var y = splitted[1];
return x + ", " + y;
}
}
});
},
//Checks if the graph will be a straight line
straightLine: function(lineArray){
if(typeof lineArray != 'undefined' && lineArray.length > 0) {
for(var i = 1; i < lineArray.length; i++)
{
if(lineArray[i] !== lineArray[0])
return false;
}
}
return true;
},
};
Statistics.generateGraph();

Resources