This tutorial will go through how to get started with parameter managers. It will start with an overly simple project to highlight some key features, then, apply the same parameter management to a more advanced project.
The first project is a simple “newRGG” type project. It will be composed of shoots (cylinders) and buds (spheres). The single growth rule replace a bud by a shoot and two buds.
We consider 2 types of bud that will make the growth slightly different: a green one, and a blue one. They both extend the same base bud module.
We first declare the three type of modules that will represent the possible type of “bud”.
module BaseBud(super.radius) extends Sphere { int age = 0; void grow(){ switch(aging){ case 0: age+=1; break; case 1: age = (age>1)? age*age : (age>0)? 2 : 1; break; default: } } } module GBud(super.radius) extends BaseBud.(setShader(GREEN)) { void grow(){ super.grow(); radius *= 0.8; } } module BBud(super.radius) extends BaseBud.(setShader(BLUE)) { void grow(){ super.grow(); radius *= 0.6; } }
Then we define some variables that represent the configuration of the project:
public global int aging = 0; public global int ageLimit = 10; public global int budType = 0; public global float initialLength = 0.8;
Then, we can declare a Bud factory, i.e. a method that produce the type of bud based on the budType:
BaseBud pBud(float len) { switch (budType) { case 0: return new GBud(len); case 1: return new BBud(len); default: return null; } }
Lastly, the initialization and growth rule:
protected void init () [ Axiom ==> pBud(initialLength); ] public void run () [ b:BaseBud(x), (!tooOld(b)) ==> F(x) [RU(30) RH(90) pBud(b[radius]).($[age]=b[age], grow())] [RU(-30) RH(90) pBud(b[radius]).($[age]=b[age], grow())]; ] boolean tooOld(BaseBud n){ return n[age]>ageLimit ; }
The given model can be run until the ageLimit threshold is met. Depending on the value of each of the four presented variables, the resulting “tree” is different.
We can first tag these fours variables as parameters to change them from the GUI editor.
Replace their previous declaration with:
@IsParameter @Choice({"Linear", "Exponential"}) public global int aging = 0; @IsParameter public global int ageLimit = 10; @IsParameter @Choice({"Green bud", "Blue bud"}) public global int budType = 0; @Range(min=0, max=1) @IsParameter public global float initialLength = 0.8;
Now open the GUI editor by clicking on the parameter manager button:
It will open the editor:
In order to simulate how these parameters could impact the resulting tree (not only from a 3d view perspective) we can compute a simple descriptor: the total volume of the buds with the method:
public void compute_vol() { double s = sum( (*Sphere*).getVolume() ); println("Total volume of buds: " + s); } public void complete(){ for (applyUntilFinished()){ run(); } compute_vol(); }
Let's save the current set of parameter values in a file. In the parameter manager editor click on “save parameters”. It will automatically create a parameter file and store the parameter in.
Now we can also set up the project to be run-able in headless and modify parameters from outside of GroIMP, with either:
Add the following to setup the headless to run the complete method from above and to load the parameter's value from the file:
protected void startup() { super.startup(); if (de.grogra.pf.boot.Main.getProperty("headless") != null) { runLater(null); } } protected void run(Object info) { loadPMs(); complete(); System.exit(0); }
Now run the project in headless with:
java -jar core.jar --headless Model.gsz
This will print in the terminal the output value of compute_vol. E.g. Total volume of buds: 2.78392774842903
Let's change some parameter value for the run:
java -jar core.jar -PModel.ageLimit=15 -PModel.aging=1 -PModel.initialLength=1 -PModel.budType=1 --headless Model.gsz
This should display in the terminal: Total volume of buds: 0.07469535004252173.
It is also possible to simply change the content of the parameter file by simply opening the file and changing its content.
The file is called parameter_files/default-parameter-manager.parameters. By setting its content to:
Model.budType=0 Model.ageLimit=7 Model.initialLength=0.5 Model.aging=0
And running in headless again: java -jar core.jar –headless Model.gsz
I get the value: Total volume of buds: 2.592734549068271
Now let's see how these parameters can be fit into a bigger project, the QSM project example