02_user_tutorials:01_getting_started:02_rgg-code-structure
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| 02_user_tutorials:01_getting_started:02_rgg-code-structure [2025/01/24 12:59] – removed - external edit (Unknown date) 127.0.0.1 | 02_user_tutorials:01_getting_started:02_rgg-code-structure [2025/01/24 13:05] (current) – [RGG Code structure introduction] tim2 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== RGG Code structure introduction ====== | ||
| + | |||
| + | The RGG programming language repents the core of almost all GroIMP models. It is used to describe the simulation and analysis of the models and can be quite overwhelming at first. This tutorial describes the basic concept and the structure of a simple simulation. | ||
| + | |||
| + | |||
| + | ===== RGG ===== | ||
| + | |||
| + | The language extends java and implements the XL-language specification (https:// | ||
| + | |||
| + | This leads to a programming language based on two paradigms, the object orientation of java and the rule based structure of XL. In order to separate these two rgg is using different brackets to define code blocks. | ||
| + | The java blocks are framed by curly brackets '' | ||
| + | |||
| + | ===== functions ===== | ||
| + | |||
| + | Even so the function declaration follows the syntax of java, the body of the function can be of both code blocks. In difference to java rgg code allows to start directly with the declaration of functions without creating a class before. (Internally the rgg file is handled as one java class). | ||
| + | |||
| + | If a function is defined by '' | ||
| + | |||
| + | ==== init ==== | ||
| + | |||
| + | Additionally there are several functions predefined that can be used to change the behavior of the simulation. At this point we will only talk about the initialization: | ||
| + | |||
| + | <code java> | ||
| + | protected void init () | ||
| + | [ | ||
| + | {println(" | ||
| + | Axiom ==> A(parameters.length); | ||
| + | ] | ||
| + | </ | ||
| + | |||
| + | The Axiom is the node that is added to the graph in the very beginning of the simulation and is used as an access point. | ||
| + | ===== Java blocks ===== | ||
| + | |||
| + | The java block allow java syntax up to java 1.6.( this is independent from the java version that is used to run GroIMP). Therefore it is possible to use features such as file reading and writing, mathematical calculations, | ||
| + | |||
| + | Every new rgg file also imports by default a set of library functions that are used to interact with the graph or the GroIMP platform. This functions can be explored in the function explorer in the software. You can find it on the main menu under ' | ||
| + | |||
| + | Moreover rgg comes with some additions to the java syntax, or more accurate to the syntax of java 6. | ||
| + | |||
| + | |||
| + | ==== Modules ==== | ||
| + | |||
| + | A module in RGG is very similar to a class in java, it can extend other modules or implements java interfaces. It can also hold functions like ' | ||
| + | The parameters are unlink in a java class directly defined in the head of the module (see below 'float len') and the code executed on the initialization of a module is defined by just a second par of curly brackets (see below {setShader(GREEN); | ||
| + | |||
| + | Besides that the main difference is the use case. A module is always a GroIMP Node, meaning it can be added to the GroIMP simulation graph (ProjectGraph) similar to [[01_user_documentation: | ||
| + | |||
| + | <code java> | ||
| + | module A(float len) extends Sphere(0.1) | ||
| + | { | ||
| + | {setShader(GREEN); | ||
| + | |||
| + | public float getDiameter(){ | ||
| + | return radius*2; | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | It is also possible to have modules that do not extend any other object and have no direct effect on the graph. These nodes can be useful for aggregations, | ||
| + | |||
| + | ==== Instantiation ==== | ||
| + | |||
| + | While in theory every part/ | ||
| + | Using the syntax below the module Branch is one object in the graph and is during the creation of the object interpreted as an extension of M. Yet for the visualization and the ray tracing it is represented by the four F objects with the different shaders. | ||
| + | |||
| + | <code java > | ||
| + | |||
| + | module Branch(float len) extends M(len)==> | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | |||
| + | On the right side of the '' | ||
| + | |||
| + | It has to be noticed that even so instantiations create a smaller graph they tempt to slow down the visualization. | ||
| + | |||
| + | ==== Queries ==== | ||
| + | |||
| + | In GroIMP the project graph is considered to hold almost all information on the simulation. Therefore it can also be seen as a knowledge graph. To retrieve this knowledge rgg uses the [[02_user_tutorials: | ||
| + | |||
| + | As shown in the example below in '' | ||
| + | |||
| + | <code java> | ||
| + | public void calc(){ | ||
| + | long countA = count((*RU(30) RH(90) A*)); | ||
| + | long countM = count((*M*)); | ||
| + | if(countM> | ||
| + | println((float)countA/ | ||
| + | } | ||
| + | println(sum((*Branch*).len)); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | in the last line of the example above: '' | ||
| + | The first way is more in the style of java while the second way is better adapted to GroIMP. Therefore the second way is not only changing the attribute of the object but also notifies the change to the platform. | ||
| + | Moreover it manages the access of the attributes differently, | ||
| + | |||
| + | <code java> | ||
| + | public void growRadius(){ | ||
| + | (*A*)[radius]+=0.1; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== Lambda expressions ==== | ||
| + | |||
| + | Since java 1.6 did not include lamda expression, an own implementation was added to rgg. | ||
| + | The syntax an the explanation can be found [[01_user_documentation: | ||
| + | ===== XL Blocks ===== | ||
| + | |||
| + | While using XL queries mainly two rules are used: replacement rules('' | ||
| + | |||
| + | |||
| + | ==== Replacement rules ==== | ||
| + | |||
| + | The concept of an replacement rule is basically that all part of the project graph that are similar to the left part (before '' | ||
| + | The left part can thereby be any [[02_user_tutorials: | ||
| + | The right part (the production) is a collection of Nodes ( instances of either turtle commands, 3d objects or modules) which are linked by different edges. In the example below only successor- and branch-edges are used. A node that is separated to its predecessor by only a white space is added as a sucessor to the predecessor. A Node or a set of nodes framed by square brackets in that is added to the predecessor with a branch-edge. | ||
| + | |||
| + | The most noticeable difference between these edges is that a Node should always only have one successor child. Therefore branches are needed to grow into different directions based on the way nodes interpreted by the visualization. In very simple terms this interpretation means that the transformation (rotation, location ...) of a Node is the sum of all its predecessors. | ||
| + | |||
| + | In our example the first A on the right side would be moved a distance of '' | ||
| + | |||
| + | |||
| + | <code java> | ||
| + | public void run ()[ | ||
| + | A(x) ==> F(x) [RU(30) RH(90) A(x*0.8)] [RU(-30) RH(90) A(x*0.8)]; | ||
| + | ] | ||
| + | </ | ||
| + | |||
| + | As shown above it is also possible to forward parameters from the left side to the right (similar to a parametric rewriting rule in formal systems). Moreover it is possible to use '' | ||
| + | |||
| + | ==== Execution rule ==== | ||
| + | |||
| + | The left side of an execution rule is similar to the left side of the production rule. Yet the main difference is that the nodes (or pattern of nodes) found by the query are not replaced. Instead the code on the right side is applied on them. | ||
| + | |||
| + | <code java> | ||
| + | public void getDiameter()[ | ||
| + | a: | ||
| + | ] | ||
| + | </ | ||
| + | |||
| + | This works very similar to looping over the result of the query. This also works with manipulation several nodes at the same time: | ||
| + | |||
| + | <code java> | ||
| + | public void change()[ | ||
| + | |||
| + | l:RU h:RH ::> { | ||
| + | float a = h[angle]; | ||
| + | h[angle]=l[angle]; | ||
| + | l[angle]=a; | ||
| + | } | ||
| + | ] | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== Working with several Files ==== | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | In GroIMP it is possible to split your code into several files and folders to improve the structure and keep an overview. | ||
| + | <color # | ||
| + | |||
| + | |||
| + | To use function from another file this file needs to be imported similar to a java class or package. | ||
| + | Yet in the case of GroIMP all files are imported by their name without the directories, | ||
| + | <code java> | ||
| + | import parameters.YourModule; | ||
| + | </ | ||
| + | |||
| + | |||
| + | To get this a bit clearer lets assume our parameters.rgg file contains the following code: | ||
| + | <code java> | ||
| + | public static int length = 1; | ||
| + | public static float diameter = 0.1; | ||
| + | module Leaf() ==> leaf3d(1); | ||
| + | module Shoot() extends F(1); | ||
| + | </ | ||
| + | |||
| + | To import one specific object once, you can simply do '' | ||
| + | <code java> | ||
| + | protected void init () | ||
| + | [ | ||
| + | Axiom ==> parameters.Leaf(); | ||
| + | ] | ||
| + | </ | ||
| + | |||
| + | If you want to use your module several times you can also import it one in the beginning and then reuse it: | ||
| + | |||
| + | <code java> | ||
| + | import parameters.Leaf; | ||
| + | protected void init () | ||
| + | [ | ||
| + | Axiom ==> Leaf()[RL(180) Leaf()]; | ||
| + | ] | ||
| + | </ | ||
| + | |||
| + | Finally you can import all modules with the * operator: | ||
| + | <code java> | ||
| + | import parameters.*; | ||
| + | protected void init () | ||
| + | [ | ||
| + | Axiom ==> Shoot() Leaf()[RL(180) Leaf()]; | ||
| + | ] | ||
| + | </ | ||
| + | |||
| + | This can also be done with the static variables using static import: | ||
| + | <code java> | ||
| + | |||
| + | import static parameters.*; | ||
| + | protected void init () | ||
| + | [ | ||
| + | Axiom ==> F(length, | ||
| + | ] | ||
| + | </ | ||
