Script permettant de faire « tomber » des objets sur une face, c'est à dire les placer automatiquement au point d'intersection avec la surface, comme s'ils étaient physiquement posés dessus. L'intersection se calcule verticalement (vecteur Z) mais on peut choisir d'utiliser le z d'un plan de construction. On a également la possibilité d'ajouter une marge supplémentaire (offset) à la chute pour masquer certaines parties de l'objet (racines d'un arbre par exemple).
import rhinoscriptsyntax as rs
objectIds = rs.GetObjects("Select objects")
projectionSrfId = rs.GetObject("Select surface or polysurface to project to", rs.filter.polysurface | rs.filter.surface)
planes = []
planes.append("WorldXY") # add World XY
cplanes = rs.NamedCPlanes() # add named CPlanes
if cplanes:
    for cplane in cplanes:
        planes.append(cplane)
projectionPlane = rs.GetString("Plane to use for direction of projection (World or named CPlanes)", "WorldXY", planes)
offset = rs.GetReal("z Offset", 0)
if projectionSrfId:
    if objectIds:
        for objectId in objectIds:
            box = rs.BoundingBox(objectId,rs.NamedCPlane(projectionPlane), True) #if CPlane name is not found, falls back on WorldXY
            if box:
                bottomRightPt = [0,0,0]
                topLeftPt = [0,0,0]
                bottomLeftPt = [0,0,0]
                for i, point in enumerate(box):
                    if i==1:
                        bottomRightPt = point
                    if i==7:
                        topLeftPt = point
                    if i==3:
                        bottomLeftPt = point
                diagonal = rs.AddLine(topLeftPt, bottomRightPt)
                centroidPt = rs.CurveMidPoint(diagonal)
                rs.DeleteObject(diagonal)
                zVector = rs.VectorCreate(bottomLeftPt, topLeftPt)
                zVector = rs.VectorDivide(zVector, 2)
                zVectorU = rs.VectorUnitize(zVector)
                offsetVector = rs.VectorScale(zVectorU,-offset)
                bottomCentroidPt = [centroidPt[0] + zVector[0], centroidPt[1] + zVector[1], centroidPt[2] + zVector[2]]
                projectedPts = rs.ProjectPointToSurface(bottomCentroidPt, projectionSrfId, zVector)
                if projectedPts:
                    nearestProjectedPtId = rs.PointArrayClosestPoint(projectedPts, bottomCentroidPt)
                    destinationPt = projectedPts[nearestProjectedPtId]
                    rs.AddPoint(destinationPt)
                    projectVector = rs.VectorCreate(destinationPt,bottomCentroidPt)
                    if offset != 0:
                        projectVector = rs.VectorAdd(projectVector,offsetVector)
                    rs.MoveObject(objectId, projectVector)
                else:
                    print "Object cannot be projected on surface."
            else:
                print "Bounding-boxes couldn't be created."
    else:
        print "No object selected."
else:
    print "No surface selected."