marcomusy / vedo

A python module for scientific analysis of 3D data based on VTK and Numpy
https://vedo.embl.es
MIT License
2.05k stars 266 forks source link

How to color vedo.mag("DISPLACEMENTS") for a TetMesh or Ugrid #325

Closed SADPR closed 3 years ago

SADPR commented 3 years ago

First of all, I would like to thank you for sharing this amazing code as a open source, I have been using it for a project and so far I have only face the following doubt:

I have a TetMesh or Ugrid with the following Points array: displacements = tetmesh.getPointArray()... array([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.], ..., [0., 0., 0.], [0., 0., 0.], [0., 0., 0.]], dtype=float32) Which represents DISPLACEMENT_X, DISPLACEMENT_Y, DISPLACEMENT_Z.

What I would like to do is to show() for the values of my vedo.mag(displacements).

If this were transformed to a polygonal Mesh mesh = (tetmesh.tomesh(fill=True, shrink=1)), I can ask for it in the following way:

Nevertheless, I would like to keep my tetmesh, and when If I ask tetmesh.show(axes=1, viewup = 'z'), it does not know what to color. Is there a way that I can say to my tetmesh to color for the values of the vedo.mag(displacements)?

marcomusy commented 3 years ago

Thanks Sebastian, try out this:

from vedo import *
import numpy as np

tetm = TetMesh(datadir+'limb_ugrid.vtk')

disp = np.random.rand(tetm.NPoints(), 3) # fake displacements
tetm.addPointArray(disp, "displacements")
print('disp.shape', disp.shape)

# Make a copy of tetm and send it to a polygonal mesh
cmesh = tetm.clone().tomesh(fill=True, shrink=0.5)

disp = cmesh.getPointArray("displacements")
print('disp.shape', disp.shape) # changed because of shrink

cmesh.cmap('jet', mag(disp))

arrows = Arrows(cmesh.points(), cmesh.points()+disp*10, c='k').lighting('off')

show(cmesh, arrows, axes=1)

Screenshot from 2021-03-01 16-08-29

let me know if suits your needs.

SADPR commented 3 years ago

Thank you very much for your response. This will help me with another case I am working in. Nevertheless, what I am doing now is running a Reduced Order Model of which I need to read a TetMesh every time the boundary condition is updated via the scalar bar from vedo. We are trying to run this model in a low RAM computer, therefore, transforming the mesh (tomesh()) may produce a little bit more computational cost.

Therefore, what I wanted to know is if there's a way to indicate directly something like this: tetmesh.show(vedo.mag(displacements)) or tetmesh.pointColors(vedo.mag(displacements)....)

The function pointColors used to work for TetMesh on the version vtkplotter==2020.0.1: tetmesh.pointColors(vtkplotter.mag(displs), cmap='jet').addScalarBar(vmin = 0, vmax = 0.009) tetmesh.show(axes=1, viewup='z')

Please let me know if I made myself clear, this can be a little bit confusing. I really thank you for your time and help. I take advantage of this space to congratulate you on this great work.

marcomusy commented 3 years ago

You're welcome! vtkplotter has been retired since quite a while, If possible I would suggest to upgrade to the latest vedo.

The pointColors() is still available but recently substituted by cmap() method. Note that your tetmesh.pointColors(vedo.mag(displacements)....) is exactly equivalent to the newer cmesh.cmap('jet', mag(disp)).

there's a way to indicate directly something like this: tetmesh.show(vedo.mag(displacements))

No... because show refers already to the list of stuff ready to be rendered.

boundary condition is updated via the scalar bar

You mean slider ?

If so, maybe something like this would work for you:

solution1

from vedo import *
import numpy as np

tetm = TetMesh(datadir+'limb_ugrid.vtk', c=['r','g','lb','b']) # or c='jet'

disps = np.random.rand(tetm.NPoints(), 3)-0.5 # fake displacements
tetm.addPointArray(mag(disps), "displacements")

def slid(w,e):
    value = w.GetRepresentation().GetValue()
    np.random.seed(int(value))

    disps = np.random.rand(tetm.NPoints(), 3)-0.5 # new displacements
    tetm.addPointArray(mag(disps), "displacements")
    plt.render()

plt = Plotter(axes=1)
plt.addSlider2D(slid, 0, 100)
plt.show(tetm)

will visualize using a volumetric mapper: Screenshot from 2021-03-01 17-19-42

solution 2

from vedo import *
import numpy as np

tetm = TetMesh(datadir+'limb_ugrid.vtk', c=['r','g','lb','b']) # or c='jet'

disps = np.random.rand(tetm.NPoints(), 3)-0.5 # fake displacements
tetm.addPointArray(mag(disps), "displacements")

def slid(w,e):
    global mesh
    value = w.GetRepresentation().GetValue()
    np.random.seed(int(value))
    disps = np.random.rand(tetm.NPoints(), 3)-0.5 # fake displacements
    tetm.addPointArray(mag(disps), "displacements")

    plt.remove(mesh, render=False)
    mesh = tetm.tomesh(fill=0).selectPointArray("displacements")
    plt.add(mesh)

plt = Plotter()
mesh = tetm.tomesh(fill=0).selectPointArray("displacements")
plt.addSlider2D(slid, 0, 100)
plt.show(mesh, axes=1)

Screenshot from 2021-03-01 17-20-09

SADPR commented 3 years ago

Thanks very much, this helped me.