Make this python code working with python 3

   2290   12   3
User Avatar
Member
255 posts
Joined: Sept. 2012
Offline
Hi guys
Might i ask you what might cause this python 2.7 code not to work with v3 please? How to fix it?
Looking forward to hear what you python's guru has to suggest, thanks!

v*
---------------------------------




import numpy as np

node = hou.pwd()
geo = node.geometry()

ptsString = geo.pointFloatAttribValuesAsString("P") # get pts data efficiently
ptsArray = np.frombuffer(ptsString, dtype=np.float32) # convert to np array
ptsArray = ptsArray.reshape(len(ptsArray)/3 ,3) # reshape as array of vectors

mean = np.mean(ptsArray, axis=0) # compute mean of pts positions
ptsArray = ptsArray - mean # transform pts to the center
mtx = np.cov(ptsArray.T) # compute covariation mtx

eigenvalues, eigenvectors = np.linalg.eig(mtx) # compute eigens

# sort eigenvalues
sort = eigenvalues.argsort()
eigenvalues = eigenvalues
eigenvectors = eigenvectors

e1 = eigenvectors
e2 = eigenvectors
e3 = eigenvectors

# compute bbox dimesions
orient = np.array( (e1, e2, e3) ).T

ee1 = np.dot((1,0,0), orient)
ee2 = np.dot((0,1,0), orient)
ee3 = np.dot((0,0,1), orient)

scale1 = np.dot(ptsArray, ee1)
scale2 = np.dot(ptsArray, ee2)
scale3 = np.dot(ptsArray, ee3)

scale1 = ( np.amax(scale1) - np.amin(scale1) ) / 2
scale2 = ( np.amax(scale2) - np.amin(scale2) ) / 2
scale3 = ( np.amax(scale3) - np.amin(scale3) ) / 2

scale = (scale1, scale2, scale3)

# output to attribs
geo.addAttrib(hou.attribType.Global, "eigenvector1", (0.,0.,0.))
geo.addAttrib(hou.attribType.Global, "eigenvector2", (0.,0.,0.))
geo.addAttrib(hou.attribType.Global, "eigenvector3", (0.,0.,0.))
geo.addAttrib(hou.attribType.Global, "scale", (0.,0.,0.))
geo.addAttrib(hou.attribType.Global, "mean", (0.,0.,0.))

