tutorials:a-beginners-tutorial
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
tutorials:a-beginners-tutorial [2024/12/19 11:36] – created Tim | tutorials:a-beginners-tutorial [2024/12/19 13:34] (current) – barley1965 | ||
---|---|---|---|
Line 8: | Line 8: | ||
Installing the platform GroIMP on your computer is actually quite straightforward if you carefully follow the instructions below. GroIMP runs on Java, so first of all, make sure you have a recent version of Java installed. To check if you have Java installed on your machine you open the command prompt window (type cmd in the search window), then type “java -version”, | Installing the platform GroIMP on your computer is actually quite straightforward if you carefully follow the instructions below. GroIMP runs on Java, so first of all, make sure you have a recent version of Java installed. To check if you have Java installed on your machine you open the command prompt window (type cmd in the search window), then type “java -version”, | ||
- | {{:tutorial: | + | {{:tutorials: |
I have version 22 on my computer, which is one of the latest versions. If you don’t see this message or you know you don’t have Java, make sure to install Java version 22 before proceeding to the next step (you can find it here: https:// | I have version 22 on my computer, which is one of the latest versions. If you don’t see this message or you know you don’t have Java, make sure to install Java version 22 before proceeding to the next step (you can find it here: https:// | ||
Line 21: | Line 21: | ||
Locate the downloaded file, double click on it (make sure you have administrator rights on your machine for installation), | Locate the downloaded file, double click on it (make sure you have administrator rights on your machine for installation), | ||
- | {{:tutorial: | + | {{:tutorials: |
Normally, click on ‘I Agree’, then on ‘Next’. Choose the destination folder, then the maximum heap size for Java. This allocates a certain amount of RAM (random access memory) to the Java Virtual Machine on which GroIMP is running. By default, 1500 MB are allocated, but you can allocate up to 50 per cent of the RAM available on your machine to Java, without any problem (so on a machine with 10 GB RAM you can enter 5000):\\ | Normally, click on ‘I Agree’, then on ‘Next’. Choose the destination folder, then the maximum heap size for Java. This allocates a certain amount of RAM (random access memory) to the Java Virtual Machine on which GroIMP is running. By default, 1500 MB are allocated, but you can allocate up to 50 per cent of the RAM available on your machine to Java, without any problem (so on a machine with 10 GB RAM you can enter 5000):\\ | ||
- | {{:tutorial: | + | {{:tutorials: |
After this you click on ‘Install’ and wait for the installation to finish (this can take more than ten minutes). | After this you click on ‘Install’ and wait for the installation to finish (this can take more than ten minutes). | ||
- | After the installation, | + | After the installation, |
GroIMP will now be available either on your desktop or in the list of programmes: | GroIMP will now be available either on your desktop or in the list of programmes: | ||
- | {{:tutorial: | + | {{:tutorials: |
Opening GroIMP should give a splash screen like this: | Opening GroIMP should give a splash screen like this: | ||
- | {{:tutorial: | + | {{:tutorials: |
- | Then the platform should open, but you won’t see much yet, just an empty window with a menu on top. The first thing we want to do is to open an existing model called Alga.gsz: In the menu, go to “File” –> “Open”, then choose “Alga.gsz”((// | + | Then the platform should open, but you won’t see much yet, just an empty window with a menu on top. The first thing we want to do is to open an existing model called Alga.gsz: In the menu, go to “File” –> “Open”, then choose “Alga.gsz”((// |
))//.// (see also [[# | ))//.// (see also [[# | ||
- | {{:tutorial: | + | {{:tutorials: |
You should then see the following screen: | You should then see the following screen: | ||
- | {{:tutorial: | + | {{:tutorials: |
- | Note that on your machine, the naming of the menu items might vary, due to the language settings of your Java version (I have a French Java installation, so some of the menu items will appear | + | Note that on your machine, the naming of the menu items might vary, due to the language settings of your Java version (in this tutorial, the menu items will appear in English).\\ |
GroIMP is a multi-windows platform, i.e. it consists in fact of a (large) number of windows, which can be piled upon each other (like the sheets in an Excel file), “glued” side by side, or be viewed separately (this is handy if your computer is connected to more than one computer screen). To change the size of an integrated window you can simply click and drag on one of the grey hatched lines separating two windows. To change the position of a window you can click on the tab, hold and drag the whole window to its new position. You will see on your left a window called “View”, which contains the visual output of a model (currently a blue cylinder on its side, with a label “A” below it) and on your right a window called “jEdit – Alga.rgg”, | GroIMP is a multi-windows platform, i.e. it consists in fact of a (large) number of windows, which can be piled upon each other (like the sheets in an Excel file), “glued” side by side, or be viewed separately (this is handy if your computer is connected to more than one computer screen). To change the size of an integrated window you can simply click and drag on one of the grey hatched lines separating two windows. To change the position of a window you can click on the tab, hold and drag the whole window to its new position. You will see on your left a window called “View”, which contains the visual output of a model (currently a blue cylinder on its side, with a label “A” below it) and on your right a window called “jEdit – Alga.rgg”, | ||
- | {{:tutorial: | + | {{:tutorials: |
- | The buttons “run” and “Run run” serve to run the model. Unless you are told so, __do not use__ the “Run run” button for the time being, as in some models (like the current one!) it will carry out the rules indefinitely, | + | The buttons “run” and “Run run” serve to run the model. Unless you are told so, __do not use__ the “Run run” button for the time being, as in some models (like the current one!) it will carry out the rules indefinitely, |
- | If you modify the code you can save it afterwards using the save button of the jEdit window: {{:tutorial: | + | If you modify the code you can save it afterwards using the save button of the jEdit window: {{:tutorials: |
Apart from saving the code, this button will have an effect similar to the reset button, by letting you go back to the starting point of the model. | Apart from saving the code, this button will have an effect similar to the reset button, by letting you go back to the starting point of the model. | ||
Line 59: | Line 59: | ||
Let’s have a closer look at the code (in the jEdit window). By the way, jEdit is an external code editor, which will highlight reserved words and other parts of the code, thereby making it more readable. Scrolling down to line 22 (the line numbers can be found on the left of the jEdit screen), you will see the following code: | Let’s have a closer look at the code (in the jEdit window). By the way, jEdit is an external code editor, which will highlight reserved words and other parts of the code, thereby making it more readable. Scrolling down to line 22 (the line numbers can be found on the left of the jEdit screen), you will see the following code: | ||
- | {{:tutorial: | + | {{:tutorials: |
- | From the lecture, you will already know that the text in line 24 is a rule, with a left-hand-side and a right-hand-side. The keyword ‘Axiom’ refers to the start word of the L-system, and ‘==> | + | The text in line 24 is a rule, with a left-hand-side and a right-hand-side. The keyword ‘Axiom’ refers to the start word of the L-system, and ‘%%==>%%’ is an operator that essentially means “// |
- | {{:tutorial: | + | {{:tutorials: |
Note that the rule has to end with a semicolon (;) : omitting this will result in the error message above. This error message is rather helpful as it points exactly to the place where something has gone wrong and indicates what has to be modified: concretely, here it says//: I actually expected a semicolon instead of the square bracket, so to rectify the code insert a semicolon before the square bracket,// ] ). (You will have to get used to the fact that error messages are often pointing to a place in the code just above/ | Note that the rule has to end with a semicolon (;) : omitting this will result in the error message above. This error message is rather helpful as it points exactly to the place where something has gone wrong and indicates what has to be modified: concretely, here it says//: I actually expected a semicolon instead of the square bracket, so to rectify the code insert a semicolon before the square bracket,// ] ). (You will have to get used to the fact that error messages are often pointing to a place in the code just above/ | ||
- | {{:tutorial: | + | {{:tutorials: |
Reinsert the semicolon at the end of line 24 and save the code. | Reinsert the semicolon at the end of line 24 and save the code. | ||
Let’s have a closer look at the code surrounding the Axiom rule: | Let’s have a closer look at the code surrounding the Axiom rule: | ||
- | protected void init () | + | '' |
init () is what is called a method in the Java language. Whenever you see a name followed by a pair of simple brackets, (), you can be almost certain that you are dealing with a method. A method is a little //programme within the programme//, | init () is what is called a method in the Java language. Whenever you see a name followed by a pair of simple brackets, (), you can be almost certain that you are dealing with a method. A method is a little //programme within the programme//, | ||
Next, have a look at the following code:\\ | Next, have a look at the following code:\\ | ||
- | {{:tutorial: | + | {{:tutorials: |
It is another method, named run(), void like the init() method (i.e. just //doing stuff// but returning nothing), but its type is public. This means the user can actually directly carry out this method by pressing the run (or Run run) button on the upper left panel that we have looked at before. The run() method contains three rules that we already dealt with in the lecture. They describe the development of the filamentous cyanobacterium (formerly known as blue-green alga) species //Anabaena catenula//, which was used by Aristid Lindenmayer to create the first L-system.\\ | It is another method, named run(), void like the init() method (i.e. just //doing stuff// but returning nothing), but its type is public. This means the user can actually directly carry out this method by pressing the run (or Run run) button on the upper left panel that we have looked at before. The run() method contains three rules that we already dealt with in the lecture. They describe the development of the filamentous cyanobacterium (formerly known as blue-green alga) species //Anabaena catenula//, which was used by Aristid Lindenmayer to create the first L-system.\\ | ||
Line 92: | Line 92: | ||
- | Open Ex02.gsz ([[# | + | Open Ex02.gsz ([[# |
- | {{:tutorial: | + | {{:tutorials: |
F(x) on the left-hand side (LHS) is replaced by 4 times F(x/3) on the right-hand-side (RHS) of the rule. This is actually already a parametric L-system, because the F has a parameter x (its length, which is equal to 10 in the beginning, see Axiom rule). And because we are using x on the left- and right-hand side of the rule, we can make sure that the length of the F at the left-hand side of the rule is taken over to the right-hand side. In other words F(10) on the LHS becomes F(3.33333) on the RHS. Other than that we have three rotation command, twice RU(-60) and once RU(120). Together with the replacement of one F by four smaller Fs, this gives the fractal that is known as the von Koch curve. Click a few times on application (not “Run application”) to observe the transformation of the triangle into a snowflake (we had this model in the lecture).\\ | F(x) on the left-hand side (LHS) is replaced by 4 times F(x/3) on the right-hand-side (RHS) of the rule. This is actually already a parametric L-system, because the F has a parameter x (its length, which is equal to 10 in the beginning, see Axiom rule). And because we are using x on the left- and right-hand side of the rule, we can make sure that the length of the F at the left-hand side of the rule is taken over to the right-hand side. In other words F(10) on the LHS becomes F(3.33333) on the RHS. Other than that we have three rotation command, twice RU(-60) and once RU(120). Together with the replacement of one F by four smaller Fs, this gives the fractal that is known as the von Koch curve. Click a few times on application (not “Run application”) to observe the transformation of the triangle into a snowflake (we had this model in the lecture).\\ | ||
By the way, we learned in the lecture that the stuff we see in the View window is actually only an interpretation of the string by the turtle. Where is the string? Click on the window tab “Textual Overview” to see the string. In the beginning it looks like this:\\ | By the way, we learned in the lecture that the stuff we see in the View window is actually only an interpretation of the string by the turtle. Where is the string? Click on the window tab “Textual Overview” to see the string. In the beginning it looks like this:\\ | ||
- | {{:tutorial: | + | {{:tutorials: |
Note that the string is preceded by the words “Node” and “RGGRoot” and that the string is bordered by two square brackets [] like the rules. All strings in GroIMP are actually graphs and they all have to start by these two initial nodes. You also see that at the start there are 8 nodes (the six turtle commands from the Axiom rule, plus the two initial nodes). After carrying out application once, this increases to 26 (the initial two nodes, plus the initial three RU commands, plus 3 times 7 new turtle commands that originate from replacing F). This increases to 98 in the next step, then 386, 1538, 6145, 24577, 98305, 393217… we stop here as the string rapidly becomes too long to be counted. | Note that the string is preceded by the words “Node” and “RGGRoot” and that the string is bordered by two square brackets [] like the rules. All strings in GroIMP are actually graphs and they all have to start by these two initial nodes. You also see that at the start there are 8 nodes (the six turtle commands from the Axiom rule, plus the two initial nodes). After carrying out application once, this increases to 26 (the initial two nodes, plus the initial three RU commands, plus 3 times 7 new turtle commands that originate from replacing F). This increases to 98 in the next step, then 386, 1538, 6145, 24577, 98305, 393217… we stop here as the string rapidly becomes too long to be counted. | ||
Line 112: | Line 112: | ||
Click on the application button a few times: the initial stem produces further, ever thinner and shorter, stems, plus branches consisting of slightly bent-up stems (the effect of the command RU(-20)): | Click on the application button a few times: the initial stem produces further, ever thinner and shorter, stems, plus branches consisting of slightly bent-up stems (the effect of the command RU(-20)): | ||
- | {{:tutorial: | + | {{:tutorials: |
How do we get the alternation of branches (left and right following upon each other)? | How do we get the alternation of branches (left and right following upon each other)? | ||
Line 132: | Line 132: | ||
Open Ex06.gsz ([[# | Open Ex06.gsz ([[# | ||
- | {{:tutorial: | + | {{:tutorials: |
B(x) is the Bud, and I(x) the internode. We have again rotations around the UP axis, RU(30) and RU(-30), but these are followed by rotations around the HEAD axis of the turtle, RH(90). It is these rotations which turn the structure into a true 3D architecture.\\ | B(x) is the Bud, and I(x) the internode. We have again rotations around the UP axis, RU(30) and RU(-30), but these are followed by rotations around the HEAD axis of the turtle, RH(90). It is these rotations which turn the structure into a true 3D architecture.\\ | ||
Line 142: | Line 142: | ||
Open Ex07.gsz ([[# | Open Ex07.gsz ([[# | ||
- | {{:tutorial: | + | {{:tutorials: |
Note, however, that the sides of the triangle are now colored, red, blue and yellow. Have a look at the Axiom rule to see why: | Note, however, that the sides of the triangle are now colored, red, blue and yellow. Have a look at the Axiom rule to see why: | ||
- | {{:tutorial: | + | {{:tutorials: |
What has happened here? Instead of simply using F (with an argument in brackets) we have used f1:F(10) and f2:F(10). This is called “assigning a name to an object”. In other words, using a //unique// name (f1 and f2), we have identified the first two F(10) (note that we have not done this with the last F(10)). The way to do it is to use a unique short name followed by a colon (:) and the designation of a (previously defined) module or a known turtle command (which is an object, too). Change the first f2:F(10) to f1:F(10) and save the code. When you do this, the buttons on the top left of the screen will disappear, and a message appear in the window “Messages”: | What has happened here? Instead of simply using F (with an argument in brackets) we have used f1:F(10) and f2:F(10). This is called “assigning a name to an object”. In other words, using a //unique// name (f1 and f2), we have identified the first two F(10) (note that we have not done this with the last F(10)). The way to do it is to use a unique short name followed by a colon (:) and the designation of a (previously defined) module or a known turtle command (which is an object, too). Change the first f2:F(10) to f1:F(10) and save the code. When you do this, the buttons on the top left of the screen will disappear, and a message appear in the window “Messages”: | ||
- | {{:tutorial: | + | {{:tutorials: |
You have declared the local variable f1 twice, which is not allowed as it should be unique like we said before, and also (2< | You have declared the local variable f1 twice, which is not allowed as it should be unique like we said before, and also (2< | ||
- | {{:tutorial: | + | {{:tutorials: |
This method accepts the hexadecimal color value 0x0000ff and interprets is as pure blue. So what then, is the color 0xff0000? You see that the last F is yellow? Why? How can you change its color from yellow to fuchsia? | This method accepts the hexadecimal color value 0x0000ff and interprets is as pure blue. So what then, is the color 0xff0000? You see that the last F is yellow? Why? How can you change its color from yellow to fuchsia? | ||
Line 160: | Line 160: | ||
Press the derivation button once: the snowflake appears but everything is yellow now! Have a look at the rule in the method derivation to see why: in fact, when this rule is carried out, any F(x) (where x represents the length of the line, initially 10) is replaced by four new F, but in this rule no colours are specified. The specific objects f1 and f2 and their colors are //only// defined in the Axiom rule, not afterwards in the derivation rule. In this rule, they are thus replaced by new F whose color is undefined and thus yellow. How do you have to rewrite the code to //keep// the colors (see following picture)? | Press the derivation button once: the snowflake appears but everything is yellow now! Have a look at the rule in the method derivation to see why: in fact, when this rule is carried out, any F(x) (where x represents the length of the line, initially 10) is replaced by four new F, but in this rule no colours are specified. The specific objects f1 and f2 and their colors are //only// defined in the Axiom rule, not afterwards in the derivation rule. In this rule, they are thus replaced by new F whose color is undefined and thus yellow. How do you have to rewrite the code to //keep// the colors (see following picture)? | ||
- | {{:tutorial: | + | {{:tutorials: |
(Hint: use the fact that the turtle command F has three parameters: length, diameter, and color, where the latter can be indicated as a simple number between 0 and 15). | (Hint: use the fact that the turtle command F has three parameters: length, diameter, and color, where the latter can be indicated as a simple number between 0 and 15). | ||
Line 168: | Line 168: | ||
Open Ex08.gsz ([[# | Open Ex08.gsz ([[# | ||
+ | <code java> | ||
F(x/3) RU(-60) F(x/3) RU(120) F(x/3) RU(-60) F(x/3) | F(x/3) RU(-60) F(x/3) RU(120) F(x/3) RU(-60) F(x/3) | ||
+ | </ | ||
Suppose we want to change the angle of the RU rotation, from 60 and -60 to 55 and -55. We could do this manually by changing all the arguments one by one (note that we replaced 120 by 2*55=110): | Suppose we want to change the angle of the RU rotation, from 60 and -60 to 55 and -55. We could do this manually by changing all the arguments one by one (note that we replaced 120 by 2*55=110): | ||
F(x/3) RU(-55) F(x/3) RU(110) F(x/3) RU(-55) F(x/3) | F(x/3) RU(-55) F(x/3) RU(110) F(x/3) RU(-55) F(x/3) | ||
Line 187: | Line 188: | ||
Open Ex09.gsz ([[# | Open Ex09.gsz ([[# | ||
+ | <code java> | ||
module Leaf(float len, float width) extends Parallelogram(len, | module Leaf(float len, float width) extends Parallelogram(len, | ||
{{setShader(GREEN); | {{setShader(GREEN); | ||
+ | </ | ||
The leaf is defined as an extension of a Parallelogram object. You can have a look at how such an object looks like, by inserting it into the scene. For this, use the menu item “Objects” 🡪 “Primitives” 🡪 “Parallelogram”: | The leaf is defined as an extension of a Parallelogram object. You can have a look at how such an object looks like, by inserting it into the scene. For this, use the menu item “Objects” 🡪 “Primitives” 🡪 “Parallelogram”: | ||
- | {{:tutorial: | + | {{:tutorials: |
- | The Leaf module is defined with two parameters, len and width, both of type float (floating point number), which will be used to draw a parallelogram of length len and width width. Finally, the definition invokes the method setShader of Parallelogram to paint the leaves green. Note that for this you need to write {{ in the beginning, and }} at the end. | + | The Leaf module is defined with two parameters, len and width, both of type float (floating point number), which will be used to draw a parallelogram of length len and width width. Finally, the definition invokes the method setShader of Parallelogram to paint the leaves green. Note that for this you need to write '' |
The leaf petiole is defined as an extension of F: | The leaf petiole is defined as an extension of F: | ||
Line 210: | Line 212: | ||
Open Ex10.gsz ([[# | Open Ex10.gsz ([[# | ||
- | {{:tutorial: | + | {{:tutorials: |
Make sure you do this quickly otherwise you might see this happen: | Make sure you do this quickly otherwise you might see this happen: | ||
- | {{:tutorial: | + | {{:tutorials: |
In fact “slowly double clicking” on the name opens the editor to rename the shader, which we don’t want right now (but it’s good to know anyway).\\ | In fact “slowly double clicking” on the name opens the editor to rename the shader, which we don’t want right now (but it’s good to know anyway).\\ | ||
When you have double clicked correctly you should see the Attribute Editor appear with the Shader properties open: | When you have double clicked correctly you should see the Attribute Editor appear with the Shader properties open: | ||
- | {{:tutorial: | + | {{:tutorials: |
You will see that the shader for the leaf object is already defined as an image (with a long, German sounding name…). Click on that name and choose another image, “GalaLeaf1”: | You will see that the shader for the leaf object is already defined as an image (with a long, German sounding name…). Click on that name and choose another image, “GalaLeaf1”: | ||
- | {{:tutorial: | + | {{:tutorials: |
Notice that when you have already produced a structure, the effect is immediate, i.e. the leaf textures will change to the new image instantly. Otherwise you will see it when you develop the structure by pressing run a few times. By the way, you can also create your own (leaf) textures. Here’s how it’s done: Instead of clicking on “Project Images” you click on “from File”, then select an image file (preferably in png format) that you have prepared with, e.g. a tool like GIMP or ImageJ (for now you can simply download an image of a leaf from the internet and use that). | Notice that when you have already produced a structure, the effect is immediate, i.e. the leaf textures will change to the new image instantly. Otherwise you will see it when you develop the structure by pressing run a few times. By the way, you can also create your own (leaf) textures. Here’s how it’s done: Instead of clicking on “Project Images” you click on “from File”, then select an image file (preferably in png format) that you have prepared with, e.g. a tool like GIMP or ImageJ (for now you can simply download an image of a leaf from the internet and use that). | ||
Line 232: | Line 234: | ||
Open Ex11.gsz ([[# | Open Ex11.gsz ([[# | ||
- | {{:tutorial: | + | {{:tutorials: |
We declared two constants, APICAL_REDUCTION-FACTOR, | We declared two constants, APICAL_REDUCTION-FACTOR, | ||
- | {{:tutorial: | + | {{:tutorials: |
You see that the Bud, which has a parameter strength, is “named” using b:Bud, so that we can use a // | You see that the Bud, which has a parameter strength, is “named” using b:Bud, so that we can use a // | ||
Line 245: | Line 247: | ||
Open Ex12.gsz ([[# | Open Ex12.gsz ([[# | ||
- | {{:tutorial: | + | {{:tutorials: |
This constant is of type integer and restricts the maximum branching order to 2. Next, since it is the Bud which is going to carry the information about the branching order, we need to give the Bud a new parameter, let’s call it order: | This constant is of type integer and restricts the maximum branching order to 2. Next, since it is the Bud which is going to carry the information about the branching order, we need to give the Bud a new parameter, let’s call it order: | ||
- | {{:tutorial: | + | {{:tutorials: |
When the first Bud is initiated in the Axiom rule, we write | When the first Bud is initiated in the Axiom rule, we write | ||
- | {{:tutorial: | + | {{:tutorials: |
to designate a bud with order 0 and strength 5. In the actual production rule, several things are happening: | to designate a bud with order 0 and strength 5. In the actual production rule, several things are happening: | ||
- | {{:tutorial: | + | {{:tutorials: |
The order of the bud is referred to with the letter o, but like before we also use the “name” b for the Bud to be able to refer to its parameter order in the following condition, | The order of the bud is referred to with the letter o, but like before we also use the “name” b for the Bud to be able to refer to its parameter order in the following condition, | ||
Line 268: | Line 270: | ||
Open Ex13.gsz ([[# | Open Ex13.gsz ([[# | ||
- | {{:tutorial: | + | {{:tutorials: |
STRENGTH_LIMIT is a constant parameter that we are going to use to define a certain lower limit of the strength variable of Bud. Have a look at the new condition in the production rule of the method grow: | STRENGTH_LIMIT is a constant parameter that we are going to use to define a certain lower limit of the strength variable of Bud. Have a look at the new condition in the production rule of the method grow: | ||
+ | <code java> | ||
(b[order] <= MAX_ORDER_ALLOWED && b[strength] > STRENGTH_LIMIT) | (b[order] <= MAX_ORDER_ALLOWED && b[strength] > STRENGTH_LIMIT) | ||
+ | </ | ||
We see a new condition, b[strength] > STRENGTH_LIMIT, | We see a new condition, b[strength] > STRENGTH_LIMIT, | ||
Line 283: | Line 285: | ||
Open Ex14.gsz ([[# | Open Ex14.gsz ([[# | ||
- | {{:tutorial: | + | {{:tutorials: |
This module has two parameters, age (because the Internode will age, i.e. become older with time), and f, both of type integer, i.e. they will typically be incremented by adding 1. Note that it extends F, whereby very small values for length and diameter are given (the initial size of the internode being small as we intend it to grow). The colouring of the Internode is very strange, but you will see that it will help us to distinguish the different internodes: we use “if“ and “else” and the condition “(f==0) to paint the internode either green or blue, depending on whether f is zero or not. The definition of the module for the Meristem is: | This module has two parameters, age (because the Internode will age, i.e. become older with time), and f, both of type integer, i.e. they will typically be incremented by adding 1. Note that it extends F, whereby very small values for length and diameter are given (the initial size of the internode being small as we intend it to grow). The colouring of the Internode is very strange, but you will see that it will help us to distinguish the different internodes: we use “if“ and “else” and the condition “(f==0) to paint the internode either green or blue, depending on whether f is zero or not. The definition of the module for the Meristem is: | ||
- | {{:tutorial: | + | {{:tutorials: |
which gives a red sphere in appearance. Meristem has the same two parameters, age and f. In the Axiom rule, a Meristem is inserted, with age = 30 and f=0: | which gives a red sphere in appearance. Meristem has the same two parameters, age and f. In the Axiom rule, a Meristem is inserted, with age = 30 and f=0: | ||
- | {{:tutorial: | + | {{:tutorials: |
The public method run contains three rules. The first one replaces the Meristem with an Internode and a new Meristem, under the condition that its age is exactly 30. | The public method run contains three rules. The first one replaces the Meristem with an Internode and a new Meristem, under the condition that its age is exactly 30. | ||
- | {{:tutorial: | + | {{:tutorials: |
This is done by identifying the Meristem by a name “m”, which is then used in the condition (“m[age]”) and to pass on the current value of f to the Internode (“m[f]”) and the new Meristem (“1-m[f]”). This is to make sure to have consecutive values of f that alternate between 0 and 1 (if you don’t believe me, try this out in an Excel sheet…). Look back at the definition of the Internode and you see now that this will lead to an alternation of blue and green internodes. Also note that the Internode and Meristem receive age = 0, their initial age.\\ | This is done by identifying the Meristem by a name “m”, which is then used in the condition (“m[age]”) and to pass on the current value of f to the Internode (“m[f]”) and the new Meristem (“1-m[f]”). This is to make sure to have consecutive values of f that alternate between 0 and 1 (if you don’t believe me, try this out in an Excel sheet…). Look back at the definition of the Internode and you see now that this will lead to an alternation of blue and green internodes. Also note that the Internode and Meristem receive age = 0, their initial age.\\ | ||
The second rule is a so-called actualization rule: | The second rule is a so-called actualization rule: | ||
- | {{:tutorial: | + | {{:tutorials: |
The left-hand-side looks similar to the last rule, only that the condition m[age]< | The left-hand-side looks similar to the last rule, only that the condition m[age]< | ||
Line 306: | Line 308: | ||
The third rule is again an actualization rule, but this time several variables of Internode are updated at once: | The third rule is again an actualization rule, but this time several variables of Internode are updated at once: | ||
- | {{:tutorial: | + | {{:tutorials: |
Length is incremented by 0.005 as long as the age of the internode has not reached 30 days, diameter is continuously incremented by 0.0002, without a condition, and internode age is incremented by one.\\ | Length is incremented by 0.005 as long as the age of the internode has not reached 30 days, diameter is continuously incremented by 0.0002, without a condition, and internode age is incremented by one.\\ | ||
Line 315: | Line 317: | ||
Open Ex16.gsz ([[# | Open Ex16.gsz ([[# | ||
- | {{:tutorial: | + | {{:tutorials: |
The rule continues as follows: | The rule continues as follows: | ||
- | {{:tutorial: | + | {{:tutorials: |
- | {{:tutorial: | + | {{:tutorials: |
- | {{:tutorial: | + | {{:tutorials: |
Line 335: | Line 337: | ||
Open Ex17.gsz ([[# | Open Ex17.gsz ([[# | ||
- | {{:tutorial: | + | {{:tutorials: |
The following module definition is a bit special: Here you define your own rotation command derived from the turtle command RU: It inherits the attribute " | The following module definition is a bit special: Here you define your own rotation command derived from the turtle command RU: It inherits the attribute " | ||
- | {{:tutorial: | + | {{:tutorials: |
(If you do not do this then GroIMP will issue a warning message but will nevertheless compile the code otherwise : try it out by writing “float angle” instead of “super.angle”!). | (If you do not do this then GroIMP will issue a warning message but will nevertheless compile the code otherwise : try it out by writing “float angle” instead of “super.angle”!). | ||
Line 345: | Line 347: | ||
The Axiom rule is longer than usual, we actually specify the entire structure already here, a stem with two lateral branches, at two different insertion points and angles: | The Axiom rule is longer than usual, we actually specify the entire structure already here, a stem with two lateral branches, at two different insertion points and angles: | ||
- | {{:tutorial: | + | {{:tutorials: |
Note that we are using our own module Rotation instead of RU.\\ | Note that we are using our own module Rotation instead of RU.\\ | ||
The public method changeAngle (for which you will have a button) contains an actualization rule for our module Rotation:\\ | The public method changeAngle (for which you will have a button) contains an actualization rule for our module Rotation:\\ | ||
- | {{:tutorial: | + | {{:tutorials: |
There are two conditions for this rule to be applied, and both concern the current argument of Rotation (identified here as “r”): In fact, the condition states that for the rule to be applied, the angle should be between MAXANGLE and -MAXANGLE. This might seem strange at first but in the if-else statement that follows you will see that it works, because if the angle is already negative it will be further decreased until it reaches -90 degrees, and if it is positive, it will be further increased until it reaches +90 degrees. Try out a value for MAXANGLE of 20, and see what happens! How can you slow down the angle increment on one side only? | There are two conditions for this rule to be applied, and both concern the current argument of Rotation (identified here as “r”): In fact, the condition states that for the rule to be applied, the angle should be between MAXANGLE and -MAXANGLE. This might seem strange at first but in the if-else statement that follows you will see that it works, because if the angle is already negative it will be further decreased until it reaches -90 degrees, and if it is positive, it will be further increased until it reaches +90 degrees. Try out a value for MAXANGLE of 20, and see what happens! How can you slow down the angle increment on one side only? | ||
Line 362: | Line 364: | ||
//Write the following two rules in the editor window below the comment (“%%// | //Write the following two rules in the editor window below the comment (“%%// | ||
- | **Axiom ==> Bud** | + | **Axiom |
- | **Bud ==> Internode Node Bud** | + | **Bud %%==>%% Internode Node Bud** |
In order for this to work as a program, we have to write a bit more (by “wrapping” the rules with some method code): | In order for this to work as a program, we have to write a bit more (by “wrapping” the rules with some method code): | ||
- | {{:tutorial: | + | {{:tutorials: |
run() is a public method. public: so that the user (you) can use it to run the model, and a method is a function that is carried out to run what is found inside, in this case the rule(s) are carried out. The name of the method doesn’t have to be run(), by the way: you can call it what you like, e.g. executer() | run() is a public method. public: so that the user (you) can use it to run the model, and a method is a function that is carried out to run what is found inside, in this case the rule(s) are carried out. The name of the method doesn’t have to be run(), by the way: you can call it what you like, e.g. executer() | ||
Line 376: | Line 378: | ||
//Click the run button a few times. Also, open the graph view (In the Menu go to “Panels, 2D, Graph”). Click on the objects and then inspect the Attribute Editor.// In the graph view you see the actual data structure, the “graph”. | //Click the run button a few times. Also, open the graph view (In the Menu go to “Panels, 2D, Graph”). Click on the objects and then inspect the Attribute Editor.// In the graph view you see the actual data structure, the “graph”. | ||
- | //Move the object, zoom in and out, and turn it, using the corresponding tools.// {{:tutorial: | + | //Move the object, zoom in and out, and turn it, using the corresponding tools.// {{:tutorials: |
- | //Click// {{:tutorial: | + | //Click// {{:tutorials: |
===== Introducing Leaves ===== | ===== Introducing Leaves ===== | ||
Line 388: | Line 390: | ||
//Insert the source code between Node and Bud:// **[ Leaf ]** | //Insert the source code between Node and Bud:// **[ Leaf ]** | ||
- | {{:tutorial: | + | {{:tutorials: |
- | //then save and rerun by pressing// {{:tutorial: | + | //then save and rerun by pressing// {{:tutorials: |
- | {{:tutorial: | + | {{:tutorials: |
The leaves are normally not sticking to the branch, but instead they are inserted at a certain angle. To tell the program that it should put the leaf at such an angle, we use this rotation command: **RL(70)**. You already know the turtle from the lecture: It has three axes around which rotations can take place. The RL-command will perform a rotation (R) around the left or L-Vector. //You can also visualize the three vectors with the first three fingers of your (right or left) hand//: thumb = UP, index = HEAD, middle = LEFT | The leaves are normally not sticking to the branch, but instead they are inserted at a certain angle. To tell the program that it should put the leaf at such an angle, we use this rotation command: **RL(70)**. You already know the turtle from the lecture: It has three axes around which rotations can take place. The RL-command will perform a rotation (R) around the left or L-Vector. //You can also visualize the three vectors with the first three fingers of your (right or left) hand//: thumb = UP, index = HEAD, middle = LEFT | ||
- | {{:tutorial: | + | {{:tutorials: |
//Now save and rerun the model for a few steps//. The rotation around the LEFT vector is also called “pitching down” (similar to a landing or sinking plane). | //Now save and rerun the model for a few steps//. The rotation around the LEFT vector is also called “pitching down” (similar to a landing or sinking plane). | ||
- | {{:tutorial: | + | {{:tutorials: |
As you can see, the leaves are all pointing to one side, which is rather unnatural. Quite more often, leaves are arranged differently, | As you can see, the leaves are all pointing to one side, which is rather unnatural. Quite more often, leaves are arranged differently, | ||
- | {{:tutorial: | + | {{:tutorials: |
//Save and rerun//. Finally, let’s insert another internode below the bud, because it seems the apical bud is sticking directly to the leaf. //Insert// **Internode** //before// RH(180)// | //Save and rerun//. Finally, let’s insert another internode below the bud, because it seems the apical bud is sticking directly to the leaf. //Insert// **Internode** //before// RH(180)// | ||
- | {{:tutorial: | + | {{:tutorials: |
- | {{:tutorial: | + | {{:tutorials: |
===== Introducing branches ===== | ===== Introducing branches ===== | ||
Line 418: | Line 420: | ||
Now we have a single stem with leaves, which endlessly produces new phytomers at the end. However, real plants produce branches, i.e. they produce new phytomers from lateral buds. So how can we teach the model to do this? First, let’s get rid of the leaves for reasons of simplicity, we will put them back in later. //Comment the leaves out using /* */ (the code should look like this:\\ | Now we have a single stem with leaves, which endlessly produces new phytomers at the end. However, real plants produce branches, i.e. they produce new phytomers from lateral buds. So how can we teach the model to do this? First, let’s get rid of the leaves for reasons of simplicity, we will put them back in later. //Comment the leaves out using /* */ (the code should look like this:\\ | ||
- | //{{:tutorial: | + | //{{:tutorials: |
- | {{:tutorial: | + | {{:tutorials: |
//Save and run for a few steps only//. You see that the branched structure is completely flat, i.e. 2D. Let’s modify the RH command to make the plant branch to all sides, i.e. in 3 dimensions: | //Save and run for a few steps only//. You see that the branched structure is completely flat, i.e. 2D. Let’s modify the RH command to make the plant branch to all sides, i.e. in 3 dimensions: | ||
//Insert// **RH(137.5)** //before the terminal Bud, then save and rerun:\\ | //Insert// **RH(137.5)** //before the terminal Bud, then save and rerun:\\ | ||
- | //{{:tutorial: | + | //{{:tutorials: |
137.5° is an angle very often encountered in nature: it is referred to as the “Golden Angle”. At this (so-called // | 137.5° is an angle very often encountered in nature: it is referred to as the “Golden Angle”. At this (so-called // | ||
Line 431: | Line 433: | ||
In this series, every new number is the sum of the last two numbers. When you divide two consecutive numbers (the smaller one by the bigger one = “ratio”), | In this series, every new number is the sum of the last two numbers. When you divide two consecutive numbers (the smaller one by the bigger one = “ratio”), | ||
- | Put the leaves back in by removing the comments around the code: {{:tutorial: | + | Put the leaves back in by removing the comments around the code: {{:tutorials: |
- | {{:tutorial: | + | {{:tutorials: |
You get a real ball of leaves, with just one rule! Why do we get this? Because the Bud rule is unrestricted, | You get a real ball of leaves, with just one rule! Why do we get this? Because the Bud rule is unrestricted, | ||
Line 446: | Line 448: | ||
Therefore, the way to restrict for instance branching order is to give the bud a parameter: Have a look at the new definition of the module bud:\\ | Therefore, the way to restrict for instance branching order is to give the bud a parameter: Have a look at the new definition of the module bud:\\ | ||
\\ | \\ | ||
- | {{:tutorial: | + | {{:tutorials: |
- | Bud has now a parameter called order, and it is of type integer (int), which means it can be incremented by adding one each time we create a new branch. Orders are usually counted starting from 0 or 1. Let’s start with 1. When a module is used for the first time, we initiate the parameter by writing its value in brackets just behind the name of the module: As the bud should start with order 1 we //write// **Bud(1)** //in the Axiom:// {{:tutorial: | + | Bud has now a parameter called order, and it is of type integer (int), which means it can be incremented by adding one each time we create a new branch. Orders are usually counted starting from 0 or 1. Let’s start with 1. When a module is used for the first time, we initiate the parameter by writing its value in brackets just behind the name of the module: As the bud should start with order 1 we //write// **Bud(1)** //in the Axiom:// {{:tutorials: |
In the bud rule, we refer to the current value of order with the letter o: **Bud(o)**. The compiler of GroIMP recognizes a parameter of a module from its position when it has more than one parameter (here, order is the only parameter of Bud, and therefore there is only one position). In the beginning this value is 1 (see the Axiom), in other words, when the production rule is applied for the first time, the value of o is one. On the right-hand side, we want to leave the order of the // | In the bud rule, we refer to the current value of order with the letter o: **Bud(o)**. The compiler of GroIMP recognizes a parameter of a module from its position when it has more than one parameter (here, order is the only parameter of Bud, and therefore there is only one position). In the beginning this value is 1 (see the Axiom), in other words, when the production rule is applied for the first time, the value of o is one. On the right-hand side, we want to leave the order of the // | ||
Line 455: | Line 457: | ||
In the end the code of the method run should look like this: | In the end the code of the method run should look like this: | ||
- | {{:tutorial: | + | {{:tutorials: |
- | //Save and rerun using only the// {{:tutorial: | + | //Save and rerun using only the// {{:tutorials: |
- | {{:tutorial: | + | {{:tutorials: |
However, if you manually lower the order of a selected bud and then press run again you will see that this bud will start to develop once more because the condition becomes TRUE. Try it out! | However, if you manually lower the order of a selected bud and then press run again you will see that this bud will start to develop once more because the condition becomes TRUE. Try it out! | ||
Line 474: | Line 476: | ||
The new constant is of type integer, has got the name PHYLLO (remember the convention to write constant is capital letters) and the value 50. (You can write this in Line 25, before the init method). In order to be able to use the phyllochron to determine the moment of bud outgrowth, we have to add a new parameter to the module Bud: | The new constant is of type integer, has got the name PHYLLO (remember the convention to write constant is capital letters) and the value 50. (You can write this in Line 25, before the init method). In order to be able to use the phyllochron to determine the moment of bud outgrowth, we have to add a new parameter to the module Bud: | ||
- | {{:tutorial: | + | {{:tutorials: |
Note that the parameter phyllo is the //first// parameter, while order is now the //second// parameter (this is important as the compiler recognizes parameters in modules by their position). | Note that the parameter phyllo is the //first// parameter, while order is now the //second// parameter (this is important as the compiler recognizes parameters in modules by their position). | ||
Line 480: | Line 482: | ||
We initiate the parameter (i.e. give it a concrete value) the first time the module is declared, in the Axiom rule: | We initiate the parameter (i.e. give it a concrete value) the first time the module is declared, in the Axiom rule: | ||
- | {{:tutorial: | + | {{:tutorials: |
Note that we didn’t write a number but instead used the name of the constant PHYLLO, then the program knows that it has to insert the number 50 every time the name PHYLLO is used. Later, we can change this number more easily in the declaration of the constant PHYLLO. What should be done with this number by the model? The idea is that it should count down from 50 (the current value of PHYLLO) to zero, before producing the next phytomer. The module Bud refers to this parameter under a name, so let’s call it p. p can have values between PHYLLO and 0. If p is larger than zero, it should be reduced by 1. Whenever a new Bud is inserted at the tip of the shoot or at the sides, the parameter should be re-set to the value of PHYLLO, because this new Bud has to wait and “count down” its own value of p from PHYLLO to zero before it can grow out itself. We now have two cases: p>0: wait and p==0: grow. Thus, we need to write a new rule, a kind of “dormancy” rule: | Note that we didn’t write a number but instead used the name of the constant PHYLLO, then the program knows that it has to insert the number 50 every time the name PHYLLO is used. Later, we can change this number more easily in the declaration of the constant PHYLLO. What should be done with this number by the model? The idea is that it should count down from 50 (the current value of PHYLLO) to zero, before producing the next phytomer. The module Bud refers to this parameter under a name, so let’s call it p. p can have values between PHYLLO and 0. If p is larger than zero, it should be reduced by 1. Whenever a new Bud is inserted at the tip of the shoot or at the sides, the parameter should be re-set to the value of PHYLLO, because this new Bud has to wait and “count down” its own value of p from PHYLLO to zero before it can grow out itself. We now have two cases: p>0: wait and p==0: grow. Thus, we need to write a new rule, a kind of “dormancy” rule: | ||
Line 495: | Line 497: | ||
After all these changes, your run-method should look like this:\\ | After all these changes, your run-method should look like this:\\ | ||
- | {{:tutorial: | + | {{:tutorials: |
//Save and rerun now. Change the value of PHYLLO (for instance to 100 or 25) and observe the effect on the speed of development! Check out the values of p by clicking on different buds, you can also manually change these values in the Attribute editor:// | //Save and rerun now. Change the value of PHYLLO (for instance to 100 or 25) and observe the effect on the speed of development! Check out the values of p by clicking on different buds, you can also manually change these values in the Attribute editor:// | ||
- | {{:tutorial: | + | {{:tutorials: |
===== Introducing flowering ===== | ===== Introducing flowering ===== | ||
Line 508: | Line 510: | ||
Now, plants don’t stay vegetative forever. In fact, what you observe in many plants is that an apical meristem, after having formed a certain number of phytomers, will decide to form a terminal flower and thereby use itself up, i.e. there will be no further formation of phytomers. Let’s tell the bud to produce a flower once it has formed a given number of phytomers. In order to do so, we have to introduce a new parameter to the bud, r (for rank), which is counted up to 10, and if r == 10, it produces a flower. First, we change the axiom rule (r is initially 1): | Now, plants don’t stay vegetative forever. In fact, what you observe in many plants is that an apical meristem, after having formed a certain number of phytomers, will decide to form a terminal flower and thereby use itself up, i.e. there will be no further formation of phytomers. Let’s tell the bud to produce a flower once it has formed a given number of phytomers. In order to do so, we have to introduce a new parameter to the bud, r (for rank), which is counted up to 10, and if r == 10, it produces a flower. First, we change the axiom rule (r is initially 1): | ||
- | {{:tutorial: | + | {{:tutorials: |
Then, we need a new rule for the flower, which is inserted after the two rules in the run method: | Then, we need a new rule for the flower, which is inserted after the two rules in the run method: | ||
Line 530: | Line 532: | ||
//Your run method should now look like this:// | //Your run method should now look like this:// | ||
- | {{:tutorial: | + | {{:tutorials: |
You now get a flowering plant, it looks ok, but not really //nice//. | You now get a flowering plant, it looks ok, but not really //nice//. | ||
Line 536: | Line 538: | ||
//Insert the word// **Joli** //before each module (without a space), JoliInternode, | //Insert the word// **Joli** //before each module (without a space), JoliInternode, | ||
- | {{:tutorial: | + | {{:tutorials: |
Of course, Joli is not a magic word. Instead, we had to define all the modules we were going to use in the model beforehand. | Of course, Joli is not a magic word. Instead, we had to define all the modules we were going to use in the model beforehand. | ||
Line 548: | Line 550: | ||
//Now try it on your own: Here is a tree that I constructed using two lines of code and two modules, A and B. Write the code that will create the tree!// | //Now try it on your own: Here is a tree that I constructed using two lines of code and two modules, A and B. Write the code that will create the tree!// | ||
- | {{:tutorial: | + | {{:tutorials: |
//Hint: A is used for the stem, B for the branches.// | //Hint: A is used for the stem, B for the branches.// | ||
Line 585: | Line 587: | ||
] | ] | ||
- | public void executer | + | public void run () |
[ | [ | ||
A ==> A B; | A ==> A B; |
tutorials/a-beginners-tutorial.1734604579.txt.gz · Last modified: 2024/12/19 11:36 by Tim