66DEGREES_TO_RADIANS = pi / 180
77
88def branching_turtle_to_coords (turtle_program , d0 , theta = 20. , phi = 20. ):
9+
910 '''
1011 Working with discontinuous paths i.e. tree formation
1112 '+' : postive rotation by (deg)
@@ -22,87 +23,83 @@ def branching_turtle_to_coords(turtle_program, d0, theta=20., phi=20.):
2223 Returns
2324 tuple: A list of tuples which provide the coordinates of the branches
2425 '''
25-
26- # Initialize variables
27- saved_states = list () # Stack for saving and restoring states
28- stateSize = 10 # Number of elements in each state tuple
29- dx = 0 # x displacement
30- dy = 0 # y displacement
31- dz = 0 # z displacement
32- lseg = 1. # Length of each segment
33- rim = 400 # Rim radius for proximity calculation
34-
35- # Choose the starting direction randomly
26+ saved_states = list ()
27+ stateSize = 10
28+ dx = 0
29+ dy = 0
30+ dz = 0
31+ lseg = 1.
32+ rim = 400
33+
3634 startidx = 3 #random.randint(1,3)
3735 if startidx == 1 :
3836 state = (1. , 0.1 , 0.1 , 0 , 0 , d0 , lseg , dx , dy , dz )
3937 elif startidx == 2 :
4038 state = (0.1 , 1. , 0 , 0 , 0 , d0 , lseg , dx , dy , dz )
4139 else :
4240 state = (0.1 , 0.1 , 1. , 0 , 0 , d0 , lseg , dx , dy , dz )
41+
4342 yield state
4443
45- index = 0 # Keeps track of the index of the command being executed
46- origin = (0.1 , 0.1 , 1. ) # Origin point for proximity calculation
44+ index = 0
45+ origin = (0.1 , 0.1 , 1. )
4746
48- # Loop through each command in the turtle program
4947 for command in turtle_program :
50- # Get the current state of the turtle
5148 x , y , z , alpha , beta , diam , lseg , dx , dy , dz = state
5249
53- # If the command is a move forward command
50+
5451 if command .lower () in 'abcdefghijs' : # Move forward (matches a-j and A-J)
52+ # segment start
53+
5554
56- # Start a new segment
5755 if command .islower ():
58- # Get the length and diameter of the segment from the brackets
5956 lseg , tdiam = eval_brackets (index , turtle_program )
60- # Calculate the displacement vector based on the current direction and segment length
61- dx , dy , dz = rotate ( p = beta * DEGREES_TO_RADIANS ,
62- r = alpha * DEGREES_TO_RADIANS ,
63- v = normalise ( np . array ([ x , y , z ]), lseg ))
64- # If the diameter is specified, update the current diameter
65- if tdiam > 0.0 :
66- diam = tdiam
67- # Move the turtle forward by the displacement vector
57+ dx , dy , dz = rotate ( pitch_angle = beta * DEGREES_TO_RADIANS ,
58+ roll_angle = alpha * DEGREES_TO_RADIANS ,
59+ vector = normalise ( np . array ([ x , y , z ]), lseg ))
60+
61+ if tdiam > 0.0 : diam = tdiam
62+
63+ #dx, dy, dz, alpha = proximity(state,origin,rim)
64+
6865 x += dx
6966 y += dy
7067 z += dz
7168
72- # Save the current state
7369 state = (x , y , z , alpha , beta , diam , lseg , dx , dy , dz )
70+
71+ # segment end
7472 yield state
7573
76- elif command == '+' : # Turn clockwise
77- phi , _ = eval_brackets (index , turtle_program ) # Get the angle to rotate by
78- state = (x , y , z , alpha + phi , beta , diam , lseg , dx , dy , dz ) # Update the state with new angle
74+ elif command == '+' : # Turn clockwise
75+ phi , _ = eval_brackets (index , turtle_program )
76+ state = (x , y , z , alpha + phi , beta , diam , lseg , dx , dy , dz )
7977
80- elif command == '-' : # Turn counterclockwise
81- phi , _ = eval_brackets (index , turtle_program ) # Get the angle to rotate by
82- state = (x , y , z , alpha - phi , beta , diam , lseg , dx , dy , dz ) # Update the state with new angle
78+ elif command == '-' : # Turn counterclockwise
79+ phi , _ = eval_brackets (index , turtle_program )
80+ state = (x , y , z , alpha - phi , beta , diam , lseg , dx , dy , dz )
8381
84- elif command == '/' : # Turn around y-axis
85- theta , _ = eval_brackets (index , turtle_program ) # Get the angle to rotate by
86- state = (x , y , z , alpha , beta + theta , diam , lseg , dx , dy , dz ) # Update the state with new angle
82+ elif command == '/' :
83+ theta , _ = eval_brackets (index , turtle_program )
84+ state = (x , y , z , alpha , beta + theta , diam , lseg , dx , dy , dz )
8785
88- elif command == '[' : # Remember current state
89- saved_states .append (state ) # Push the current state onto the stack
86+ elif command == '[' : # Remember current state
87+ saved_states .append (state )
9088
91- elif command == ']' : # Return to previous state
92- state = saved_states .pop () # Pop the previous state from the stack and update the current state
89+ elif command == ']' : # Return to previous state
90+ state = saved_states .pop ()
9391
94- # Yield a tuple of NaN values to indicate the start of a new branch
95- nanValues = []
96- for i in range (stateSize ): nanValues .append (float ('nan' ))
97- yield tuple (nanValues )
92+ nanValues = []
93+ for i in range (stateSize ): nanValues .append (float ('nan' ))
94+ yield tuple (nanValues )
9895
99- x , y , z , alpha , beta , diam , lseg , dx , dy , dz = state # Update the current state with previous state
100- yield state # Yield the current state
96+ x , y , z , alpha , beta , diam , lseg , dx , dy , dz = state
97+ yield state
10198
102- index += 1 # Increment the command index
103- # Note: silently ignore unknown commands
99+ index += 1
104100
105101def eval_brackets (index , turtle ):
102+
106103 """
107104 Extracts values within brackets in the turtle program and evaluates them to return tuple of values.
108105
@@ -145,7 +142,6 @@ def eval_brackets(index, turtle):
145142 if neg1 == 1 : aa *= - 1 # if neg1 flag is set, negate first value
146143 return aa , 0.0
147144
148-
149145def randomposneg ():
150146 """
151147 Return either 1 or -1 with a 50/50 probability.
@@ -155,8 +151,6 @@ def randomposneg():
155151 """
156152 return 1 if random .random () < 0.5 else - 1
157153
158-
159-
160154def raddist (origin , location , shell = 80 , core = False ):
161155 """
162156 Calculate the distance between two points and check if it falls within a specified range.
@@ -181,8 +175,6 @@ def raddist(origin, location, shell=80, core=False):
181175 # check if location is outside the shell
182176 return distance > shell
183177
184-
185-
186178def proximity (state : tuple , origin : np .ndarray , rim : float ) -> tuple :
187179 """
188180 Calculates the proximity of a point to a given origin within a specified rim.
@@ -244,5 +236,4 @@ def posneg(value: float) -> float:
244236 if value >= 0. :
245237 return 1.
246238 else :
247- return - 1.
248-
239+ return - 1.
0 commit comments