geo.setGlobalAttribValue("eigenvector1", e1)
geo.setGlobalAttribValue("eigenvector2", e2)
geo.setGlobalAttribValue("eigenvector3", e3)
geo.setGlobalAttribValue("scale", scale)
geo.setGlobalAttribValue("mean", (float(mean), float(mean), float(mean)))
Vincent Thomas   (VFX and Art since 1998)
Senior Env and Lighting  artist & Houdini generalist & Creative Concepts
http://fr.linkedin.com/in/vincentthomas [fr.linkedin.com]
User Avatar
Member
8556 posts
Joined: July 2007
Offline
in Python3 this line
ptsArray = ptsArray.reshape(len(ptsArray)/3 ,3) # reshape as array of vectors
should look like this
ptsArray = ptsArray.reshape(len(ptsArray)//3 ,3) # reshape as array of vectors
to enforce integer division which in Python2 was happening automatically

also if you are using this code to compute oriented BBox of the geo or transform matrix from it, then you may consider using Extract Transform SOP instead

PS: try to embedd any code in code blocks, otherwise you will lose all formatting and []symbols
Edited by tamte - Sept. 18, 2021 13:22:13
Tomas Slancik
FX Supervisor
Method Studios, NY
User Avatar
Member
255 posts
Joined: Sept. 2012
Offline
Thanks you so much Tomas. Yes, you guess right, it's to compute an bounding box more correctly oriented than the one compute by the default Houdini sop node . See below

Im interested by your suggestion actually, Do you mind to tell me a few more detail how to use this node to output an oriented bounding box please?

Thanks you!

Attachments:
bound_orientationcompare.gif (9.0 MB)

Vincent Thomas   (VFX and Art since 1998)
Senior Env and Lighting  artist & Houdini generalist & Creative Concepts
http://fr.linkedin.com/in/vincentthomas [fr.linkedin.com]
User Avatar
Member
255 posts
Joined: Sept. 2012
Offline
Ahh, some issues still remains, i put the full code in the python clock code in case you might have one idea , should be more easy to track .... Any idea guys? Tomas?




import numpy as np

node = hou.pwd()
geo = node.geometry()

ptsString = geo.pointFloatAttribValuesAsString("P") # get pts data efficiently
ptsArray = np.frombuffer(ptsString, dtype=np.float32) # convert to np array
ptsArray = ptsArray.reshape(len(ptsArray)//3 ,3) # reshape as array of vectors

mean = np.mean(ptsArray, axis=0) # compute mean of pts positions
ptsArray = ptsArray - mean # transform pts to the center
mtx = np.cov(ptsArray.T) # compute covariation mtx

eigenvalues, eigenvectors = np.linalg.eig(mtx) # compute eigens

# sort eigenvalues
sort = eigenvalues.argsort()[::-1]
eigenvalues = eigenvalues[sort]
eigenvectors = eigenvectors[:,sort]

e1 = eigenvectors[0]
    e2 = eigenvectors[1]
e3 = eigenvectors[2]

# compute bbox dimesions
orient = np.array( (e1, e2, e3) ).T

ee1 = np.dot((1,0,0), orient)
ee2 = np.dot((0,1,0), orient)
ee3 = np.dot((0,0,1), orient)

scale1 = np.dot(ptsArray, ee1)
scale2 = np.dot(ptsArray, ee2)
scale3 = np.dot(ptsArray, ee3)

scale1 = ( np.amax(scale1) - np.amin(scale1) ) / 2
scale2 = ( np.amax(scale2) - np.amin(scale2) ) / 2
scale3 = ( np.amax(scale3) - np.amin(scale3) ) / 2

scale = (scale1, scale2, scale3)

# output to attribs
geo.addAttrib(hou.attribType.Global, "eigenvector1", (0.,0.,0.))
geo.addAttrib(hou.attribType.Global, "eigenvector2", (0.,0.,0.))
geo.addAttrib(hou.attribType.Global, "eigenvector3", (0.,0.,0.))
geo.addAttrib(hou.attribType.Global, "scale", (0.,0.,0.))
geo.addAttrib(hou.attribType.Global, "mean", (0.,0.,0.))

geo.setGlobalAttribValue("eigenvector1", e1)
geo.setGlobalAttribValue("eigenvector2", e2)
geo.setGlobalAttribValue("eigenvector3", e3)
geo.setGlobalAttribValue("scale", scale)
geo.setGlobalAttribValue("mean", (float(mean[0]), float(mean[1]), float(mean[2])))
Vincent Thomas   (VFX and Art since 1998)
Senior Env and Lighting  artist & Houdini generalist & Creative Concepts
http://fr.linkedin.com/in/vincentthomas [fr.linkedin.com]
User Avatar
Member
8556 posts
Joined: July 2007
Offline
vinyvince
Im interested by your suggestion actually, Do you mind to tell me a few more detail how to use this node to output an oriented bounding box please?
it really depends on what you are doing as it doesnt compute best fitted oriented bounding box, which would be also unstable per frame
but it will compute rigid transform difference between 2 geos withthe same topo so you can use that to update either bbox from rest or initial best fitted oriented bbox

here is and example:
- red - oriented bbox recomputed every frame using Bounds SOP - unstable as it soely depends on input geo per frame
- green - oriented bbox computed only on 1 ref frame and then updated its transform based on geo difference
- blue - axis aligned bbox computed from the geo at rest, so precise user controlled stable box alignment and then transform updated every frame based on geo difference
Edited by tamte - Sept. 19, 2021 17:14:02

Attachments:
ts_stable_oriented_bbox.hip (356.7 KB)
ts_stable_oriented_bbox.gif (1.2 MB)

Tomas Slancik
FX Supervisor
Method Studios, NY
User Avatar
Member
8556 posts
Joined: July 2007
Offline
vinyvince
Ahh, some issues still remains, i put the full code in the python clock code in case you might have one idea , should be more easy to track .... Any idea guys? Tomas?
seems to work for me as far as Python3 syntax and that it doesnt error out, except for line
    e2 = eigenvectors[1]
being wrongly indented

however I can't speak to actual values it outputs
Tomas Slancik
FX Supervisor
Method Studios, NY
User Avatar
Member
475 posts
Joined: July 2005
Offline
If you want to use the covariance matrix, here is a modification of an older file combined with some of your code.

Attachments:
cov_eigen_orient.hipnc (257.7 KB)

User Avatar
Member
255 posts
Joined: Sept. 2012
Offline
Both are brillant answer, thanks you guys, you both deserve a medal for all the constant contribution
Tomas, . I learned new things thanks. Actually my main target at this moment, is trying to creat the most accurate oriented bounding box for piece with arbitrary possibly intriguate shapes, which mean i ignore the rest position.

Many thanks to both of you guys!

vincent
Vincent Thomas   (VFX and Art since 1998)
Senior Env and Lighting  artist & Houdini generalist & Creative Concepts
http://fr.linkedin.com/in/vincentthomas [fr.linkedin.com]
User Avatar
Member
255 posts
Joined: Sept. 2012
Offline
Hello everyone

Strange, it was working fine in build 8.5 696, and now i got Python errors once again


"Error
Python error: Traceback (most recent call last):
File "<stdin>", line 43, in <module>
AttributeError: 'map' object has no attribute 'sort'" on the first python node of the above hip file...

Is it my station or is it working for you?
Vincent Thomas   (VFX and Art since 1998)
Senior Env and Lighting  artist & Houdini generalist & Creative Concepts
http://fr.linkedin.com/in/vincentthomas [fr.linkedin.com]
User Avatar
Member
475 posts
Joined: July 2005
Offline
you have to cast list on map now. list(map(...)) should work.
Edited by Aizatulin - Dec. 11, 2021 02:45:08

Attachments:
cov_eigen_orient_listmap.hipnc (267.2 KB)

User Avatar
Member
255 posts
Joined: Sept. 2012
Offline
You did my day man, thanks you you so much Aizatulin! big hug and a virtual (sanitized) beer for you


Im curious why this change. Oh people has to modify their own python tool for every 3 release, will not be hard to follow ?
Vincent Thomas   (VFX and Art since 1998)
Senior Env and Lighting  artist & Houdini generalist & Creative Concepts
http://fr.linkedin.com/in/vincentthomas [fr.linkedin.com]
User Avatar
Member
475 posts
Joined: July 2005
Offline
In some situations it can be an advantage, to have a more generalized map function. But for old scripts it can be a nightmare as well.
User Avatar
Member
255 posts
Joined: Sept. 2012
Offline
Yes, i also just notice i have to update some snipest in COP for my substance houdini edge wear .

Hopefully it will not happen not too often!
thanks again
Vincent Thomas   (VFX and Art since 1998)
Senior Env and Lighting  artist & Houdini generalist & Creative Concepts
http://fr.linkedin.com/in/vincentthomas [fr.linkedin.com]
  • Quick Links