In this tutorial we will create a simple model of architecture and development of a tomato plant.
module Organ(super.length) extends M(length);
module Apex extends Organ; module Internode extends Organ; module Leaf extends Organ; module Leaflet extends Organ; module Flower extends Organ;
static double PHYLLOTAXIS_ANGLE = 137.51; static double LEAF_ANGLE = 60; static double LEAF_LENGTH = 0.40; static double PETIOLE_WIDTH = 0.01; static double INTERNODE_LENGTH = 0.08; static double INTERNODE_WIDTH = 0.02; static int NB_VEG_PHYTOMERS = 8;
module Apex extends Organ ==> Sphere(0.01).(setShader(RED)) ;
module Internode extends Organ { double width; { length = INTERNODE_LENGTH; width = INTERNODE_WIDTH; } } ==> Cylinder(length, width/2).(setShader(YELLOW)) ;
module Leaf extends Organ { double width; double angle; double petioleLength; double petioleWidth; { length = LEAF_LENGTH; width = 0.5*LEAF_LENGTH; angle = LEAF_ANGLE; petioleLength = 0.2*LEAF_LENGTH; petioleWidth = PETIOLE_WIDTH; } } ==> RL(angle) Cylinder(petioleLength, petioleWidth/2).(setShader(GREEN)) Parallelogram(length-petioleLength, width) ;
module Truss extends Organ ==> RL(TRUSS_ANGLE) RH(90) for (int i:1:NB_FLOWERS) ( Cylinder(0.02,0.001).(setShader(YELLOW)) [ if(i%2==0) ( RH(90) ) else ( RH(-90) ) RU(60) Cylinder(0.02,0.001).(setShader(BLUE)) Sphere(0.02).(setShader(RED)) ] RU(-20) ) ;
protected void init() [ Axiom ==> Apex; ]
First, we specify rewriting rules for vegetative development of the primary shoot in tomato.
public void run() [ a:Apex ==> Internode [Leaf] RH(PHYLLOTAXIS_ANGLE) a ; ]
After a certain number of phytomers (internodes with leaves), specified by a parameter NB_VEG_PHYTOMERS, primary shoot will change into sympodial shoot. For this, a repetitive pattern with 3 leaves and 1 truss with fruits is typical for many (high-wire) tomato cultivars.
public void run() [ a:Apex, (a[rank] < NB_VEG_PHYTOMERS) ==> Internode [Leaf] RH(PHYLLOTAXIS_ANGLE) a {a[rank]++;} ; a:Apex, (a[rank] >= NB_VEG_PHYTOMERS) ==> Internode if ((a[rank] - NB_VEG_PHYTOMERS) % 4 == 1) ( [Truss] ) else ( [Leaf] ) RH(PHYLLOTAXIS_ANGLE) a {a[rank]++;} ; ]