@@ -14,7 +14,7 @@ growth of these trees vary across individuals following a predefined distributio
1414The data types, rendering methods and growth rules are the same as in the binary
1515tree example:
1616
17- ```` @example forest
17+ ```` julia
1818using VirtualPlantLab
1919using Distributions, Plots, ColorTypes
2020import GLMakie
@@ -53,7 +53,7 @@ import .TreeTypes
5353
5454Create geometry + color for the internodes
5555
56- ```` @example forest
56+ ```` julia
5757function VirtualPlantLab. feed! (turtle:: Turtle , i:: TreeTypes.Internode , data)
5858 # Rotate turtle around the head to implement elliptical phyllotaxis
5959 rh! (turtle, data. phyllotaxis)
6565
6666Create geometry + color for the leaves
6767
68- ```` @example forest
68+ ```` julia
6969function VirtualPlantLab. feed! (turtle:: Turtle , l:: TreeTypes.Leaf , data)
7070 # Rotate turtle around the arm for insertion angle
7171 ra! (turtle, - data. leaf_angle)
8080
8181Insertion angle for the bud nodes
8282
83- ```` @example forest
83+ ```` julia
8484function VirtualPlantLab. feed! (turtle:: Turtle , b:: TreeTypes.BudNode , data)
8585 # Rotate turtle around the arm for insertion angle
8686 ra! (turtle, - data. branch_angle)
8989
9090Rules
9191
92- ```` @example forest
92+ ```` julia
9393meristem_rule = Rule (TreeTypes. Meristem, rhs = mer -> TreeTypes. Node () +
9494 (TreeTypes. Bud (), TreeTypes. Leaf ()) +
9595 TreeTypes. Internode () + TreeTypes. Meristem ())
@@ -126,7 +126,7 @@ of each tree and rotates it.
126126(ii) Wrap the axiom, rules and the creation of the graph into a function that
127127takes the required parameters as inputs.
128128
129- ```` @example forest
129+ ```` julia
130130function create_tree (origin, growth, budbreak, orientation)
131131 axiom = T (origin) + RH (orientation) + TreeTypes. Internode () + TreeTypes. Meristem ()
132132 tree = Graph (axiom = axiom, rules = (meristem_rule, branch_rule),
138138The code for elongating the internodes to simulate growth remains the same as for
139139the binary tree example
140140
141- ```` @example forest
141+ ```` julia
142142getInternode = Query (TreeTypes. Internode)
143143
144144function elongate! (tree, query)
@@ -166,13 +166,13 @@ of 2 meters. First we generate the original positions of the trees. For the
166166position we just need to pass a ` Vec ` object with the x, y, and z coordinates of
167167the location of each TreeTypes. The code below will generate a matrix with the coordinates:
168168
169- ```` @example forest
169+ ```` julia
170170origins = [Vec (i,j,0 ) for i = 1 : 2.0 : 20.0 , j = 1 : 2.0 : 20.0 ]
171171````
172172
173173We may assume that the initial orientation is uniformly distributed between 0 and 360 degrees:
174174
175- ```` @example forest
175+ ```` julia
176176orientations = [rand ()* 360.0 for i = 1 : 2.0 : 20.0 , j = 1 : 2.0 : 20.0 ]
177177````
178178
@@ -181,22 +181,22 @@ LogNormal and Beta distribution, respectively. We can generate random
181181values from these distributions using the ` Distributions ` package. For the
182182relative growth rate:
183183
184- ```` @example forest
184+ ```` julia
185185growths = rand (LogNormal (- 2 , 0.3 ), 10 , 10 )
186186histogram (vec (growths))
187187````
188188
189189And for the budbreak parameter:
190190
191- ```` @example forest
191+ ```` julia
192192budbreaks = rand (Beta (2.0 , 10 ), 10 , 10 )
193193histogram (vec (budbreaks))
194194````
195195
196196Now we can create our forest by calling the ` create_tree ` function we defined earlier
197197with the correct inputs per tree:
198198
199- ```` @example forest
199+ ```` julia
200200forest = vec (create_tree .(origins, growths, budbreaks, orientations));
201201nothing # hide
202202````
@@ -214,22 +214,22 @@ as you may need to change some settings in your computer).
214214We can simulate the growth of each tree by applying the method ` simulate ` to each
215215tree, creating a new version of the forest (the code below is an array comprehension)
216216
217- ```` @example forest
217+ ```` julia
218218newforest = [simulate (tree, getInternode, 2 ) for tree in forest];
219219nothing # hide
220220````
221221
222222And we can render the forest with the function ` render ` as in the binary tree
223223example but passing the whole forest at once
224224
225- ```` @example forest
225+ ```` julia
226226render (Scene (newforest))
227227````
228228
229229If we iterate 4 more iterations we will start seeing the different individuals
230230diverging in size due to the differences in growth rates
231231
232- ```` @example forest
232+ ```` julia
233233newforest = [simulate (tree, getInternode, 15 ) for tree in newforest];
234234render (Scene (newforest))
235235````
@@ -243,7 +243,7 @@ and execute the iterations of the loop in multiple threads using the macro `@thr
243243Note that the rendering function can also be ran in parallel (i.e. the geometry will be
244244generated separately for each plant and the merge together):
245245
246- ```` @example forest
246+ ```` julia
247247using Base. Threads
248248newforest = deepcopy (forest)
249249@threads for i in eachindex (forest)
@@ -254,7 +254,7 @@ render(Scene(newforest), parallel = true)
254254
255255An alternative way to perform the simulation is to have an outer loop for each timestep and an internal loop over the different trees. Although this approach is not required for this simple model, most FSP models will probably need such a scheme as growth of each individual plant will depend on competition for resources with neighbouring plants. In this case, this approach would look as follows:
256256
257- ```` @example forest
257+ ```` julia
258258newforest = deepcopy (forest)
259259for step in 1 : 15
260260 @threads for i in eachindex (newforest)
@@ -271,7 +271,7 @@ tweaking the 3D representation. When we want to combine plants generated from gr
271271geometric element it is best to combine all these geometries in a ` GLScene ` object. We can start the scene
272272with the ` newforest ` generated in the above:
273273
274- ```` @example forest
274+ ```` julia
275275scene = Scene (newforest);
276276nothing # hide
277277````
@@ -284,15 +284,15 @@ above when we determined the origin of each plant. VPL offers some shortcuts: `O
284284passing the desired length as input. Below, a rectangle is created on the XY plane with the origin as a
285285corner and each side being 11 units long:
286286
287- ```` @example forest
287+ ```` julia
288288soil = Rectangle (length = 21.0 , width = 21.0 )
289289rotatey! (soil, pi / 2 )
290290VirtualPlantLab. translate! (soil, Vec (0.0 , 10.5 , 0.0 ))
291291````
292292
293293We can now add the ` soil ` to the ` scene ` object with the ` add! ` function.
294294
295- ```` @example forest
295+ ```` julia
296296VirtualPlantLab. add! (scene, mesh = soil, color = RGB (1 ,1 ,0 ))
297297````
298298
@@ -302,7 +302,7 @@ your code but also to help setup the scene (e.g. if you are not sure how big the
302302Howver, it may be distracting for the visualization. It turns out that we can turn that off with
303303` show_axes = false ` :
304304
305- ```` @example forest
305+ ```` julia
306306render (scene, axes = false )
307307````
308308
@@ -312,7 +312,7 @@ we can run the `save_scene` function on the object returned from `render`. The a
312312` render ` to increase the number of pixels in the final image. A helper function ` calculate_resolution ` is provided to
313313compute the resolution from a physical width and height in cm and a dpi (e.g., useful for publications and posters):
314314
315- ```` @example forest
315+ ```` julia
316316res = calculate_resolution (width = 16.0 , height = 16.0 , dpi = 1_000 )
317317output = render (scene, axes = false , resolution = res)
318318export_scene (scene = output, filename = " nice_trees.png" )
0 commit comments