Plotly: How to plot a tetrahedron volume

Question:

I have a set of xyz points and a set of tetrahedrons. Where each node of the tetrahedron points to an index in the points table.

I need to plot the tetrahedrons with a corresponding color based on the tag attribute.

points

Index x y z
0 x_1 y_1 z_1
1 x_2 y_2 z_2

tetrahedrons

Index a b c d tag
0 a_1.pt b_1.pt c_1.pt d_1.pt 9
1 a_2.pt b_2.pt c_2.pt d_2.pt 0

I have tried using the Mesh3d api but it does not allow for a 4th vertex.

I can plot something like the code below but it does not have all the faces of the tetrahedron.

go.Figure(data=[
    go.Mesh3d(
        x=mesh_pts.x, y=mesh_pts.y, z=mesh_pts.z,
        i=tagged_th.a, j=tagged_th.b, k=tagged_th.c,
    ),
]).show()

I think the Volume or Isosurface plots might work but I’m not sure how to convert my data into a format to be consumed by those apis.

Asked By: Squanchy

||

Answers:

I don’t see what you mean by "does not allow for a 4th vertex". Here is an example with two tetrahedra:

import plotly.graph_objects as go
import plotly.io as pio
import numpy as np

i = np.array([0, 0, 0, 1])
j = np.array([1, 2, 3, 2])
k = np.array([2, 3, 1, 3])

fig = go.Figure(data = [
    go.Mesh3d(
        x = [0,1,2,0, 4,5,6,4],
        y = [0,0,1,2, 0,0,1,2],
        z = [0,2,2,3, 4,2,4,1],
        i = np.concatenate((i, i+4)),
        j = np.concatenate((j, j+4)),
        k = np.concatenate((k, k+4)),
        facecolor = ["red","red","red","red", "green","green","green","green"]
    )
])

pio.write_html(fig, file = "tetrahedra.html", auto_open = True)

enter image description here

Answered By: Stéphane Laurent

I can’t hide the fact that, a few minutes ago, I wasn’t even aware of i,j,k parameters. But, still, I know that Mesh3D draws triangles, not tetrahedron. You need to take advantage of those i,j,k parameters to control which triangles are drawn. But it is still your job to tell which triangles need to be drawn to that it look like tetrahedrons.

Yes, there are 4 triangles per tetrahedron. If you wish to draw them four, you need to explicitly pass i,j,k for all 4. Not just pass i,j,k and an nonexistent l and expect plotly to understand that this means 4 triangles.

If a, b, c and d are 4 vertices of a tetrahedron, then the 4 triangles you need to draw are the 4 combinations of 3 of vertices from those. That is bcd, acd, abd and abc.

Let’s write this in 4 rows

bcd
acd
abd
abc
^^^
|||
||------k
|------ j
------- i

So, if, now, a, b, c and d are list of n vertices, then i, j, k must be lists 4 times longer

i=b + a + a + a
j=c + c + b + b
k=d + d + d + c

Application: let’s define 2 tetrahedrons, one sitting on the spike of the other, using your dataframes format

import plotly.graph_objects as go
import pandas as pd

mesh_pts = pd.DataFrame({'x':[0, 1, 0, 0, 1, 0, 0],
                         'y':[0, 0, 1, 0, 0, 1, 0],
                         'z':[0, 0, 0, 1, 1, 1, 2]})

tagged_th = pd.DataFrame({'a':[0,3],
                          'b':[1,4],
                          'c':[2,5],
                          'd':[3,6],
                          'tag':[0,1]})

# And from there, just create a list of triangles, made of 4 combinations 
# of 3 points taken from list of tetrahedron vertices
go.Figure(data=[
    go.Mesh3d(
        x=mesh_pts.x,
        y=mesh_pts.y,
        z=mesh_pts.z,
        i=pd.concat([tagged_th.a, tagged_th.a, tagged_th.a, tagged_th.b]),
        j=pd.concat([tagged_th.b, tagged_th.b, tagged_th.c, tagged_th.c]),
        k=pd.concat([tagged_th.c, tagged_th.d, tagged_th.d, tagged_th.d]),
        intensitymode='cell',
        intensity=pd.concat([tagged_th.tag, tagged_th.tag, tagged_th.tag, tagged_th.tag])
    )
]).show()

enter image description here

Answered By: chrslg
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.