Rhino python 101 - recursive tree

Ciao, ho iniziato a studiare python (fatto un corso) e mi sono lanciato con rhino.python e GhPython.
In particolare ora sto seguendo la guida di Rhino.Python 101 (il primer) che è un po’ vecchiotto e c’è qualche errore, ma comunque molto valido.

Ora, per quanto sia un principiante sono riuscito a far funzionare più o meno tutto, sia nell’editor interno di rhino che “traslandolo” su GhPython (che a voi sembrerà semplice, ma per me non lo era per niente).
Fino a questo punto (capitolo 8.6.2 del primer). Onestamente non riesco a capire cosa cambiare per correggere l’errore (ho fatto diverse prove, ma niente). Mi sembra che funzioni, ma invece di ottenere il pezzettino di arco giusto, ottengo l’arco opposto (sia in gh che nell’editor).

se qualcuno mi può dare una mano e soprattutto spiegare perchè non funziona, mi fate un grosso favore. via allego il gh per comodità e perchè così mi dite se ho tirato fuori in modo corretto le curve, o c’è un modo migliore (la parte di creazione della lista b e successivo append e return li ho aggiunti io rispetto allo script).

Python_101_RecursiveTree.gh (16,8 KB)

in pratica dovrei ottenere le parti che ho disegnato in blu (o circa)

copio qui anche lo script per comodità:

import rhinoscriptsyntax as rs
import random

def AddArcDir(ptStart, ptEnd, vecDir):
    vecBase = rs.PointSubtract(ptEnd, ptStart)
    if rs.VectorLength(vecBase) == 0.0 : return
    
    if rs.IsVectorParallelTo(vecBase, vecDir): return
    
    vecBase = rs.VectorUnitize(vecBase)
    VecDir = rs.VectorUnitize(vecDir)
    
    vecBisector = rs.VectorAdd(vecDir, vecBase)
    vecBisector = rs.VectorUnitize(vecBisector)
    
    dotProd = rs.VectorDotProduct(vecBisector, vecDir)
    midLength = (0.5*rs.Distance(ptStart, ptEnd))/dotProd
    
    vecBisector = rs.VectorScale(vecBisector, midLength)
    return rs.AddArc3Pt(ptStart, rs.PointAdd(ptStart, vecBisector), ptEnd)

def RandomPointInCone(origin, dir, minDist, maxDist, maxAng):
    vecTwig = rs.VectorUnitize(dir)
    vecTwig = rs.VectorScale(vecTwig, minDist + random.random()*(maxDist - minDist))
    MutationPlane = rs.PlaneFromNormal((0,0,0), vecTwig)
    vecTwig = rs.VectorRotate(vecTwig, random.random()*maxAng, MutationPlane[1])
    vecTwig = rs.VectorRotate(vecTwig, random.random()*360, dir)
    return rs.PointAdd(origin, vecTwig)

def RecursiveGrowth(ptStart, vecDir, props, generation):
    minTwigCount, maxTwigCount, maxGenerations, maxTwigLength, lengthMutation, maxTwigAngle, angleMutation = props    
    if generation>maxGenerations: return
    b=[]
    newProps = props
    maxTwigLength *= lengthMutation
    maxTwigAngle *= angleMutation
    if maxTwigAngle>90: maxTwigAngle=90
    
    newprops = minTwigCount, maxTwigCount, maxGenerations, maxTwigLength, lengthMutation, maxTwigAngle, angleMutation
    maxN = int(minTwigCount + random.random()*(maxTwigCount - minTwigCount))
    for n in range(1, maxN):
        ptGrow = RandomPointInCone(ptStart, vecDir, 0.25*maxTwigLength, maxTwigLength, maxTwigAngle)
        newTwig = AddArcDir(ptStart, ptGrow, vecDir)
        if newTwig:
            vecGrow = rs.CurveTangent(newTwig, rs.CurveDomain(newTwig)[1])
            RecursiveGrowth(ptGrow, vecGrow, newProps, generation+1)
            b.append(newTwig)
    return b

minTwigCount = TL_min
maxTwigCount = TL_max
maxGenerations = max_G
maxTwigLength = TL
lengthMutation = TL_m
maxTwigAngle = TA
angleMutation = TA_m
props = minTwigCount, maxTwigCount, maxGenerations, maxTwigLength, lengthMutation, maxTwigAngle, angleMutation


a = RecursiveGrowth(P, X, props, g)

Soluzione con GH.
Bisognerebbe riportare il concetto dentro lo script.
Python_101_RecursiveTree a.gh (16,3 KB)

Grazie! in effetti mi ha fatto venire in mente una soluzione (che a me è sembrata controintuitiva) ma che ha risolto il problema, almeno nel Python Editor su Rhino:

  • nella funzione AddArcDir: ho scambiato l’ordine del ptEnd con il ptAdd
import rhinoscriptsyntax as rs
import random

