Hi Alan,
Very nice Math equation!
And the python function is very neat.
Great job


Regards,
Chris Chia
QA Analyst / ICE, FaceRobot and General Specialist,
Autodesk Media and Entertainment


From: softimage-boun...@listproc.autodesk.com 
[mailto:softimage-boun...@listproc.autodesk.com] On Behalf Of Bradley Gabe
Sent: Thursday, May 03, 2012 2:22 AM
To: softimage@listproc.autodesk.com
Subject: Re: Scripting: Closest Point On a Point Cloud?

Thanks Alan! You have officially leveled up and gained the title of SI Python 
Optimizer (Spo).

I knew the math, but for some reason assumed that compiled Math functions would 
run faster than Python. That'll teach me. [cid:image001.gif@01CD2946.7C108780]  
Actually, thinking about it now, anything that has to repeated call the COM 
layer would end up being slow-ish.

Nifty trick there using a key sort in lieu of comparing values to figure out 
the min.

FYI, it might be even faster for multi-Pos queries to provide an optional 3rd 
argument allowing the user to input the PosArray if they have already generated 
it:


def FindClosestPoint( inObj, inPos, pos=None ):

    fX, fY, fZ = inPos.Get2()

    if not pos:

        pts = inObj.ActivePrimitive.Geometry.Points

        pos = pts.PositionArray







    d = dict( [ (i, (fX-pos[0][i])**2 + (fY-pos[1][i])**2 + (fZ-pos[2][i])**2 ) 
for i in xrange(pts.Count) ] )

    closestIndices = sorted(d, key=d.get)



    # distance = d[closestIndices[0]]**0.5

    return closestIndices[0]

On Wed, May 2, 2012 at 2:00 PM, Alan Fregtman 
<alan.fregt...@gmail.com<mailto:alan.fregt...@gmail.com>> wrote:
Hey Brad,

I wondered if using math directly would be faster than working with XSIMath 
objects, so I tried. You probably knew this, but to get a distance between two 
3D vectors the formula is quite easy:

d = √  (Ax-Bx)2 + (Ay-By)2 + (Az-Bz)2
where A and B are two vectors to measure from.

However, you can skip the squareroot if you're only comparing relative 
distances. Squareroots can be computationally expensive.


Knowing this, I wrote a version which appears to run about 77% faster, and it's 
shorter too! (It takes 4.5s testing a null near a 1000x1000 pointcloud grid, vs 
your code taking about 20.3s on the same task.)


def FindClosestPoint( inObj, inPos ):

    fX, fY, fZ = inPos.Get2()

    pts = inObj.ActivePrimitive.Geometry.Points

    pos = pts.PositionArray



    d = dict( [ (i, (fX-pos[0][i])**2 + (fY-pos[1][i])**2 + (fZ-pos[2][i])**2 ) 
for i in xrange(pts.Count) ] )

    closestIndices = sorted(d, key=d.get)



    # distance = d[closestIndices[0]]**0.5

    return closestIndices[0]


I love me a Python optimization challenge. :)
Cheers,

   -- Alan


ps: Friendly nod to Xavier for pointing out "**" syntax does "to the power of" 
so I don't need to use math.pow() in my code.

On Tue, May 1, 2012 at 5:55 PM, Bradley Gabe 
<witha...@gmail.com<mailto:witha...@gmail.com>> wrote:
Sure, have at it:

def FindClosestPoint( inObj, inPos):
dist = 10000
ID = -1
Pos = XSIMath.CreateVector3()
PosArr = inObj.ActivePrimitive.Geometry.Points.PositionArray
for index in range(inObj.ActivePrimitive.Geometry.Points.Count):
Pos.Set(
PosArr[0][index],
PosArr[1][index],
PosArr[2][index]
)
Pos.SubInPlace(inPos)
D = Pos.Length()
if D < dist:
dist = D
ID = index
return ID




On Tue, May 1, 2012 at 5:52 PM, Alan Fregtman 
<alan.fregt...@gmail.com<mailto:alan.fregt...@gmail.com>> wrote:
Care to share a sample snippet? Maybe there are even faster ways to approach it.

On Tue, May 1, 2012 at 5:42 PM, Bradley Gabe 
<witha...@gmail.com<mailto:witha...@gmail.com>> wrote:
UPDATE:

All things considered, it's not too horrible simply looping through every 
position from the Geometry.Points.PositionArray, and comparing the distance in 
order to find the closest point in the cloud. So far, that technique is faster 
than anything else I've attempted to cook up.

-Bradley

On Tue, May 1, 2012 at 3:01 PM, Bradley Gabe 
<witha...@gmail.com<mailto:witha...@gmail.com>> wrote:
Nah, it was raising errors when I tried it before starting this thread, and it 
still is now [cid:image002.gif@01CD2946.7C108780] :

# ERROR : 2028 - Traceback (most recent call last):
#   File "<Script Block >", line 2, in <module>
#     obj.ActivePrimitive.Geometry.GetClosestLocations([0, 0, 0])
#   File "<COMObject <unknown>>", line 2, in GetClosestLocations
# COM Error: Invalid argument specified. - [line 2]


On Tue, May 1, 2012 at 2:58 PM, Bradley Gabe 
<witha...@gmail.com<mailto:witha...@gmail.com>> wrote:
I was going by the following quote from the docs:

Note: Point locators are currently only supported by NurbsSurfaceMesh and 
PolygonMesh objects.

But I'll still give it a shot...

On Tue, May 1, 2012 at 2:54 PM, Stephen Blair 
<stephen.bl...@autodesk.com<mailto:stephen.bl...@autodesk.com>> wrote:
But doesn't a PointCloudGeometry support GetClosestLocations? Can you use that 
(I didn't try it yet) ?







<<attachment: winmail.dat>>

Reply via email to