Diagramme de Voronoï: PythonScript
août 19, 2015 0

PythonScript pour génerer un diagramme de Voronoï (sans Grasshopper)

Fonctionnalité incontournable de Grasshopper, le diagramme de Voronoï permet à partir d’un nuage de points de délimiter la région définissant l’espace plus proche du point générateur (germe) que de n’importe quel autre.
Cette fonctionnalité n’est pas à ma connaissance disponible dans Rhinocéros 3D. Sa construction laborieuse se prête donc particulièrement bien au script.

Voici donc un script généré dans PythonScript employant la méthode d’intersection des bissectrices reliant chaque “germe” à tous les autres.

Le script prend pour données des points à sélectionner. Ceux-ci doivent s’inscrire dans un plan (coplanaire) mais pas nécessairement le planC.

Pour exécuter le script sélectionner (Outil – > PythonScript -> Modifier) puis ajouter le code ci-dessous dans un nouvel onglet.
Pour l’exécuter sélectionner l’icône :

screen
Un diagramme de Voronoï est généré à partir des points sélectionnées. Plus précisément, une polyligne définit la cellule correspondant à chaque germe.
Voronoï rhinocéros3d

Ce diagramme peut servir de base à de nombreuses formes. Ici, un tuyau (fonction T-Splines) est créé à partir des polylignes fermés. Le réseau de tube est ensuite transposé sur un cylindre (GlisserSurSurface) puis déformé à l’aide d’une modification de cage.
Voronoï Rhino3D Script

Attention toutefois, comme s’en amusent les développeurs de Grasshoppeur, l’emploi excessif de Voronoï nuit sérieusement à la créativité !
Voronoi overdose

import rhinoscriptsyntax as rs

maxm = 0
points = rs.GetPointCoordinates(message = "selectionner points")
rs.EnableRedraw(False)
points = rs.AddPoints(points)

#facteur d'echelle de la boîte de contour
scaler = 1.2

theplane = rs.PlaneFitFromPoints(points)
rs.ViewCPlane(None, theplane)

#Verifier si les points sont coplanaires
if not rs.PointsAreCoplanar(points):
print "Erreur: Les points ne sont pas coplanaires"
exit()

# Obtenir la normal au plan pour définir axe de rotation
norm = theplane.Normal

def bbox(lespts, planeman):
global maxm
plane = rs.ViewCPlane()
rs.ViewCPlane(None, plane)
bboxlines = []
box = rs.BoundingBox(lespts, planeman)

for k in range(4):
bboxlines.append(rs.AddLine(box[k], box[k+1]))
#rs.AddTextDot( k, box[k] )
maxm += rs.CurveLength(bboxlines[k])
#rs.DeleteObjects(bboxlines)
center = rs.VectorAdd(box[0], box[2])
center = rs.VectorScale(center,0.5)
rs.ScaleObjects(bboxlines, center, [scaler, scaler, scaler])
maxm *= scaler
return bboxlines

#pour chaque point générateur...
for i, points in enumerate(points):
#liste des lignes délimitant la région de chaque cellule
bdrylst = []
#ajouter un pt d'annotation a chaque point générateur
#rs.AddTextDot( i, points )
#ajouter les lignes de la boîte de contour aux courbes définissant la région de cellule
bboxlines2 = bbox(points, theplane)
for u in range(4):
bdrylst.append(bboxlines2[u])
for j, point fin in enumerate(points):
#sauter la création de lignes ou pt de départ et arrive sont confondues
if rs.Distance(points, point fin) < 0.01:
continue
oneline = rs.AddLine(points, point fin)
#ajouter une segment de chaque point "i" vers chaque point "j"
rs.DeleteObject(oneline)
#déterminer le milieu du segment pour établir la bissectrice
vec = rs.VectorSubtract(point fin, points)
vec = rs.VectorScale(vec, 0.5)
midpt = rs.AddPoint(rs.PointAdd(points, vec))
#creer les 2 points de la bissectrice par rotation autour du milieu du segment
rot1 = rs.VectorRotate(vec,90,norm)
rot2 = rs.VectorRotate(vec,-90,norm)
bdry = rs.AddLine(rs.PointAdd(midpt, rot1),rs.PointAdd(midpt, rot2))
#mise a l'échelle du segment pour assurer l'intersection des bissectrices
scalef = maxm / rs.CurveLength(bdry)
rs.ScaleObject(bdry, midpt, [scalef,scalef,scalef])
#ajouter segments a la liste des lignes définissant la région
#bdrycopy = bdry[:]
bdrylst.append(bdry)
rs.DeleteObjects(midpt)
#rs.DeleteObject(bdry)
#Sélectionner les courbes de région
rs.SelectObjects(bdrylst)
#Obtenir les coordonnées du point générateur dans le plan C
pointstC = rs.PointCoordinates(points)
pointstC = rs.XformWorldToCPlane(points C,theplane)
#Employer la commande CurveBoolean afin d'obtenir la région Voronoi du point générateur
rs.Command("_CurveBoolean _DeleteInput _All " + str(pointstC) + " " + "_Enter " )
rs.UnselectAllObjects()
rs.DeleteObjects(bdrylst)
rs.DeleteObjects(points)
rs.EnableRedraw(True)

Laisser un commentaire

Restez informé(e)