marcomusy / vedo

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

mesh modify doesnt change mesh pos() also GetPosition() not working #996

Closed smoothumut closed 6 months ago

smoothumut commented 6 months ago

Hi Marco, With the new update I have also realized 2 things that I couldnt make work

1 - I used to call GetPosition() from a vedo.Mesh object and it used to give me a robust position. but now vedo.Mesh doesnt have that attribute. But also mesh.actor.GetPosition() always returns [0,0,0]

2 - I change the vertices/points of a mesh in one of my cases. when I change the points, and ask for the position the pos() attribute returns [0,0,0] even though it shows the mesh in right position of the plotter . it reset it.

  """Modify mesh vertex positions"""
  from vedo import *

  disc = Disc(res=(8,120)).linewidth(0.1)

  plt = Plotter(interactive=False, axes=1)
  plt.show(disc, Point(), __doc__)

  disc.shift(1,1,1)
  print("disc_pos",disc.pos())
  for i in range(100):
      # Modify vertex positions
      disc.vertices += [0.01, 0.01*sin(i/20), 0]
      plt.reset_camera().render()

  print("disc_pos2",disc.pos())
  plt.interactive().close()

Thanks in advance Regards

marcomusy commented 6 months ago

OK, this time i think it's not a bug but in fact an intended behavior :) If you directly modify the vertex coordinates manually there no more an homogeneous transform that describes the new position nor orientation of the object, therefore the self.transform object is reset. In this example

from vedo import Disc, Point, Plotter

disc = Disc(res=(8,120)).linewidth(0.1)
disc.rotate_x(20).shift(1,2,0)

plt = Plotter(interactive=False, axes=1)
plt.show(disc, Point())

# current linear transformation:
print(disc.transform)
print("disc_pos1", disc.pos())

plt.interactive()
for i in range(100):
    disc.vertices += [0.01, 0.0, 0]
    plt.reset_camera().render()
print("disc_pos2", disc.pos())

plt.interactive().close()

Screenshot from 2023-12-21 17-35-18

you can still copy-clone the LinearTransform if you want to keep track of it:

T = disc.transform.clone()

and can apply it to any other object:

my_other_obj.apply_transform(T)

Let me know if this makes sense to you.

smoothumut commented 6 months ago

Hi Marco, thank you very much for your reply and help I still couldnt make it : )
I have troubles with some basics and I am still learning so please bear with me :)

In the code below, when I apply the transformation, it moves the disc and apply the previous shifts and rotates to the object again. So the objects position goes where it shouldnt supposed to go. The code below changes the disc's position but in my real scenario I just change the shape of the object. its orientation and position stays same. And I need its position and orientation.

But after changing the points. The transform is being reset and I cannot get its current position. when I try to set them back, its position changes but position prints where it supposed to be.

  disc = Disc(res=(8,120)).linewidth(0.1)
  disc.rotate_x(20).shift(1,2,0)

  plt = Plotter(interactive=False, axes=1)
  plt.show(disc, Point())

  # current linear transformation:
  t = disc.transform.clone()
  print(disc.transform)
  print("disc_pos1", disc.pos())

  plt.interactive()
  for i in range(100):
      disc.vertices += [0.01, 0.0, 0]
      plt.reset_camera().render()

  print("disc_pos2", disc.pos())
  print(disc.transform)
  plt.interactive()
  disc.apply_transform(t)
  plt.render()
  plt.interactive().close()
My First question,

After changing its shape, How can I get its current position and orientation in new update? ( or maybe its new position) It's position looks [0,0,0] and if I set position, it moves the object from its current position ..... print("disc_pos2", disc.pos()) print(disc.transform) plt.interactive() disc.actor.SetPosition(1,2,0) print("getposition",disc.actor.GetPosition()) plt.render()

apply_transform(disc,t)

  plt.interactive().close()
My Second question;

I have realized that with the new update, Mesh object and vtkOpenGLActor relationship is changed. please please correct me If I am wrong.

vedo Mesh object used to be a vtkOpenGLActor I used to get the positions from mesh.GetPosition() or get the matrix using mesh.GetMatrix() Now I see that the vtkOpenGLActor becomes mesh.actor but I have noticed that mesh.actor.GetPosition() always gives the [0,0,0] even though I use shifts and mesh.actor.GetMatrix() always gives identity matrix even though I use rotations unless I change the position by mesh.actor.SetPosition() or rotate mesh.actor using vtk's rotations and orientations methods. the previous "shift"s in vedo was also changing the actor's Positions. previous "shift" used to use SetPosition() but current "shift"s in vedo goes with vedo's mesh's transforms not with vtk Actor.

for the new 5.0 update (which looks more robust and clean), I can change my code with renames and other changes (tens of thousands by the way :) , but my concern is not being able to connect vtk and vedo? Am I correct or I am missing something. Thanks thanks in advance Best Regards Umut

smoothumut commented 6 months ago

Hi Marco, I have solved my first question using 2023.4.7 and solve half using 2023.5.0

