I'm learning a bit of plotly mixing it with HTML/JavaScript, so I'm using the plotly.js CDN
I pretend to draw a set of randomly generated dots into a X
, Y
, and Z
coordinate space, I have successfully generated all the dots but I'm facing an issues trying to show in the same drawing all three coordinates axis as a reference planes...
I have successfully been able to show the XY
plane and dots
But I'm still failing to shows the XZ
and YZ
references planes as I'm doing in here but with lines
I have even attempt to use chatGPT but it's totally lost trying to resolve the issue...
Here share the whole JS script code I'm using , hope I get someone that can help!!!!
<script>
// Array to store the generated points
const dots = [];
// Generate 100 points with random x, y, z coordinates
for (let i = 0; i < 100; i++) {
const x = Math.random() * 20 - 10;
const y = Math.random() * 20 - 10;
const z = Math.random() * 20 - 10;
dots.push({ x, y, z });
}
// Extract x, y, and z coordinates separately for the chart
const xData = dots.map(point => point.x);
const yData = dots.map(point => point.y);
const zData = dots.map(point => point.z);
// Configure the 3D chart trace
const trace = {
x: xData,
y: yData,
z: zData,
mode: 'markers',
marker: {
size: 5,
color: 'rgb(75, 192, 192)',
},
type: 'scatter3d',
};
// Plane x-y (z = 0)
const dataPlaneXY = {
x: [-10, 10, 10, -10],
y: [-10, -10, 10, 10],
z: [0, 0, 0, 0],
type: 'mesh3d',
colorscale: 'Viridis',
opacity: 0.5,
lighting: {
specular: 0.2,
ambient: 0.8,
diffuse: 0.5,
fresnel: 0.2,
},
};
// Plane x-z (y = 0)
const dataPlaneXZ = {
x: [-10, 10, 10, -10],
y: [0, 0, 0, 0],
z: [-10, -10, 10, 10],
type: 'mesh3d',
colorscale: 'Viridis',
opacity: 0.5,
lighting: {
specular: 0.2,
ambient: 0.8,
diffuse: 0.5,
fresnel: 0.2,
},
};
// Plane y-z (x = 0)
const dataPlaneYZ = {
x: [0, 0, 0, 0],
y: [-10, 10, 10, -10],
z: [-10, -10, 10, 10],
type: 'mesh3d',
colorscale: 'Viridis',
opacity: 0.5,
lighting: {
specular: 0.2,
ambient: 0.8,
diffuse: 0.5,
fresnel: 0.2,
},
};
// Data for the chart, including the lines for the reference planes
const data = [trace, dataPlaneXY, dataPlaneXZ, dataPlaneYZ];
// Configure the layout of the 3D chart
const layout = {
scene: {
xaxis: { title: 'X Coordinate', range: [-10, 10], showaxeslines: true },
yaxis: { title: 'Y Coordinate', range: [-10, 10], showaxeslines: true },
zaxis: { title: 'Z Coordinate', range: [-10, 10], showaxeslines: true },
aspectmode: 'cube', // ensures the axes have the same scale
showaxeslines: true, // Show axis lines
},
};
// Draw the 3D chart
Plotly.newPlot('coordinateChart', data, layout);
</script>
Thanks a lot for @kikon for they answer ( please read it!!! )
A mesh3d
is a set of triangles; the properties x
, y
and z
specify a set of points; one has also to specify how these points are to be grouped in triangles.
The safest and clearest way to do that is to set the properties i
, j
and k
.
If one sets:
i: [0, 1],
j: [1, 2],
k: [2, 3],
there will be two triangles: the first formed by the points 0,1,2 and the second by points 1,2,3 - coordinates taken from the x
,y
,z
arrays.
Here's a solution, based on that (note that I changed the order of two coordinates also):
const dots = [];
// Generate 100 points with random x, y, z coordinates
for (let i = 0; i < 100; i++) {
const x = Math.random() * 20 - 10;
const y = Math.random() * 20 - 10;
const z = Math.random() * 20 - 10;
dots.push({ x, y, z });
}
// Extract x, y, and z coordinates separately for the chart
const xData = dots.map(point => point.x);
const yData = dots.map(point => point.y);
const zData = dots.map(point => point.z);
// Configure the 3D chart trace
const trace = {
x: xData,
y: yData,
z: zData,
mode: 'markers',
marker: {
size: 5,
color: 'rgb(75, 192, 192)',
},
type: 'scatter3d',
};
// Plane x-y (z = 0)
const dataPlaneXY = {
x: [-10, 10, -10, 10],
y: [-10, -10, 10, 10],
z: [0, 0, 0, 0],
i: [0, 1],
j: [1, 2],
k: [2, 3],
type: 'mesh3d',
colorscale: 'Viridis',
opacity: 0.5,
lighting: {
specular: 0.2,
ambient: 0.8,
diffuse: 0.5,
fresnel: 0.2,
},
};
// Plane x-z (y = 0)
const dataPlaneXZ = {
x: [-10, 10, -10, 10],
y: [0, 0, 0, 0],
z: [-10, -10, 10, 10],
i: [0, 1],
j: [1, 2],
k: [2, 3],
type: 'mesh3d',
colorscale: 'Viridis',
opacity: 0.5,
lighting: {
specular: 0.2,
ambient: 0.8,
diffuse: 0.5,
fresnel: 0.2,
},
};
// Plane y-z (x = 0)
const dataPlaneYZ = {
x: [0, 0, 0, 0],
y: [-10, 10, -10, 10],
z: [-10, -10, 10, 10],
i: [0, 1],
j: [1, 2],
k: [2, 3],
type: 'mesh3d',
colorscale: 'Viridis',
opacity: 0.5,
lighting: {
specular: 0.2,
ambient: 0.8,
diffuse: 0.5,
fresnel: 0.2,
},
};
// Data for the chart, including the lines for the reference planes
const data = [trace, dataPlaneXY, dataPlaneXZ, dataPlaneYZ];
// Configure the layout of the 3D chart
const layout = {
scene: {
xaxis: { title: 'X Coordinate', range: [-10, 10], showaxeslines: true },
yaxis: { title: 'Y Coordinate', range: [-10, 10], showaxeslines: true },
zaxis: { title: 'Z Coordinate', range: [-10, 10], showaxeslines: true },
aspectmode: 'cube', // ensures the axes have the same scale
showaxeslines: true, // Show axis lines
},
};
// Draw the 3D chart
Plotly.newPlot('coordinateChart', data, layout);
<div id='coordinateChart' style="height:450px; width:100%"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/plotly.js/2.24.3/plotly.min.js" integrity="sha512-OB3KqMv8ZelkEhNOv1J6PB0aYRkn8oota0+LoGXIVD3hv1Pu9ebxFJXBopRlGkYLTLEUM7aX9zBepBzGcZzH5A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Now, for an alternative solution, and an explanation of why did the xy plane work without the i
, j
, k
: if they are not specified, then the Delaunay triangulation is used - see the docs on alphahull and delaunayaxis properties.
So, it turns out that at least for the 4 coplanar points that you have Delaunay triangulation works fine, but you have to set the delaunayaxis
to the axis perpendicular to their plane. And yes, the default is z
and that's why it worked with no addition for the xy plane:
const dots = [];
// Generate 100 points with random x, y, z coordinates
for (let i = 0; i < 100; i++) {
const x = Math.random() * 20 - 10;
const y = Math.random() * 20 - 10;
const z = Math.random() * 20 - 10;
dots.push({ x, y, z });
}
// Extract x, y, and z coordinates separately for the chart
const xData = dots.map(point => point.x);
const yData = dots.map(point => point.y);
const zData = dots.map(point => point.z);
// Configure the 3D chart trace
const trace = {
x: xData,
y: yData,
z: zData,
mode: 'markers',
marker: {
size: 5,
color: 'rgb(75, 192, 192)',
},
type: 'scatter3d',
};
// Plane x-y (z = 0)
const dataPlaneXY = {
x: [-10, 10, 10, -10],
y: [-10, -10, 10, 10],
z: [0, 0, 0, 0],
delaunayaxis: 'z', //default
type: 'mesh3d',
colorscale: 'Viridis',
opacity: 0.5,
lighting: {
specular: 0.2,
ambient: 0.8,
diffuse: 0.5,
fresnel: 0.2,
},
};
// Plane x-z (y = 0)
const dataPlaneXZ = {
x: [-10, 10, 10, -10],
y: [0, 0, 0, 0],
z: [-10, -10, 10, 10],
delaunayaxis: 'y',
type: 'mesh3d',
colorscale: 'Viridis',
opacity: 0.5,
lighting: {
specular: 0.2,
ambient: 0.8,
diffuse: 0.5,
fresnel: 0.2,
},
};
// Plane y-z (x = 0)
const dataPlaneYZ = {
x: [0, 0, 0, 0],
y: [-10, 10, 10, -10],
z: [-10, -10, 10, 10],
delaunayaxis: 'x',
type: 'mesh3d',
colorscale: 'Viridis',
opacity: 0.5,
lighting: {
specular: 0.2,
ambient: 0.8,
diffuse: 0.5,
fresnel: 0.2,
},
};
// Data for the chart, including the lines for the reference planes
const data = [trace, dataPlaneXY, dataPlaneXZ, dataPlaneYZ];
// Configure the layout of the 3D chart
const layout = {
scene: {
xaxis: { title: 'X Coordinate', range: [-10, 10], showaxeslines: true },
yaxis: { title: 'Y Coordinate', range: [-10, 10], showaxeslines: true },
zaxis: { title: 'Z Coordinate', range: [-10, 10], showaxeslines: true },
aspectmode: 'cube', // ensures the axes have the same scale
showaxeslines: true, // Show axis lines
},
};
// Draw the 3D chart
Plotly.newPlot('coordinateChart', data, layout);
<div id='coordinateChart' style="height:450px"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/plotly.js/2.24.3/plotly.min.js" integrity="sha512-OB3KqMv8ZelkEhNOv1J6PB0aYRkn8oota0+LoGXIVD3hv1Pu9ebxFJXBopRlGkYLTLEUM7aX9zBepBzGcZzH5A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>