def fractal(depth, x1, y1, z1, x2, y2, z2, length, anglerec, angle, lvariation, aran, lran, anglerech, angleh, branches, verticality, gchance): #test if depth>0 if depth: #defining random angle variation and length variation arn = random.uniform(-angle / 100 * aran, angle / 100 * aran) lrn = random.uniform(-length / 100 * lran, length / 100 * lran) if hrandom == True: #defining horizontal rotation angles ahor = random.sample(range(0, 360), branches) #removing numbers within tolerance ahr = rs.CullDuplicateNumbers(ahor, angleh) #in a 360 fashion if ahr[0] + 360 - angleh < ahr[-1]: del ahr[0] else: #generating evenly distributed angles ahr = range(0, 360 + 1, 360 // branches)[:-1] #previous branch vector vecst = rg.Point3d(x1, y1, z1) vecend = rg.Point3d(x2, y2, z2) movevec = ghc.Vector2Pt(vecst, vecend, True)[0] #returns vector and it's length #perpendicular vector rotplane3 = ghc.PlaneNormal( vecend, movevec) #creates plane perpendicular to vector plns = ghc.DeconstructPlane(rotplane3) #origin, x, y, z rotplane = ghc.ConstructPlane( plns[2], plns[1], plns[3] ) #constructing new plane switching x and y planes to make perpendicular #generating perpendicular vector vecperp = ghc.Rotate(movevec, radians(90), rotplane)[0] #generating vector amplitudes leny = (length + lrn) * sin( radians((anglerec + arn) * (1 - (verticality**depth)))) lenz = (length + lrn) * cos(radians(anglerec + arn)) ampy = ghc.Amplitude(vecperp, leny) ampz = ghc.Amplitude(movevec, lenz) #changing branch length dependant on branch depth length = length * lvariation #building points endpoint1 = ghc.Move( vecend, ampz)[0] #returns moved object and transformation data endpoint = ghc.Move( endpoint1, ampy)[0] #returns moved object and transformation data #rotating point in a cone fashion rotpoint = ghc.Rotate3D( endpoint, radians(anglerech), vecend, movevec)[0] #returns rotated geometry and transformation data #building line between points linegeo = rg.Line(vecend, rotpoint) #setting coords for next branch x1 = x2 y1 = y2 z1 = z2 #getting xyz from rotated point x2 = rg.Point3d(rotpoint)[0] y2 = rg.Point3d(rotpoint)[1] z2 = rg.Point3d(rotpoint)[2] #building a dict of lines with depth as key, and corresponding lines as values if depth not in treelin.keys(): treelin[depth] = [linegeo] else: treelin[depth].append(linegeo) #calling function with different angle parameter for branch splitting #calling as many branches as spread within tolerance for aa in ahr: if ( (random.randint(40, 99) / 100)**depth ) < gchance or depth == depthstart + 1: #or added to prevent blank trees fractal(depth - 1, x1, y1, z1, x2, y2, z2, length, angle, angle, lvariation, aran, lran, aa, angleh, branches, verticality, gchance)
def fractal(depth, x1, y1, z1, x2, y2, z2, length, anglerec, angle, lvariation, aran, lran, anglerech, angleh, branches, verticality, gchance, depthstart, radtolen, radchng, mngon, polygon, branch_cluster): #test if depth>0 if depth: #defining random angle variation and length variation arn = random.uniform(-angle / 100 * aran, angle / 100 * aran) lrn = random.uniform(-length / 100 * lran, length / 100 * lran) if hrandom == True: #defining horizontal rotation angles ahor = random.sample(range(0, 360), branches) #removing numbers within tolerance ahr = rs.CullDuplicateNumbers(ahor, angleh) #in a 360 fashion if ahr[0] + 360 - angleh < ahr[-1]: del ahr[0] else: #generating evenly distributed angles ahr = range(0, 360 + 1, 360 // branches)[:-1] #previous branch vector vecst = rg.Point3d(x1, y1, z1) vecend = rg.Point3d(x2, y2, z2) movevec = ghc.Vector2Pt(vecst, vecend, True)[0] #returns vector and it's length #perpendicular vector rotplane3 = ghc.PlaneNormal( vecend, movevec) #creates plane perpendicular to vector plns = ghc.DeconstructPlane(rotplane3) #origin, x, y, z rotplane = ghc.ConstructPlane( plns[2], plns[1], plns[3] ) #constructing new plane switching x and y planes to make perpendicular #generating perpendicular vector vecperp = ghc.Rotate(movevec, radians(90), rotplane)[0] #generating vector amplitudes leny = (length + lrn) * sin( radians((anglerec + arn) * (1 - (verticality**depth)))) lenz = (length + lrn) * cos(radians(anglerec + arn)) ampy = ghc.Amplitude(vecperp, leny) ampz = ghc.Amplitude(movevec, lenz) #changing branch length dependant on branch depth length = length * lvariation #building points endpoint1 = ghc.Move( vecend, ampz)[0] #returns moved object and transformation data endpoint = ghc.Move( endpoint1, ampy)[0] #returns moved object and transformation data #rotating point in a cone fashion rotpoint = ghc.Rotate3D( endpoint, radians(anglerech), vecend, movevec)[0] #returns rotated geometry and transformation data #building line between points linegeo = rg.Line(vecend, rotpoint) #defining recursion depth key = depthstart + 1 - depth #building geometry pln = ghc.PlaneNormal(rotpoint, linegeo) #returns a plane perp to a vector radius = length * (radchng**(key)) / radtolen #reduce details with each branch, but not less than 3 splits = 3 if mngon - key + 1 <= 3 else mngon - key + 1 polygonend = ghc.Polygon(pln, radius, splits, 0)[0] #returns a polygon and its perimeter #aligning curves for loft creation crvst = ghc.EndPoints(polygon)[0] pntcld = ghc.Discontinuity(polygonend, 1) #returns points and point parameters #finind seam point closest_point = ghc.ClosestPoint( crvst, pntcld[0] ) #returns closest point, closest point index, distance between closest points seampnt = pntcld[1][closest_point[1]] polygonend = ghc.Seam(polygonend, seampnt) lcurves = [polygon, polygonend] #building geometry geo = ghc.ExtrudePoint( polygon, rotpoint ) if depth == 1 and splits == 3 else rg.Brep.CreateFromLoft( lcurves, rg.Point3d.Unset, rg.Point3d.Unset, rg.LoftType.Normal, False)[0] #if last branch than make a pyramid #make solid geocapped = ghc.CapHoles(geo) #building a dict of geo with depth as key, and geo as values pgons.update( {branch_cluster: [geocapped]}) if branch_cluster not in pgons.keys( ) else pgons[branch_cluster].append(geocapped) branchesout.append(geocapped) #setting coords for next branch x1 = x2 y1 = y2 z1 = z2 #getting xyz from rotated point x2 = rg.Point3d(rotpoint)[0] y2 = rg.Point3d(rotpoint)[1] z2 = rg.Point3d(rotpoint)[2] #setting base polygon for next branch polygon = polygonend #filling dict with branch clusters cluster.append(cluster[-1] + 1) branch_cluster = cluster[-1] #calling function with different angle parameter for branch splitting, calling as many branches as spread within tolerance if depth != 1: for aa in ahr: if ( (random.randint(40, 99) / 100)**depth ) < gchance or depth == depthstart + 1: #or added to prevent blank trees fractal(depth - 1, x1, y1, z1, x2, y2, z2, length, angle, angle, lvariation, aran, lran, aa, angleh, branches, verticality, gchance, depthstart, radtolen, radchng, mngon, polygon, branch_cluster) #leaf logic if depth <= leavesdepth and leavesperbranch > 0 and maxleaves > 0: #vector for leaf growth spread leafpntvec = ghc.Vector2Pt(vecend, rotpoint, True)[0] #setting leaf growth position on last barnch, leafpnt list lastbranchlength = ghc.Length(linegeo) leaves_list = [lastbranchlength] [ leaves_list.append(lengthparam) for lengthparam in random.sample( range(0, int(lastbranchlength)), leavesperbranch - 1) ] if leavesperbranch > 1 else None for leafpnt in leaves_list: leafamp = ghc.Amplitude(leafpntvec, leafpnt) leafpoint = ghc.Move(vecend, leafamp)[0] #plane for leaf generation linetocenter = ghc.Line(stpntbase, leafpoint) planetocenter = ghc.PlaneNormal(leafpoint, linetocenter) #create an imaginary circle with leaflen radius and populate it with points for random leaf generation leafgenerationcircle = ghc.CircleCNR(leafpoint, linetocenter, leaflen) circlesurf = ghc.BoundarySurfaces(leafgenerationcircle) leafcnt = random.randint(0, maxleaves) if leafcnt > 0: leafendpnts = ghc.PopulateGeometry(circlesurf, leafcnt, random.randint(1, 500)) def leafgenerator(point): #random z move zmove = rg.Vector3d(0, 0, 1) moveamp = random.uniform(-leaflen / 3, leaflen / 5) ampzmove = ghc.Amplitude(zmove, moveamp) llendpnt = ghc.Move(point, ampzmove)[0] #setting a leaf centerline vector leafvector = ghc.Vector2Pt(leafpoint, llendpnt, True)[0] #defining leaf center point as avarage of st and end pnts midpnt = ghc.Average([leafpoint, llendpnt]) #generating perpendicular vector vecperpleaf = ghc.Rotate(leafvector, radians(90), planetocenter)[0] leafperpamp = ghc.Amplitude( vecperpleaf, random.uniform((leafwidth / 2) / 5 * 4, (leafwidth / 2) / 5 * 6)) #moving mid point to both sides midpnt1 = ghc.Move(midpnt, leafperpamp)[0] midpnt2 = ghc.Move(midpnt, -leafperpamp)[0] #leaf geo leafgeo = rg.NurbsSurface.CreateFromCorners( leafpoint, midpnt1, llendpnt, midpnt2) leaves.append(leafgeo) #iterate over random number of generated points if list, else generate for one point [leafgenerator(pp) for pp in leafendpnts] if isinstance( leafendpnts, list) else leafgenerator(leafendpnts)
def fractal(depth, x1, y1, z1, x2, y2, z2, length, anglerec, angle, lvariation, aran, lran, anglerech, angleh, branches, gravity): #test if depth>0 if depth: #defining random angle variation and length variation arn = random.uniform(-angle / 100 * aran, angle / 100 * aran) lrn = random.uniform(-length / 100 * lran, length / 100 * lran) #defining horizontal rotation angles ahor = random.sample(range(0, 360), branches) """ #removing numbers within tolerance ahr = rs.CullDuplicateNumbers(ahor, angleh) #in a 360 fashion if ahr[0]+360-angleh<ahr[-1]: del ahr[0] random.shuffle(ahr) """ ahr = [0, 90, 270, 180] #previous branch vector vecst = rg.Point3d(x1, y1, z1) vecend = rg.Point3d(x2, y2, z2) movevec = ghc.Vector2Pt(vecst, vecend, True)[0] #returns vector and it's length #perpendicular vector rotation plane rotplane3 = ghc.PlaneNormal( vecend, movevec) #creates plane perpendicular to vector plns = ghc.DeconstructPlane(rotplane3) #origin, x, y, z rotplane = ghc.ConstructPlane( plns[0], plns[3], plns[2] ) #constructing new plane switching x and y planes to make perpendicular #generating perpendicular vector vecperp = ghc.Rotate(movevec, radians(90), rotplane)[0] #generating vector amplitudes leny = (length + lrn) * sin(radians(anglerec + arn)) lenz = (length + lrn) * cos(radians(anglerec + arn)) ampy = ghc.Amplitude(vecperp, leny) ampz = ghc.Amplitude(movevec, lenz) #changing branch length dependant on branch depth length = length * lvariation #building points endpoint1 = ghc.Move( vecend, ampz)[0] #returns moved object and transformation data endpoint = ghc.Move( endpoint1, ampy)[0] #returns moved object and transformation data #rotating point in a cone fashion rotpoint = ghc.Rotate3D( endpoint, anglerech, vecend, movevec)[0] #returns rotated geometry and transformation data #vertical branch angle angl1 = ghc.Angle(rg.Line(vecend, rotpoint), horizont, verticalpln)[0] #outputs angle and reflex angl = ghc.Degrees(angl1) anglls.append(angl) #rotate depending on how horizontal branch is if angl > 0 and angl < 180: if angl < 89: grrot = ((30 / 100) * (100 - (angl * 0.9)) / 100) * gravity elif angl > 91: grrot = ((30 / 100) * (100 - ((180 - angl) * 0.9)) / 100) * gravity try: grrot == 0 rotpoint = ghc.Rotate3D(rotpoint, grrot, vecend, verticalpln)[0] except: pass #building line between points linegeo = rg.Line(vecend, rotpoint) #setting coords for next branch x1 = x2 y1 = y2 z1 = z2 #getting xyz from rotated point x2 = rg.Point3d(rotpoint)[0] y2 = rg.Point3d(rotpoint)[1] z2 = rg.Point3d(rotpoint)[2] #building a dict of lines with depth as key, and corresponding lines as values if depth not in treelin.keys(): treelin[depth] = [linegeo] else: treelin[depth].append(linegeo) #calling function with different angle parameter for branch splitting #calling as many branches as spread within tolerance for aa in ahr: fractal(depth - 1, x1, y1, z1, x2, y2, z2, length, angle, angle, lvariation, aran, lran, aa, angleh, branches, gravity)
def fractal(depth, x1, y1, z1, x2, y2, z2, length, anglerec, angle, lvariation, aran, lran, anglerech, angleh, branches, verticality, gchance, depthstart, radtolen, radchng, mngon, polygon): #test if depth>0 if depth: #defining random angle variation and length variation arn = random.uniform(-angle / 100 * aran, angle / 100 * aran) lrn = random.uniform(-length / 100 * lran, length / 100 * lran) if hrandom == True: #defining horizontal rotation angles ahor = random.sample(range(0, 360), branches) #removing numbers within tolerance ahr = rs.CullDuplicateNumbers(ahor, angleh) #in a 360 fashion if ahr[0] + 360 - angleh < ahr[-1]: del ahr[0] else: #generating evenly distributed angles ahr = range(0, 360 + 1, 360 // branches)[:-1] #previous branch vector vecst = rg.Point3d(x1, y1, z1) vecend = rg.Point3d(x2, y2, z2) movevec = ghc.Vector2Pt(vecst, vecend, True)[0] #returns vector and it's length #perpendicular vector rotplane3 = ghc.PlaneNormal( vecend, movevec) #creates plane perpendicular to vector plns = ghc.DeconstructPlane(rotplane3) #origin, x, y, z rotplane = ghc.ConstructPlane( plns[2], plns[1], plns[3] ) #constructing new plane switching x and y planes to make perpendicular #generating perpendicular vector vecperp = ghc.Rotate(movevec, radians(90), rotplane)[0] #generating vector amplitudes leny = (length + lrn) * sin( radians((anglerec + arn) * (1 - (verticality**depth)))) lenz = (length + lrn) * cos(radians(anglerec + arn)) ampy = ghc.Amplitude(vecperp, leny) ampz = ghc.Amplitude(movevec, lenz) #changing branch length dependant on branch depth length = length * lvariation #building points endpoint1 = ghc.Move( vecend, ampz)[0] #returns moved object and transformation data endpoint = ghc.Move( endpoint1, ampy)[0] #returns moved object and transformation data #rotating point in a cone fashion rotpoint = ghc.Rotate3D( endpoint, radians(anglerech), vecend, movevec)[0] #returns rotated geometry and transformation data #building line between points linegeo = rg.Line(vecend, rotpoint) #defining recursion depth key = depthstart + 1 - depth #building geometry #stpnt = VECEND ghc.EndPoints(nn)[0] #returns list of two points, start and end #endpnt = ROTPOINT ghc.EndPoints(nn)[1] pln = ghc.PlaneNormal(rotpoint, linegeo) #returns a plane perp to a vector radius = length * (radchng**(key)) / radtolen #polygon = polygonbase #reduce details with each branch, but not less than 3 if mngon - key + 1 <= 3: splits = 3 else: splits = mngon - key + 1 polygonend = ghc.Polygon(pln, radius, splits, 0)[0] #returns a polygon and its perimeter #creating loft between polygons #Normal = rg.LoftType.Normal #loptions = ghc.LoftOptions(False, True, 0, 0, rg.LoftType.Normal) #loft option lcurves = [polygon, polygonend] #loftedgeo = ghc.Loft(lcurves, loptions) if depth == 1 and splits == 3: geo = ghc.ExtrudePoint( polygon, rotpoint) #if last branch than make a pyramid else: geo = ghc.RuledSurface(polygon, polygonend) #setting coords for next branch x1 = x2 y1 = y2 z1 = z2 #getting xyz from rotated point x2 = rg.Point3d(rotpoint)[0] y2 = rg.Point3d(rotpoint)[1] z2 = rg.Point3d(rotpoint)[2] #setting base polygon for next branch polygon = polygonend #pgons.append(polygon) #pgons.append(linegeo) pgons.append(geo) #calling function with different angle parameter for branch splitting #calling as many branches as spread within tolerance for aa in ahr: if ( (random.randint(40, 99) / 100)**depth ) < gchance or depth == depthstart + 1: #or added to prevent blank trees fractal(depth - 1, x1, y1, z1, x2, y2, z2, length, angle, angle, lvariation, aran, lran, aa, angleh, branches, verticality, gchance, depthstart, radtolen, radchng, mngon, polygon)
def fractal(depth, x1, y1, z1, x2, y2, z2, length, anglerec, angle, lvariation, aran, lran, anglerech, angleh, branches, verticality, gchance, depthstart, radtolen, radchng, mngon, polygon, branch_cluster): #test if depth>0 if depth: #defining random angle variation and length variation arn = random.uniform(-angle / 100 * aran, angle / 100 * aran) lrn = random.uniform(-length / 100 * lran, length / 100 * lran) if hrandom == True: #defining horizontal rotation angles ahor = random.sample(range(0, 360), branches) #removing numbers within tolerance ahr = rs.CullDuplicateNumbers(ahor, angleh) #in a 360 fashion if ahr[0] + 360 - angleh < ahr[-1]: del ahr[0] else: #generating evenly distributed angles ahr = range(0, 360 + 1, 360 // branches)[:-1] #previous branch vector vecst = rg.Point3d(x1, y1, z1) vecend = rg.Point3d(x2, y2, z2) movevec = ghc.Vector2Pt(vecst, vecend, True)[0] #returns vector and it's length #perpendicular vector rotplane3 = ghc.PlaneNormal( vecend, movevec) #creates plane perpendicular to vector plns = ghc.DeconstructPlane(rotplane3) #origin, x, y, z rotplane = ghc.ConstructPlane( plns[2], plns[1], plns[3] ) #constructing new plane switching x and y planes to make perpendicular #generating perpendicular vector vecperp = ghc.Rotate(movevec, radians(90), rotplane)[0] #generating vector amplitudes leny = (length + lrn) * sin( radians((anglerec + arn) * (1 - (verticality**depth)))) lenz = (length + lrn) * cos(radians(anglerec + arn)) ampy = ghc.Amplitude(vecperp, leny) ampz = ghc.Amplitude(movevec, lenz) #changing branch length dependant on branch depth length = length * lvariation #building points endpoint1 = ghc.Move( vecend, ampz)[0] #returns moved object and transformation data endpoint = ghc.Move( endpoint1, ampy)[0] #returns moved object and transformation data #rotating point in a cone fashion rotpoint = ghc.Rotate3D( endpoint, radians(anglerech), vecend, movevec)[0] #returns rotated geometry and transformation data #building line between points linegeo = rg.Line(vecend, rotpoint) #defining recursion depth key = depthstart + 1 - depth #building geometry pln = ghc.PlaneNormal(rotpoint, linegeo) #returns a plane perp to a vector radius = length * (radchng**(key)) / radtolen #reduce details with each branch, but not less than 3 if mngon - key + 1 <= 3: splits = 3 else: splits = mngon - key + 1 polygonend = ghc.Polygon(pln, radius, splits, 0)[0] #returns a polygon and its perimeter #aligning curves for loft creation crvst = ghc.EndPoints(polygon)[0] pntcld = ghc.Discontinuity(polygonend, 1) #returns points and point parameters #finind seam point closest_point = ghc.ClosestPoint( crvst, pntcld[0] ) #returns closest point, closest point index, distance between closest points seampnt = pntcld[1][closest_point[1]] polygonend = ghc.Seam(polygonend, seampnt) lcurves = [polygon, polygonend] #building geometry if depth == 1 and splits == 3: geo = ghc.ExtrudePoint( polygon, rotpoint) #if last branch than make a pyramid else: geo = rg.Brep.CreateFromLoft(lcurves, rg.Point3d.Unset, rg.Point3d.Unset, rg.LoftType.Normal, False)[0] #make solid geocapped = ghc.CapHoles(geo) #building a dict of geo with depth as key, and geo as values, for more efficient joins if branch_cluster not in pgons.keys(): pgons[branch_cluster] = [geocapped] else: pgons[branch_cluster].append(geocapped) #setting coords for next branch x1 = x2 y1 = y2 z1 = z2 #getting xyz from rotated point x2 = rg.Point3d(rotpoint)[0] y2 = rg.Point3d(rotpoint)[1] z2 = rg.Point3d(rotpoint)[2] #setting base polygon for next branch polygon = polygonend #calling function with different angle parameter for branch splitting #calling as many branches as spread within tolerance #filling dict with branch clusters cluster.append(cluster[-1] + 1) branch_cluster = cluster[-1] for aa in ahr: if ( (random.randint(40, 99) / 100)**depth ) < gchance or depth == depthstart + 1: #or added to prevent blank trees fractal(depth - 1, x1, y1, z1, x2, y2, z2, length, angle, angle, lvariation, aran, lran, aa, angleh, branches, verticality, gchance, depthstart, radtolen, radchng, mngon, polygon, branch_cluster)