in 2023.4.7

  import vtk
  import vedo
  from vedo import *

  disc = Disc(res=(8,120)).linewidth(0.1)
  disc.rotate_x(20).shift(1,2,0)

  plt = Plotter(interactive=False, axes=1)
  plt.show(disc, Point())

  p = disc.GetPosition()
  o = disc.GetOrientation()
  print("p",p)
  print("o",o)

  plt.interactive()
  for i in range(100):
      disc.SetPosition(0,0,0)
      disc.SetOrientation(0,0,0)

      ps = disc.points()
      modified_points = [(x + 0.01, y, z) for x, y, z in ps]
      disc.points(modified_points)

      disc.SetPosition(p[0],p[1],p[2])
      disc.SetOrientation(o[0],o[1],o[2])
      plt.reset_camera().render()

  plt.render()
  print("disc_pos2", disc.pos())
  print(disc.transform)
  plt.interactive()
  print("getposition",disc.actor.GetPosition())
  plt.render()
  plt.interactive().close()

for 2023.5.0 I couldnt find how to reset correctly in new version

from vedo import Disc, Point, Plotter, LinearTransform, NonLinearTransform,utils,logger import vtk

disc = Disc(res=(8,120)).linewidth(0.1) disc.rotate_x(20).shift(1,2,0)

plt = Plotter(interactive=False, axes=1) plt.show(disc, Point())

p = disc.transform.position o = disc.transform.orientation print("p",p) print("o",o) print("disc_transform1",disc.transform)

plt.interactive() for i in range(100): LT = LinearTransform() LT.translate(-p[0],-p[1],-p[2])

LT.orientation() I couldnt find how to orient to 0,0,0

disc.apply_transform(LT)
disc.vertices += [0.01, 0.0, 0]
LT = LinearTransform()
LT.translate(p[0],p[1],p[2])
###LT.orientation() I couldnt find how to orient back to "o"
disc.apply_transform(LT)
plt.reset_camera().render()

print("disc_transform2",disc.transform) plt.interactive() print("getposition",disc.actor.GetPosition()) plt.render() plt.interactive().close()

this workaround worked for me. but still in new version, I couldnt find the right way to orient to 0 and orientback to "o"

marcomusy commented 6 months ago

Hi Umut please feel free to ask as many questions as you like, in fact it's useful feedback to understand what can be improved in terms of clarity of the API. I want to stress that you will always be able to connect back to pure vtk classes and methods! You can access the underlying vtk objects in eg mesh.dataset(eg vtkPolyData, vtkImageData ...), mesh.mapper (vtkMapper), and mesh.properties (vtkProperty). Also transformations: mesh.transform.T (vtkTransform). Hence mesh.transform.T.GetOrientation() will give you the current orientation. To set you can create a new LinearTransofmation and then obj.apply_transform(mytrans).

Sorry for the incomplete answer, I'm travelling now, i may be slow replying!

smoothumut commented 6 months ago

Hi Marco, That s a totally complete answer for me. I deeply appreciate for your all support and quick responses.

Now It makes more sense. I got used to using GetPosition(), GetOrientation(), GetMatrix() and using them in vtkFilters. And I used many vtk methods using your examples. They always guide me to follow pipelines and helped me understand which filters are used for what and how different filters are used for different functions.

When I make some transformations (using apply_transform) on mesh on new update, some vtkOpenGLActor's properties, like position and orientation, vtkMatrix doesnt change. they stay unchanged unless I changed them manually using vtk props. But this time it concatenate the transformations. and this time vedo matrix and vtk matrix start not the match. it is like world and local matrices. Do I understand correctly?

Does this cause troubles in long run especially using filters?

(Really sorry if this question seems too basic : )

I will try to create example code to explain it clearer

marcomusy commented 6 months ago

it is like world and local matrices. Do I understand correctly?

it's more like cpu vs gpu, which is very confusing - or at least it is to me - but it has its good reason as all what happens on the gpu is way faster. In vedo 5.0 all the actors/props will normally have GetPosition() zero, but you can keep track of their movements via object.transform. To get their position: obj.pos() Also obj.transform.matrix4x4 or obj.transform.matrix3x3 Check out here what is possible. To access the vtk class the equivalent of obj.pos() becomes np.array(obj.transform.T.GetPosition())

Does this cause troubles in long run especially using filters?

.. I believe that getting rid of this source of confusion will simplify the use of filters.

Note that you will still able to extract the transform for a dataset (eg a mesh that has been manually dragged after pressing "a") with method mymesh.apply_transform_from_actor()

That said I'm always open to criticism and if you have any counterexample I'm very happy to look at it :) Have nice holidays! M.

smoothumut commented 6 months ago

Frankly, This is a great answer for me :) Thank you sooo much. You know the everything under the hood. I am able to just look at the surface. I knew the 5.0 is more robust and clean but In my perspective I couldnt have made the bridge between them. Now your explanation definitely makes everything clear to me. And I need to work on them. Thanks for the directions

By the way, please dont think my questions as critic, First of all I dont have enough knowledge to critic : ) they are all questions to understand the structure better and apply them to solve the problems in front of me.

I belive carrying this library from 4.7 to 5.0 is a big and great shift. Vedo is getting bigger, and more professional. All these changes need great time and energy. And As I said before I cant tell how gratefull I feel for you. I am doing a big 3d project thanks to vedo. otherwise I would struggle with vtk for 5x time.

Thank you sooo much and have a great holiday :)