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>>