On 13/05/2014 at 06:31, xxxxxxxx wrote:
finally....
to sort a list with tuples of mixed values, including float values, this is a solution:
import c4d
from c4d import utils
def SortFloatUniq(inList) :
outList= []
counter= 0
while counter< len(inList) :
if c4d.utils.CompareFloatTolerant(inList[counter][0][2], inList[counter-1][0][2])== False:
outList.append(inList[counter])
counter+= 1
outList= sorted(outList,key= lambda x: x[0][2])
return outList
def main() :
Listtest= [(c4d.Vector(1.0,1.0,8.0),False),(c4d.Vector(1.0,1.0,5.0),False),(c4d.Vector(1.0,1.0,5.0),False),(c4d.Vector(1.0,1.0,6.0),False),(c4d.Vector(1.0,1.0,1.0),False)]
Listtest= SortFloatUniq(Listtest)
print Listtest
if __name__=='__main__':
main()
Using the ray collider to get unique collision points on a surface and preserve the right face/backface order of collisions,
you have to limit the precision of the collider like this: (code line 48)
import c4d
def main() :
#Make sure there is an active object
if op==None: return None
#add an undo sequence
doc.StartUndo()
doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
HitList=[]
PosList=[]
matr=op.GetMg()
#initialize the collider
collider = c4d.utils.GeRayCollider()
collider.Init(op,True)
#set the origin, direction and expansion of the ray that the whole bounding box is hit by the ray
#be aware that the ray collider works in local space so reset your axis to bouningbox center
boundingbox = op.GetRad()*2
rayZposition=op.GetMp().z-boundingbox.z/2-0.1
rayXposition=0
rayYposition=400
rayposition=c4d.Vector(rayXposition,rayYposition,rayZposition)
rayzdirection=c4d.Vector(0,0,1)
raylength=boundingbox.z+0.2
#start the ray
precision = 6
inter = collider.Intersect(rayposition,rayzdirection,raylength)
if inter ==True:
count= collider.GetIntersectionCount()
collision=0
#loop through all collisions
while collision<count:
hitposition = collider.GetIntersection(collision)["hitpos"]
print hitposition
#limit the accuracy of zpositions in the HitList with a precision value because of the rounding errors with real type calculation
#store the rounded zposition to compare in the HitList
#but preserve the real collisionposition and store it in the PosList
if round(hitposition.z,precision) not in HitList:
backface = collider.GetIntersection(collision)["backface"]
PosList.append([hitposition,backface])
HitList.append(round(hitposition.z,precision))
collision+=1
#sort the PosList in Zdirection
PosList=sorted(PosList,key=lambda x: x[0][2])
print PosList
#place cubes on every unique collision position
for i,position in enumerate(PosList) :
cube = c4d.BaseObject(c4d.Ocube)
cube.SetAbsScale(c4d.Vector(0.1,0.1,0.1))
cube.SetAbsPos(position[0]*matr)
cube.SetName(str(i)+"___"+str(position[1]))
doc.InsertObject(cube)
doc.AddUndo(c4d.UNDOTYPE_NEW, cube)
c4d.EventAdd()
doc.EndUndo()
if __name__=='__main__':
main()
Cheers,
Martin