Пример #1
0
def ngons(args):

    nn, length, lvariation, kk, radtolen, mngon, depth, radchng = args

    stpnt = ghc.EndPoints(nn)[0]  #returns list of two points, start and end
    endpnt = ghc.EndPoints(nn)[1]
    vect = ghc.Vector2Pt(stpnt, endpnt,
                         False)[0]  #returns list with vector and vector length
    pln = ghc.PlaneNormal(stpnt, vect)  #returns a plane perp to a vector
    radius = length * (radchng**kk) / radtolen

    #reduce details with each branch, but not less than 3
    if mngon - kk + 1 <= 3:
        splits = 3
    else:
        splits = mngon - kk + 1

    pgn = ghc.Polygon(pln, radius, splits,
                      0)[0]  #returns a polygon and its perimeter

    if kk == depth and splits == 3:
        geo = ghc.ExtrudePoint(pgn,
                               endpnt)  #if last branch than make a pyramid
    else:
        geo = ghc.Extrude(pgn, vect)  #extrudes the polygon along vector

    return ghc.CapHoles(geo)  #caps ends on the extruded brep
Пример #2
0
def ngons(args):

    nn, length, lvariation, kk, radtolen, mngon, depth, radchng = args

    stpnt = ghc.EndPoints(nn)[0]  #returns list of two points, start and end
    endpnt = ghc.EndPoints(nn)[1]
    pln = ghc.PlaneNormal(stpnt, nn)  #returns a plane perp to a vector
    radius = length * (radchng**kk) / radtolen
    radiusend = length * (radchng**(kk + 1)) / radtolen

    #reduce details with each branch, but not less than 3
    if mngon - kk + 1 <= 3:
        splits = 3
    else:
        splits = mngon - kk + 1

    pgn = ghc.Polygon(pln, radius, splits,
                      0)[0]  #returns a polygon and its perimeter

    if kk == depth and splits == 3:
        geo = ghc.ExtrudePoint(pgn,
                               endpnt)  #if last branch than make a pyramid
    else:
        geostraight = ghc.Extrude(pgn, nn)  #extrudes the polygon along vector
        geo = ghc.Taper(
            geostraight, nn, radius, radiusend, False, False, False
        )  #inputs: geometry, axis, start radius, end radius, flat (False), infinite (False), rigid (False)

    return ghc.CapHoles(geo)  #caps ends on the extruded brep
Пример #3
0
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)
Пример #4
0
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)
Пример #5
0
#getting starting point from anchorpoint
x1 = anchorp.X
y1 = anchorp.Y
z1 = anchorp.Z - length  #to generate starting vector

#setting base variables
x2 = x1
y2 = y1
z2 = anchorp.Z  #to generate starting vector

#setting first polygon
radiusbase = length / radtolen
stpntbase = rg.Point3d(x1, y1, z1)
stpntbaseend = rg.Point3d(x2, y2, z2)
vecbase = rg.Line(stpntbase, stpntbaseend)
plnbase = ghc.PlaneNormal(stpntbaseend,
                          vecbase)  #returns a plane perp to a vector
polygonbase = ghc.Polygon(plnbase, radiusbase, mngon,
                          0)[0]  #returns a polygon and its perimeter

#base angle
anglerec = 0
anglerech = 0
cluster = [1]
branch_cluster = cluster[0]

verticality /= 100
gchance /= 100
mngon -= 1  #first mngon is defined outside recursive func, so it should enter it with -1

depth = depthstart
Пример #6
0
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)
Пример #7
0
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, 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)