def AddArcDir(ptStart, ptEnd, vecDir):
    vecBase = rs.PointSubtract(ptEnd, ptStart)
    if rs.VectorLength(vecBase) == 0.0 : return
    
    if rs.IsVectorParallelTo(vecBase, vecDir): return
    
    vecBase = rs.VectorUnitize(vecBase)
    VecDir = rs.VectorUnitize(vecDir)
    
    vecBisector = rs.VectorAdd(vecDir, vecBase)
    vecBisector = rs.VectorUnitize(vecBisector)
    
    dotProd = rs.VectorDotProduct(vecBisector, vecDir)
    midLength = (0.5*rs.Distance(ptStart, ptEnd))/dotProd
    
    vecBisector = rs.VectorScale(vecBisector, midLength)
    return rs.AddArc3Pt(ptStart, ptEnd, rs.PointAdd(ptStart, vecBisector))

def RandomPointInCone(origin, dir, minDist, maxDist, maxAng):
    vecTwig = rs.VectorUnitize(dir)
    vecTwig = rs.VectorScale(vecTwig, minDist + random.random()*(maxDist - minDist))
    MutationPlane = rs.PlaneFromNormal((0,0,0), vecTwig)
    vecTwig = rs.VectorRotate(vecTwig, random.random()*maxAng, MutationPlane[1])
    vecTwig = rs.VectorRotate(vecTwig, random.random()*360, dir)
    return rs.PointAdd(origin, vecTwig)

def RecursiveGrowth(ptStart, vecDir, props, generation):
    minTwigCount, maxTwigCount, maxGenerations, maxTwigLength, lengthMutation, maxTwigAngle, angleMutation = props    
    if generation>maxGenerations: return
    
    newProps = props
    maxTwigLength *= lengthMutation
    maxTwigAngle *= angleMutation
    if maxTwigAngle>90: maxTwigAngle=90
    
    newprops = minTwigCount, maxTwigCount, maxGenerations, maxTwigLength, lengthMutation, maxTwigAngle, angleMutation
    maxN = int(minTwigCount + random.random()*(maxTwigCount - minTwigCount))
    for n in range(1, maxN):
        ptGrow = RandomPointInCone(ptStart, vecDir, 0.25*maxTwigLength, maxTwigLength, maxTwigAngle)
        newTwig = AddArcDir(ptStart, ptGrow, vecDir)
        if newTwig:
            vecGrow = rs.CurveTangent(newTwig, rs.CurveDomain(newTwig)[1])
            
            RecursiveGrowth(ptGrow, vecGrow, newProps, generation+1)

minTwigCount = 5
maxTwigCount = 50
maxGenerations = 10
maxTwigLength = 200
lengthMutation = 10
maxTwigAngle = 20.0
angleMutation = 5.5
props = minTwigCount, maxTwigCount, maxGenerations, maxTwigLength, lengthMutation, maxTwigAngle, angleMutation


RecursiveGrowth([0,0,0], [0,0,10], props, maxGenerations-1)

e si ottiene il risultato aspettato:

anche in GH in parte risolvo, ma sembra che manchi di aggiungere la lista di “rami secondari”.
Sicuramente sto sbagliando la parte che ho aggiunto per ottenere l’output dal componente, e quindi come fare l’append della lista o come chiamare la funzione. :person_shrugging:

allego il gh modificato:
Python_101_RecursiveTree4.gh (14,7 KB)

e la parte di GhPython script del recursive:

def RecursiveGrowth(ptStart, vecDir, props, generation):
    minTwigCount, maxTwigCount, maxGenerations, maxTwigLength, lengthMutation, maxTwigAngle, angleMutation = props
    if generation>maxGenerations: return
    b=[]
    newProps = props
    maxTwigLength *= lengthMutation
    maxTwigAngle *= angleMutation
    if maxTwigAngle>90: maxTwigAngle=90
    
    newprops = minTwigCount, maxTwigCount, maxGenerations, maxTwigLength, lengthMutation, maxTwigAngle, angleMutation
    maxN = int(minTwigCount + random.random()*(maxTwigCount - minTwigCount))
    for n in range(1, maxN):
        ptGrow = RandomPointInCone(ptStart, vecDir, 0.25*maxTwigLength, maxTwigLength, maxTwigAngle)
        newTwig = AddArcDir(ptStart, ptGrow, vecDir)
        if newTwig:
            vecGrow = rs.CurveTangent(newTwig, rs.CurveDomain(newTwig)[1])
            RecursiveGrowth(ptGrow, vecGrow, newProps, generation+1)
        b.append(newTwig)
    return b

questa parte mi sembrava di averla capita perchè con gli altri script riesco ad outputtare quello che voglio, qui no :face_with_spiral_eyes:

1 Mi Piace

Sposta b=() fuori dalla def.
img2

1 Mi Piace

Grazie mille! Chiaramente mi devo rimettere a studiare