diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..3ac663ca7 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,52 @@ +# Contributing to Helios + +Thanks for contributing to [Helios](https://github.com/PlantSimulationLab/Helios)! + +The following set of guidelines should be taken as suggestion, rather than rules. These are currently a work-in-progress, and will evolve along with the project. + +If you have comments or suggestions, please feel free to [open an issue](https://github.com/PlantSimulationLab/Helios/issues/new) or [submit a pull-request](https://github.com/PlantSimulationLab/Helios/compare) to this file. + +## Editing Documentation + +Documentation source files for the Helios core can be found in `doc/UserGuide.dox`, and for each plugin in the corresponding plug-in directory sub-folder `doc/*.dox`. These files are written in [Doxygen](https://www.doxygen.nl/index.html) format. Additionally, documentation for data structures, functions, methods, etc. is written directly in the corresponding header file, and also uses Doxygen syntax. + +If you edit the documentation and want to view the changes, you can build the documentation HTML files. To do this, you need to have Doxygen installed on your system. Then, navigate to the Helios root directory and run: + +```bash +doxygen doc/Doxyfile +``` + +To view the built documentation, open the file `doc/html/index.html` in a web browser. + +## Submitting Changes + +To submit a change, please [push local changes to a branch](https://docs.github.com/en/get-started/using-git/pushing-commits-to-a-remote-repository), and [create a pull-request on github](https://github.com/PlantSimulationLab/Helios/compare). Please make edits to the latest version of the master to the extent possible in order to allow for straight-forward merging of the changes into the master. Pull requests should include a clear list of changes summarizing the overall contents of the change. + +Each individual commits should be prefaced with a one-line summary of the intended change. Large and complex commits may also include a longer description, separated by at least one line: + +``` +$ git commit -m "A brief summary of the commit. +> +> A paragraph describing the change in greater detail." +``` + +## Style Guide + +Code formatting for C++ sources is handled automatically by [clang-format](https://clang.llvm.org/docs/ClangFormat.html), which should be executed before pushing to `master`. To do this, you can run the following from a Unix terminal: + +``` +git diff --name-only master -- '***.cpp' '***.cu' '***.h' | xargs clang-format -i +``` + +Alternatively, configure your CLion client to apply formatting on save or before commit. + +In cases where the auto-formatter is inappropriate, you can disable formatting for a region of code by wrapping it with `// clang-format (off|on)` comments: + +``` +// clang-format off +... your_code_here ... +// clang-format on +``` + +Finally, note that formatting is disabled for external libraries contained in `./core/lib/...`. + diff --git a/core/src/Context.cpp b/core/src/Context.cpp index 55bd9b318..a23a4a3ef 100755 --- a/core/src/Context.cpp +++ b/core/src/Context.cpp @@ -3527,20 +3527,7 @@ helios::vec3 Cone::getNodeCoordinate(int node_index ) const{ } std::vector Cone::getNodeRadii() const{ - std::vector radii_T; - radii_T.resize(2); - for( int i=0; i<2; i++ ){ - - vec3 n0(0,0,0), nx(radii.at(i),0,0); - vec3 n0_T, nx_T; - - vecmult(transform,n0,n0_T); - vecmult(transform,nx,nx_T); - - radii_T.at(i) = (nx_T-n0_T).magnitude(); - - } - return radii_T; + return radii; } float Cone::getNodeRadius( int node_index ) const{ @@ -3548,13 +3535,7 @@ float Cone::getNodeRadius( int node_index ) const{ helios_runtime_error("ERROR (Cone::getNodeRadius): node number must be 0 or 1."); } - vec3 n0(0,0,0), nx(radii.at(node_index), 0, 0); - vec3 n0_T, nx_T; - - vecmult(transform,n0,n0_T); - vecmult(transform,nx,nx_T); - - return (nx_T-n0_T).magnitude(); + return radii.at(node_index); } uint Cone::getSubdivisionCount() const{ @@ -3655,44 +3636,38 @@ void Cone::scaleGirth( float S ){ // calculate the transformed axis unit vector of the cone vec3 axis_unit_vector = helios::make_vec3(nodes_T.at(1).x - nodes_T.at(0).x, nodes_T.at(1).y - nodes_T.at(0).y, nodes_T.at(1).z - nodes_T.at(0).z ); - float length = powf(powf(axis_unit_vector.x,2) + powf(axis_unit_vector.y,2) + powf(axis_unit_vector.z,2),0.5); - axis_unit_vector = axis_unit_vector / length; + axis_unit_vector.normalize(); //translate node 0 back to origin context->getConeObjectPointer(OID)->translate(-1.0*nodes_T.at(0)); - //rotate the cone to align with z axis helios::vec3 z_axis = make_vec3(0,0,1); //get the axis about which to rotate vec3 ra = cross( z_axis, axis_unit_vector); //get the angle to rotate - float dot = axis_unit_vector.x*z_axis.x + axis_unit_vector.y*z_axis.y + axis_unit_vector.z*z_axis.z; + float dot = axis_unit_vector*z_axis; float angle = acos_safe(dot); - //only rotate if the cone is not alread aligned with the z axis (i.e., angle is not zero. If zero, the axis of rotation is 0,0,0 and we end up with problems) + //only rotate if the cone is not already aligned with the z axis (i.e., angle is not zero. If zero, the axis of rotation is 0,0,0 and we end up with problems) if(angle != float(0.0)){ context->getConeObjectPointer(OID)->rotate( -1*angle, ra ); } - // scale the cone in the z (length) dimension - float T[16], T_prim[16]; - makeScaleMatrix( make_vec3(S,S,1), T); - matmult(T,transform,transform); - for( uint UUID : UUIDs){ - if( context->doesPrimitiveExist( UUID ) ){ - context->getPrimitiveTransformationMatrix( UUID,T_prim); - matmult(T,T_prim,T_prim); - context->setPrimitiveTransformationMatrix( UUID,T_prim); - } - } + // scale the cone in the x and y dimensions + context->scaleObject( OID, make_vec3(S,S,1) ); + //rotate back if(angle != 0.0){ context->getConeObjectPointer(OID)->rotate( angle, ra ); } - // //translate back + // translate back context->getConeObjectPointer(OID)->translate(nodes_T.at(0)); + radii.at(0) *= S; + radii.at(1) *= S; + + } uint Context::addSphereObject(uint Ndivs, const vec3 ¢er, float radius ){ @@ -4224,9 +4199,6 @@ uint Context::addTubeObject(uint Ndivs, const std::vector &nodes, const st auto* tube_new = (new Tube(currentObjectID, UUID, nodes, radius, color, Ndivs, "", this)); - float T[16], transform[16]; - tube_new->getTransformationMatrix( transform ); - for( uint p : UUID){ getPrimitivePointer_private(p)->setParentObjectID(currentObjectID); } @@ -4359,9 +4331,6 @@ uint Context::addTubeObject(uint Ndivs, const std::vector &nodes, const st auto* tube_new = (new Tube(currentObjectID, UUID, nodes, radius, colors, Ndivs, texturefile, this)); - float T[16], transform[16]; - tube_new->getTransformationMatrix( transform ); - for( uint p : UUID){ getPrimitivePointer_private(p)->setParentObjectID(currentObjectID); } @@ -4900,14 +4869,6 @@ uint Context::addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, fl auto* cone_new = (new Cone(currentObjectID, UUID, node0, node1, radius0, radius1, Ndivs, "", this)); - float T[16], transform[16]; - cone_new->getTransformationMatrix( transform ); - - makeTranslationMatrix(nodes.front(),T); - matmult(T,transform,transform); - - cone_new->setTransformationMatrix( transform ); - for( uint p : UUID){ getPrimitivePointer_private(p)->setParentObjectID(currentObjectID); } @@ -5031,14 +4992,6 @@ uint Context::addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, fl auto* cone_new = (new Cone(currentObjectID, UUID, node0, node1, radius0, radius1, Ndivs, texturefile, this)); - float T[16], transform[16]; - cone_new->getTransformationMatrix( transform ); - - makeTranslationMatrix(nodes.front(),T); - matmult(T,transform,transform); - - cone_new->setTransformationMatrix( transform ); - for( uint p : UUID){ getPrimitivePointer_private(p)->setParentObjectID(currentObjectID); } diff --git a/doc/CHANGELOG b/doc/CHANGELOG index 5510fc6c6..0dff7b3fd 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -1693,3 +1693,18 @@ The radiation model has been re-designed, with the following primary additions: - Added RadiationModel::deleteRadiationSource(). - Deleted some overloaded versions of RadiationModel::addSunSphereSource() that take a sourceID as input to change the source ID. Instead we can use RadiationModel::deleteRadiationSource() and re-add a new source. - Fixed an error in RadiationModel::getSourceFlux() for sun sphere sources that caused the flux to be incorrect. + +[1.3.14] 2024-06-22 + +***NEW PLUG-IN*** +- Plant Architecture plug-in merged from development branch to master repo. This plug-in is still in beta testing and is not yet fully documented and is likely to still have a number of bugs. Please report bugs as you find them. + +*Context* +- Cone object girth was not being properly scaled. + +*Solar Position* +- Added sub-model to calculate solar fluxes and diffuse fraction for cloudy conditions based on radiometer measurements (see SolarPosition::enableCloudCalibration()). +- Changed many variable names to make units more explicit. + +*Radiation* +- Added "ActiveGrow_LED_RedBloom" light to light spectral library. \ No newline at end of file diff --git a/doc/DoxygenLayout.xml b/doc/DoxygenLayout.xml index b9da29d6a..095e38543 100755 --- a/doc/DoxygenLayout.xml +++ b/doc/DoxygenLayout.xml @@ -6,7 +6,7 @@ - + diff --git a/doc/UserGuide.dox b/doc/UserGuide.dox index 65108d7d5..f65b22873 100755 --- a/doc/UserGuide.dox +++ b/doc/UserGuide.dox @@ -1,4 +1,4 @@ -/*! \mainpage Helios Documentation v1.3.13 +/*! \mainpage Helios Documentation v1.3.14


@@ -287,7 +287,7 @@ $ git pull */ -/*! \page API Using the Helios API +/*! \page API User/API Guide \tableofcontents @@ -1292,12 +1292,12 @@ $ git pull std::vector A; A.push_back(2.3); A.push_back(9.2); - context.setPrimitiveData(UUID,"somedataA",HELIOS_TYPE_FLOAT,A.size(),\&A[0]); + context.setPrimitiveData(UUID,"somedataA",HELIOS_TYPE_FLOAT,A.size(),&A[0]); float B[2]; B[0] = 2.3; B[1] = 9.2; - context.setPrimitiveData(UUID,"somedataB",HELIOS_TYPE_FLOAT,2,\&B[0]); + context.setPrimitiveData(UUID,"somedataB",HELIOS_TYPE_FLOAT,2,&B[0]); } diff --git a/doc/header.html b/doc/header.html index 19c25cc19..564486aea 100644 --- a/doc/header.html +++ b/doc/header.html @@ -40,7 +40,7 @@ Logo -
 v1.3.13 +
 v1.3.14
diff --git a/doc/html/CloudyFluxPartitioning.png b/doc/html/CloudyFluxPartitioning.png new file mode 100644 index 000000000..d1eb026e7 Binary files /dev/null and b/doc/html/CloudyFluxPartitioning.png differ diff --git a/doc/html/_a_p_i.html b/doc/html/_a_p_i.html index 5e0641af8..0ddb5e22a 100644 --- a/doc/html/_a_p_i.html +++ b/doc/html/_a_p_i.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
Assets.cpp
+
+
+
1
+
2
+
3#include "PlantArchitecture.h"
+
4
+
5using namespace helios;
+
6
+
7uint buildGenericLeafPrototype(helios::Context *context_ptr, uint subdivisions, const std::string &leaf_texture, float leaf_aspect_ratio, float midrib_fold_fraction, float x_curvature, float y_curvature, float petiole_roll, float wave_period, float wave_amplitude) {
+
8
+
9 // -- main leaf generation code -- //
+
10
+
11 std::vector<uint> UUIDs;
+
12
+
13 uint Nx = subdivisions; //number of leaf subdivisions in the x-direction (longitudinal)
+
14 uint Ny = ceil(leaf_aspect_ratio*float(Nx)); //number of leaf subdivisions in the y-direction (lateral)
+
15
+
16 if ( Ny % 2 != 0){ //Ny must be even
+
17 Ny = Ny + 1;
+
18 }
+
19
+
20 float dx = 1.f/float(Nx); //length of leaf subdivision in the x-direction
+
21 float dy = leaf_aspect_ratio/float(Ny); //length of leaf subdivision in the y-direction
+
22
+
23 for (int i = 0; i < Nx; i++) {
+
24 for (int j = 0; j < Ny; j++) {
+
25
+
26 float x = float(i) * dx; //x-coordinate of leaf subdivision
+
27 float y = float(j) * dy - 0.5f * leaf_aspect_ratio; //y-coordinate of leaf subdivision
+
28
+
29 //midrib leaf folding
+
30 float y_fold = cosf(0.5f*midrib_fold_fraction*M_PI)*y;
+
31 float y_fold_jplus = cosf(0.5f*midrib_fold_fraction*M_PI)*(y+dy);
+
32 float z_fold = sinf(0.5f*midrib_fold_fraction*M_PI)*fabs(y);
+
33 float z_fold_jplus = sinf(0.5f*midrib_fold_fraction*M_PI)*fabs(y+dy);
+
34
+
35 //x-curvature
+
36 float z_xcurve = x_curvature*powf(x,4);
+
37 float z_xcurve_iplus = x_curvature*powf(x+dx,4);
+
38
+
39 //y-curvature
+
40 float z_ycurve = y_curvature*powf(y/leaf_aspect_ratio,4);
+
41 float z_ycurve_jplus = y_curvature*powf((y+dy)/leaf_aspect_ratio,4);
+
42
+
43 //petiole roll
+
44 float z_petiole_0 = 0, z_petiole_1 = 0, z_petiole_2 = 0, z_petiole_3 = 0;
+
45 if( petiole_roll != 0.0f ) {
+
46 z_petiole_0 = fmin(0.1f, petiole_roll * powf(7.f * y / leaf_aspect_ratio, 4) * exp(-70.f * (x))) - 0.01 * petiole_roll / fabs(petiole_roll);
+
47 z_petiole_1 = fmin(0.1f, petiole_roll * powf(7.f * y / leaf_aspect_ratio, 4) * exp(-70.f * (x + dx))) - 0.01 * petiole_roll / fabs(petiole_roll);
+
48 z_petiole_2 = fmin(0.1f, petiole_roll * powf(7.f * (y + dy) / leaf_aspect_ratio, 4) * exp(-70.f * (x + dx))) - 0.01 * petiole_roll / fabs(petiole_roll);
+
49 z_petiole_3 = fmin(0.1f, petiole_roll * powf(7.f * (y + dy) / leaf_aspect_ratio, 4) * exp(-70.f * (x))) - 0.01 * petiole_roll / fabs(petiole_roll);
+
50 }
+
51
+
52 //vertical displacement for leaf wave at each of the four subdivision vertices
+
53 float z_wave_0 = 0, z_wave_1 = 0, z_wave_2 = 0, z_wave_3 = 0;
+
54 if( wave_period > 0.0f && wave_amplitude > 0.0f ) {
+
55 z_wave_0 = (2.f * fabs(y) * wave_amplitude * sinf((x + 0.5f * float(j >= 0.5 * Ny)) * M_PI / wave_period));
+
56 z_wave_1 = (2.f * fabs(y) * wave_amplitude * sinf((x + 0.5f * float(j >= 0.5 * Ny) + dx) * M_PI / wave_period));
+
57 z_wave_2 = (2.f * fabs(y + dy) * wave_amplitude * sinf((x + 0.5f * float(j >= 0.5 * Ny) + dx) * M_PI / wave_period));
+
58 z_wave_3 = (2.f * fabs(y + dy) * wave_amplitude * sinf((x + 0.5f * float(j >= 0.5 * Ny)) * M_PI / wave_period));
+
59 }
+
60
+
61 //define the four vertices of the leaf subdivision
+
62 vec3 v0(x, y_fold, z_fold+z_xcurve+z_ycurve+z_wave_0+z_petiole_0);
+
63
+
64 vec3 v1(x + dx, y_fold, z_fold+z_xcurve_iplus+z_ycurve+z_wave_1+z_petiole_1);
+
65
+
66 vec3 v2(x + dx, y_fold_jplus, z_fold_jplus+z_xcurve_iplus+z_ycurve_jplus+z_wave_2+z_petiole_2);
+
67
+
68 vec3 v3(x, y_fold_jplus, z_fold_jplus+z_xcurve+z_ycurve_jplus+z_wave_3+z_petiole_3);
+
69
+
70 vec2 uv0(x, (y+0.5f*leaf_aspect_ratio) / leaf_aspect_ratio);
+
71 vec2 uv1(x + dx, (y+0.5f*leaf_aspect_ratio) / leaf_aspect_ratio);
+
72 vec2 uv2(x + dx, (y + dy + 0.5f*leaf_aspect_ratio) / leaf_aspect_ratio);
+
73 vec2 uv3(x, (y + dy + 0.5f*leaf_aspect_ratio) / leaf_aspect_ratio);
+
74
+
75 UUIDs.push_back(context_ptr->addTriangle(v0, v1, v2, leaf_texture.c_str(), uv0, uv1, uv2));
+
76 UUIDs.push_back(context_ptr->addTriangle(v0, v2, v3, leaf_texture.c_str(), uv0, uv2, uv3));
+
77
+
78 }
+
79 }
+
80
+
81 return context_ptr->addPolymeshObject( UUIDs );
+
82}
+
83
+
84uint AlmondLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
85 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AlmondLeaf.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
+
86 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
87 return objID;
+
88}
+
89
+
90uint AlmondFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set ){
+
91 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AlmondHull.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
92 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
93 return objID;
+
94}
+
95
+
96uint AlmondFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
+
97 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AlmondFlower.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
98 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
99 return objID;
+
100}
+
101
+
102void AlmondPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age ) {
+
103
+
104 if( phytomer->internode_length_max < 0.01 ){ //spurs
+
105 phytomer->setInternodeMaxRadius( 0.005 );
+
106 phytomer->setVegetativeBudState( BUD_DEAD );
+
107 phytomer->scaleLeafPrototypeScale( 0.7 );
+
108 //\todo Need to kill axillary buds here, but need to separate axillary and terminal buds
+
109 }
+
110
+
111}
+
112
+
113uint BeanLeafPrototype_unifoliate(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
114 std::string leaf_texture = "plugins/plantarchitecture/assets/textures/BeanLeaf_unifoliate.png";
+
115
+
116 float leaf_aspect = 0.8; //ratio of leaf width to leaf length
+
117
+
118 float midrib_fold = 0.2; //fraction of folding along midrib (=0 leaf is flat, =1 leaf is completely folded in half)
+
119
+
120 float x_curvature = -0.2; //curvature factor along x-direction. (+curves upward, -curved downward)
+
121
+
122 float y_curvature = -0.1; //curvature factor along y-direction. (+curves upward, -curved downward)
+
123
+
124 return buildGenericLeafPrototype(context_ptr, subdivisions, leaf_texture, leaf_aspect, midrib_fold, x_curvature, y_curvature, 0, 0, 0);
+
125
+
126}
+
127
+
128uint BeanLeafPrototype_trifoliate(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
129 std::string leaf_texture;
+
130 if( compound_leaf_index==0 ){
+
131 leaf_texture = "plugins/plantarchitecture/assets/textures/BeanLeaf_tip.png";
+
132 }else if( compound_leaf_index<0 ){
+
133 leaf_texture = "plugins/plantarchitecture/assets/textures/BeanLeaf_left.png";
+
134 }else{
+
135 leaf_texture = "plugins/plantarchitecture/assets/textures/BeanLeaf_right.png";
+
136 }
+
137
+
138
+
139 float leaf_aspect = 1.0; //ratio of leaf width to leaf length
+
140
+
141 float midrib_fold = 0.2; //fraction of folding along midrib (=0 leaf is flat, =1 leaf is completely folded in half)
+
142
+
143 float x_curvature = context_ptr->randu(-0.25f,-0.01f); //curvature factor along x-direction. (+curves upward, -curved downward)
+
144
+
145 float y_curvature = -0.2; //curvature factor along y-direction. (+curves upward, -curved downward)
+
146
+
147 return buildGenericLeafPrototype(context_ptr, subdivisions, leaf_texture, leaf_aspect, midrib_fold, x_curvature, y_curvature, 0, 0, 0);
+
148
+
149}
+
150
+
151uint BeanLeafPrototype_unifoliate_OBJ(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
152 std::vector<uint> UUIDs;
+
153 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/BeanLeaf_unifoliate.obj", true );
+
154
+
155 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
156 return objID;
+
157}
+
158
+
159uint BeanLeafPrototype_trifoliate_OBJ(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
160 std::vector<uint> UUIDs;
+
161 if( compound_leaf_index==0 ){
+
162 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/BeanLeaf_tip.obj", true );
+
163 }else if( compound_leaf_index<0 ){
+
164 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/BeanLeaf_left.obj", true );
+
165 }else{
+
166 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/BeanLeaf_right.obj", true );
+
167 }
+
168 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
169 return objID;
+
170}
+
171
+
172uint BeanFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set ){
+
173 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/BeanPod.obj", true );
+
174 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
175 return objID;
+
176}
+
177
+
178uint BeanFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
+
179 std::vector<uint> UUIDs;
+
180 if( flower_is_open ){
+
181 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/BeanFlower_open_white.obj", true );
+
182 }else{
+
183 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/BeanFlower_closed_white.obj", true );
+
184 }
+
185 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
186 return objID;
+
187}
+
188
+
189void BeanPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age ){
+
190
+
191 if( shoot_node_index>10 || rank>1 ) {
+
192 phytomer->setVegetativeBudState(BUD_DEAD);
+
193 }
+
194 if( shoot_node_index<=1 || shoot_node_index > 15){
+
195 phytomer->setFloralBudState( BUD_DEAD );
+
196 }
+
197
+
198 //set leaf and internode scale based on position along the shoot
+
199 float leaf_scale = fmin(1.f, 0.3 + 0.7 * plant_age / 10.f);
+
200 phytomer->scaleLeafPrototypeScale(leaf_scale);
+
201
+
202 //set internode length based on position along the shoot
+
203 float inode_scale = fmin(1.f, 0.2 + 0.8 * plant_age / 10.f);
+
204 phytomer->scaleInternodeMaxLength(inode_scale);
+
205
+
206}
+
207
+
208uint BindweedLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
209 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/BindweedLeaf.obj", true );
+
210 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
211 return objID;
+
212}
+
213
+
214uint BindweedFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
+
215 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/BindweedFlower.obj", true );
+
216 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
217 return objID;
+
218}
+
219
+
220uint CheeseweedLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
221 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CheeseweedLeaf.obj", true );
+
222 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
223 return objID;
+
224}
+
225
+
226uint CowpeaLeafPrototype_unifoliate(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
227 std::string leaf_texture = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_unifoliate.png";
+
228
+
229 float leaf_aspect = 0.8; //ratio of leaf width to leaf length
+
230
+
231 float midrib_fold = 0.2; //fraction of folding along midrib (=0 leaf is flat, =1 leaf is completely folded in half)
+
232
+
233 float x_curvature = -0.2; //curvature factor along x-direction. (+curves upward, -curved downward)
+
234
+
235 float y_curvature = -0.1; //curvature factor along y-direction. (+curves upward, -curved downward)
+
236
+
237 return buildGenericLeafPrototype(context_ptr, subdivisions, leaf_texture, leaf_aspect, midrib_fold, x_curvature, y_curvature, 0, 0, 0);
+
238
+
239}
+
240
+
241uint CowpeaLeafPrototype_trifoliate(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
242 std::string leaf_texture;
+
243 if( compound_leaf_index==0 ){
+
244 leaf_texture = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_tip_centered.png";
+
245 }else if( compound_leaf_index<0 ){
+
246 leaf_texture = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_left.png";
+
247 }else{
+
248 leaf_texture = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_right.png";
+
249 }
+
250
+
251 float leaf_aspect = 0.8; //ratio of leaf width to leaf length
+
252
+
253 float midrib_fold = 0.2; //fraction of folding along midrib (=0 leaf is flat, =1 leaf is completely folded in half)
+
254
+
255 float x_curvature = context_ptr->randu(-0.25f,-0.01f); //curvature factor along x-direction. (+curves upward, -curved downward)
+
256
+
257 float y_curvature = -0.2; //curvature factor along y-direction. (+curves upward, -curved downward)
+
258
+
259 return buildGenericLeafPrototype(context_ptr, subdivisions, leaf_texture, leaf_aspect, midrib_fold, x_curvature, y_curvature, 0, 0, 0);
+
260
+
261}
+
262
+
263uint CowpeaLeafPrototype_unifoliate_OBJ(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
264 std::vector<uint> UUIDs;
+
265 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaLeaf_unifoliate.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
+
266
+
267 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
268 return objID;
+
269}
+
270
+
271uint CowpeaLeafPrototype_trifoliate_OBJ(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
272 std::vector<uint> UUIDs;
+
273 if( compound_leaf_index<0 ){
+
274 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaLeaf_left_highres.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
+
275 }else if( compound_leaf_index==0 ){
+
276 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaLeaf_tip_highres.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
+
277 }else{
+
278 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaLeaf_right_highres.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
+
279 }
+
280 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
281 return objID;
+
282}
+
283
+
284uint CowpeaFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set ){
+
285 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaPod.obj", make_vec3(0.,0,0), 0.75,nullrotation, RGB::black, "ZUP", true );
+
286 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
287 return objID;
+
288}
+
289
+
290uint CowpeaFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
+
291 std::vector<uint> UUIDs;
+
292 if( flower_is_open ){
+
293 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaFlower_open_yellow.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
294 }else{
+
295 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaFlower_closed_yellow.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
296 }
+
297 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
298 return objID;
+
299}
+
300
+
301void CowpeaPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age ){
+
302
+
303 if( shoot_node_index>5 || rank>1 ) {
+
304 phytomer->setVegetativeBudState(BUD_DEAD);
+
305 }else{
+
306 phytomer->setFloralBudState( BUD_DEAD );
+
307 }
+
308
+
309 //set leaf and internode scale based on position along the shoot
+
310 float leaf_scale = fmin(1.f, 0.2 + 0.8 * plant_age / 15.f);
+
311 phytomer->scaleLeafPrototypeScale(leaf_scale);
+
312
+
313 //set internode length based on position along the shoot
+
314 float inode_scale = fmin(1.f, 0.2 + 0.8 * plant_age / 15.f);
+
315 phytomer->scaleInternodeMaxLength(inode_scale);
+
316
+
317}
+
318
+
319uint PuncturevineLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
320
+
321 std::string leaf_texture = "plugins/plantarchitecture/assets/textures/PuncturevineLeaf.png";
+
322
+
323 float leaf_aspect = 0.4; //ratio of leaf width to leaf length
+
324
+
325 float midrib_fold = 0.2; //fraction of folding along midrib (=0 leaf is flat, =1 leaf is completely folded in half)
+
326
+
327 float x_curvature = -0.1; //curvature factor along x-direction. (+curves upward, -curved downward)
+
328
+
329 float y_curvature = 0.4; //curvature factor along y-direction. (+curves upward, -curved downward)
+
330
+
331 return buildGenericLeafPrototype(context_ptr, subdivisions, leaf_texture, leaf_aspect, midrib_fold, x_curvature, y_curvature, 0, 0, 0);
+
332
+
333}
+
334
+
335uint PuncturevineFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
+
336 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/PuncturevineFlower.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
337 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
338 return objID;
+
339}
+
340
+
341uint RedbudLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
342 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/RedbudLeaf.obj", make_vec3(0.,0,0), 0.75,nullrotation, RGB::black, "ZUP", true );
+
343 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
344 return objID;
+
345}
+
346
+
347uint RedbudFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
+
348 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/RedbudFlower_open.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
349 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
350 return objID;
+
351}
+
352
+
353uint RedbudFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set ){
+
354 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/RedbudPod.obj", make_vec3(0.,0,0), 0.75,nullrotation, RGB::black, "ZUP", true );
+
355 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
356 return objID;
+
357}
+
358
+
359void RedbudPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age ){
+
360
+
361// //remove all vegetative buds
+
362// phytomer->setVegetativeBudState( BUD_DEAD );
+
363//
+
364// //remove all floral buds except for the terminal one
+
365// if( shoot_node_index < shoot_max_nodes-1 ){
+
366// phytomer->setFloralBudState( BUD_DEAD );
+
367// }
+
368
+
369}
+
370
+
371uint SorghumLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
372
+
373 std::string leaf_texture = "plugins/plantarchitecture/assets/textures/SorghumLeaf.png";
+
374
+
375 float leaf_aspect = 0.25; //ratio of leaf width to leaf length
+
376
+
377 float midrib_fold_fraction = 0.3;
+
378
+
379 float x_curvature = context_ptr->randu(-0.9f,-0.6f);
+
380 float y_curvature = -0.3;
+
381
+
382 float petiole_roll = 0.04f;
+
383
+
384 //parameters for leaf wave/wrinkles
+
385 float wave_period = 0.1f; //period factor of leaf waves
+
386 float wave_amplitude = 0.035f; // amplitude of leaf waves
+
387
+
388 return buildGenericLeafPrototype(context_ptr, subdivisions, leaf_texture, leaf_aspect, midrib_fold_fraction, x_curvature, y_curvature, petiole_roll, wave_period, wave_amplitude);
+
389
+
390}
+
391
+
392uint SorghumPaniclePrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set ){
+
393
+
394 if( subdivisions<=1 ){
+
395 subdivisions = 3;
+
396 }
+
397
+
398 float panicle_height = 1;
+
399 float panicle_width = 0.25;
+
400 float width_seed = 0.1;
+
401 float height_seed = 0.3;
+
402 float seed_tilt = 50;
+
403
+
404 std::string seed_texture_file = "plugins/plantarchitecture/assets/textures/SorghumSeed.png";
+
405 RGBcolor stem_color(0.45,0.55,0.42);
+
406
+
407 std::vector<uint> UUIDs;
+
408
+
409 panicle_height -= 0.8*height_seed;
+
410
+
411 std::vector<vec3> nodes_panicle;
+
412 std::vector<float> radius_panicle;
+
413
+
414 for (int n = 0; n < subdivisions ; n++) {
+
415 float x = 0;
+
416 float y = 0;
+
417 float z;
+
418 if( n==0 ){
+
419 z = 0.5f*height_seed/float(subdivisions-1);
+
420 }else if( n==subdivisions-1 ){
+
421 z = (subdivisions-1.5f)*height_seed/float(subdivisions-1);
+
422 }else{
+
423 z = n*height_seed/float(subdivisions-1);
+
424 }
+
425
+
426 float angle = n * M_PI /float(subdivisions-1);
+
427 float dr = 0.5f * width_seed * sin(angle);
+
428
+
429 nodes_panicle.push_back(make_vec3(x, y, z));
+
430 radius_panicle.push_back(dr);
+
431
+
432 }
+
433
+
434 std::vector<uint> UUIDs_seed_ptype = context_ptr->addTube( subdivisions, nodes_panicle, radius_panicle,seed_texture_file.c_str());
+
435
+
436 int Ntheta = ceil( 3.f*panicle_height/height_seed );
+
437 int Nphi = ceil( 2.f*M_PI*panicle_width/width_seed);
+
438
+
439 for(int j=0; j < Nphi; j++ ) {
+
440 for (int i = 0; i < Ntheta; i++) {
+
441
+
442 if( i==0 && j==0 ){
+
443 continue;
+
444 }
+
445
+
446 std::vector<uint> UUIDs_copy = context_ptr->copyPrimitive(UUIDs_seed_ptype);
+
447
+
448 float phi = 2.f * M_PI * float(j + 0.5f*float(i%2)) / float(Nphi);
+
449 float theta = acos(1 - 2 * float(i + float(j)/float(Nphi)) / float(Ntheta));
+
450 float x = sin(theta) * cos(phi);
+
451 float y = sin(theta) * sin(phi);
+
452 float z = 0.5f + 0.5f*cos(theta);
+
453
+
454 x *= 0.5f * panicle_width;
+
455 y *= 0.5f * panicle_width;
+
456 z *= panicle_height;
+
457
+
458 float tilt = - deg2rad(seed_tilt) * sqrtf(1.f - z / panicle_height);
+
459
+
460 context_ptr->rotatePrimitive(UUIDs_copy, tilt, "x");
+
461 context_ptr->rotatePrimitive(UUIDs_copy, phi - 0.5f * M_PI, "z");
+
462
+
463 context_ptr->translatePrimitive(UUIDs_copy, make_vec3(x, y, z));
+
464 UUIDs.insert(UUIDs.end(), UUIDs_copy.begin(), UUIDs_copy.end());
+
465
+
466 }
+
467 }
+
468
+
469 context_ptr->deletePrimitive(UUIDs_seed_ptype);
+
470
+
471 std::vector<vec3> stem_nodes;
+
472 std::vector<float> stem_radius;
+
473 std::vector<RGBcolor> stem_colors;
+
474 for(int i=0; i<subdivisions; i++){
+
475 stem_nodes.push_back(make_vec3(0,0, float(i)/float(subdivisions-1)*panicle_height*0.75f) );
+
476 stem_radius.push_back(0.25f*panicle_width);
+
477 stem_colors.push_back(stem_color);
+
478 }
+
479
+
480 std::vector<uint> UUIDS_stem = context_ptr->addTube( subdivisions, stem_nodes, stem_radius, stem_colors);
+
481 UUIDs.insert(UUIDs.end(), UUIDS_stem.begin(), UUIDS_stem.end());
+
482
+
483// context_ptr->translatePrimitive(UUIDs, make_vec3(0,0,-0.3f*panicle_height) );
+
484 context_ptr->rotatePrimitive(UUIDs, 0.5f*M_PI, "y");
+
485
+
486 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
487 return objID;
+
488}
+
489
+
490void SorghumPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age ){
+
491
+
492 //set leaf scale based on position along the shoot
+
493 float scale = fmin(1.f, 0.5 + 0.5*float(shoot_node_index)/5.f);
+
494 phytomer->scaleLeafPrototypeScale(scale);
+
495
+
496 //set internode length based on position along the shoot
+
497 phytomer->scaleInternodeMaxLength(scale);
+
498
+
499 //remove all vegetative buds
+
500 phytomer->setVegetativeBudState( BUD_DEAD );
+
501
+
502 //remove all floral buds except for the terminal one
+
503 if( shoot_node_index < shoot_max_nodes-1 ){
+
504 phytomer->setFloralBudState( BUD_DEAD );
+
505 }
+
506
+
507}
+
508
+
509uint SoybeanLeafPrototype_trifoliate(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
510// std::vector<uint> UUIDs;
+
511// UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/SoybeanLeaf.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
+
512// uint objID = context_ptr->addPolymeshObject( UUIDs );
+
513// return objID;
+
514
+
515 std::string leaf_texture = "plugins/plantarchitecture/assets/textures/SoybeanLeaf.png";
+
516
+
517 float leaf_aspect = 1.0; //ratio of leaf width to leaf length
+
518
+
519 float midrib_fold = 0.1; //fraction of folding along midrib (=0 leaf is flat, =1 leaf is completely folded in half)
+
520
+
521 float x_curvature = context_ptr->randu(-0.2f,0.f); //curvature factor along x-direction. (+curves upward, -curved downward)
+
522
+
523 float y_curvature = -0.15; //curvature factor along y-direction. (+curves upward, -curved downward)
+
524
+
525 return buildGenericLeafPrototype(context_ptr, subdivisions, leaf_texture, leaf_aspect, midrib_fold, x_curvature, y_curvature, 0, 0, 0);
+
526
+
527}
+
528
+
529uint SoybeanLeafPrototype_unifoliate(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
530 return SoybeanLeafPrototype_trifoliate(context_ptr, subdivisions, compound_leaf_index, shoot_node_index, shoot_max_nodes); //\todo Add separate model for unifoliate leaves
+
531}
+
532
+
533uint SoybeanFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set ){
+
534 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/SoybeanPod.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
535 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
536 return objID;
+
537}
+
538
+
539uint SoybeanFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
+
540 std::vector<uint> UUIDs;
+
541 if( flower_is_open ){
+
542 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/SoybeanFlower_open_white.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
543 }else{
+
544 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/BeanFlower_closed_white.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
545 }
+
546 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
547 return objID;
+
548}
+
549
+
550void SoybeanPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age ){
+
551
+
552 if( shoot_node_index>10 || rank>1 ) {
+
553 phytomer->setVegetativeBudState(BUD_DEAD);
+
554 }
+
555 if( shoot_node_index<=0 || shoot_node_index > 15){
+
556 phytomer->setFloralBudState( BUD_DEAD );
+
557 }
+
558
+
559 //set leaf and internode scale based on position along the shoot
+
560 float leaf_scale = fmin(1.f, 0.2 + 0.8 * plant_age / 5.f);
+
561 phytomer->scaleLeafPrototypeScale(leaf_scale);
+
562
+
563 //set internode length based on position along the shoot
+
564 float inode_scale = fmin(1.f, 0.75 + 0.25 * plant_age / 5.f);
+
565 phytomer->scaleInternodeMaxLength(inode_scale);
+
566
+
567}
+
568
+
569uint StrawberryLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
570
+
571 std::string leaf_texture = "plugins/plantarchitecture/assets/textures/StrawberryLeaf.png";
+
572
+
573 float leaf_aspect = 1.0; //ratio of leaf width to leaf length
+
574
+
575 float midrib_fold_fraction = 0.2;
+
576
+
577 float x_curvature = -0.01;
+
578 float y_curvature = -0.2;
+
579
+
580 float petiole_roll = 0.05f;
+
581
+
582 //parameters for leaf wave/wrinkles
+
583 float wave_period = 0.f; //period factor of leaf waves
+
584 float wave_amplitude = 0.0f; // amplitude of leaf waves
+
585
+
586 return buildGenericLeafPrototype(context_ptr, subdivisions, leaf_texture, leaf_aspect, midrib_fold_fraction, x_curvature, y_curvature, petiole_roll, wave_period, wave_amplitude);
+
587
+
588}
+
589
+
590uint StrawberryFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
+
591 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/StrawberryFlower.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
592 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
593 return objID;
+
594}
+
595
+
596uint StrawberryFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set ){
+
597 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/StrawberryFruit.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
598 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
599 return objID;
+
600}
+
601
+
602uint SugarbeetLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
603
+
604 std::string leaf_texture = "plugins/plantarchitecture/assets/textures/SugarbeetLeaf.png";
+
605
+
606 float leaf_aspect = 0.4; //ratio of leaf width to leaf length
+
607
+
608 float midrib_fold = 0.1; //fraction of folding along midrib (=0 leaf is flat, =1 leaf is completely folded in half)
+
609
+
610 float x_curvature = -0.2; //curvature factor along x-direction. (+curves upward, -curved downward)
+
611
+
612 float y_curvature = 0.4; //curvature factor along y-direction. (+curves upward, -curved downward)
+
613
+
614 float petiole_roll = 0.75; //add a small radius roll at the based of the leaf to better mate with the petiole. Value is the magnitude of the roll (+rolls upward, - rolls downward)
+
615
+
616 //parameters for leaf wave/wrinkles
+
617 float wave_period = context_ptr->randu( 0.08f, 0.15f); //period factor of leaf waves
+
618 float wave_amplitude = context_ptr->randu(0.02f,0.04f); // amplitude of leaf waves
+
619
+
620 return buildGenericLeafPrototype(context_ptr, subdivisions, leaf_texture, leaf_aspect, midrib_fold, x_curvature, y_curvature, petiole_roll, wave_period, wave_amplitude);
+
621
+
622}
+
623
+
624uint TomatoLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
625// std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/TomatoLeaf.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
+
626// uint objID = context_ptr->addPolymeshObject( UUIDs );
+
627// return objID;
+
628
+
629 std::string leaf_texture = "plugins/plantarchitecture/assets/textures/TomatoLeaf_centered.png";
+
630
+
631 float leaf_aspect = 0.5; //ratio of leaf width to leaf length
+
632
+
633 float midrib_fold = 0.1; //fraction of folding along midrib (=0 leaf is flat, =1 leaf is completely folded in half)
+
634
+
635 float x_curvature = context_ptr->randu(-0.45f,-0.2f); //curvature factor along x-direction. (+curves upward, -curved downward)
+
636
+
637 float y_curvature = -0.3; //curvature factor along y-direction. (+curves upward, -curved downward)
+
638
+
639 //parameters for leaf wave/wrinkles
+
640 float wave_period = 0.2f; //period factor of leaf waves
+
641 float wave_amplitude = 0.03f; // amplitude of leaf waves
+
642
+
643 return buildGenericLeafPrototype(context_ptr, subdivisions, leaf_texture, leaf_aspect, midrib_fold, x_curvature, y_curvature, 0, wave_period, wave_amplitude);
+
644
+
645}
+
646
+
647uint TomatoFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set ){
+
648 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/TomatoFruit.obj", make_vec3(0.,0,0), 0.75,nullrotation, RGB::black, "ZUP", true );
+
649 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
650 return objID;
+
651}
+
652
+
653uint TomatoFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
+
654 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/TomatoFlower.obj", make_vec3(0.0,0,0), 0.75,nullrotation, RGB::black, "ZUP", true );
+
655 uint objID = context_ptr->addPolymeshObject( UUIDs );
+
656 return objID;
+
657}
+
658
+
659void TomatoPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age ){
+
660
+
661 if( shoot_node_index>5 || rank>1 ) {
+
662 phytomer->setVegetativeBudState(BUD_DEAD);
+
663 }
+
664
+
665 //set leaf and internode scale based on position along the shoot
+
666 float leaf_scale = fmin(1.f, 0.5 + 0.5 * plant_age / 10.f);
+
667 phytomer->scaleLeafPrototypeScale(leaf_scale);
+
668
+
669 //set internode length based on position along the shoot
+
670 float inode_scale = fmin(1.f, 0.7 + 0.3 * plant_age / 10.f);
+
671 phytomer->scaleInternodeMaxLength(inode_scale);
+
672
+
673}
+ +
Stores the state associated with simulation.
Definition: Context.h:1705
+
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition: Context.cpp:1349
+
void deletePrimitive(uint UUID)
Delete a single primitive from the context.
Definition: Context.cpp:1442
+
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition: Context.cpp:1121
+
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition: Context.cpp:1363
+
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition: Context.cpp:1484
+
std::vector< uint > loadOBJ(const char *filename, bool silent=false)
Load geometry contained in a Wavefront OBJ file (.obj). Model will be placed at the origin without an...
+
uint addPolymeshObject(const std::vector< uint > &UUIDs)
Add new Polymesh Compound Object.
Definition: Context.cpp:4756
+
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition: Context.cpp:5304
+
float deg2rad(float deg)
Convert degrees to radians.
Definition: global.cpp:547
+
uint addTriangle(const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2)
Add new Triangle geometric primitive.
Definition: Context.cpp:1271
+
vec3 make_vec3(float X, float Y, float Z)
Make a vec3 from three floats.
+
R-G-B color vector.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
+
+ + + + diff --git a/doc/html/_assets_8h_source.html b/doc/html/_assets_8h_source.html new file mode 100644 index 000000000..f18ffd15c --- /dev/null +++ b/doc/html/_assets_8h_source.html @@ -0,0 +1,168 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
Assets.h
+
+
+
1
+
2#ifndef HELIOS_ASSETS_H
+
3#define HELIOS_ASSETS_H
+
4
+
5#include "PlantArchitecture.h"
+
6
+
7uint buildGenericLeafPrototype(helios::Context *context_ptr, uint subdivisions, const std::string &leaf_texture, float leaf_aspect_ratio, float midrib_fold_fraction, float x_curvature, float y_curvature, float petiole_roll, float wave_period, float wave_amplitude);
+
8
+
9uint AlmondLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
10uint AlmondFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set );
+
11uint AlmondFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open=false );
+
12void AlmondPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age );
+
13
+
14uint BeanLeafPrototype_unifoliate(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
15uint BeanLeafPrototype_trifoliate(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
16uint BeanLeafPrototype_unifoliate_OBJ(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
17uint BeanLeafPrototype_trifoliate_OBJ(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
18uint BeanFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set );
+
19uint BeanFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open=false );
+
20void BeanPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age );
+
21
+
22uint BindweedLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes0 );
+
23uint BindweedFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open=false );
+
24
+
25uint CheeseweedLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
26
+
27uint CowpeaLeafPrototype_unifoliate(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
28uint CowpeaLeafPrototype_trifoliate(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
29uint CowpeaLeafPrototype_unifoliate_OBJ(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
30uint CowpeaLeafPrototype_trifoliate_OBJ(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
31uint CowpeaFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set );
+
32uint CowpeaFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open=false );
+
33void CowpeaPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age );
+
34
+
35uint PuncturevineLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
36uint PuncturevineFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open=false );
+
37
+
38uint RedbudLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
39uint RedbudFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open=false );
+
40uint RedbudFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set );
+
41void RedbudPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age );
+
42
+
43uint SorghumLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
44uint SorghumPaniclePrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set );
+
45void SorghumPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age );
+
46
+
47uint SoybeanLeafPrototype_unifoliate(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
48uint SoybeanLeafPrototype_trifoliate(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
49uint SoybeanFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set );
+
50uint SoybeanFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open=false );
+
51void SoybeanPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age );
+
52
+
53uint StrawberryLeafPrototype(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
54uint StrawberryFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set );
+
55uint StrawberryFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open=false );
+
56void StrawberryPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age );
+
57
+
58uint SugarbeetLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
59
+
60uint TomatoLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes );
+
61uint TomatoFruitPrototype( helios::Context* context_ptr, uint subdivisions, float time_since_fruit_set );
+
62uint TomatoFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open=false );
+
63void TomatoPhytomerCreationFunction( std::shared_ptr<Phytomer> phytomer, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age );
+
64
+
65#endif //HELIOS_ASSETS_H
+ +
Stores the state associated with simulation.
Definition: Context.h:1705
+
+ + + + diff --git a/doc/html/_b_l_conductance_doc.html b/doc/html/_b_l_conductance_doc.html index 7c77da651..e9235f64e 100644 --- a/doc/html/_b_l_conductance_doc.html +++ b/doc/html/_b_l_conductance_doc.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + - - - - - - - - - - - - - -
-
- - - - - - - -
-
 v1.3.13 -
-
-
- - - - - - - -
-
- - -
-
-
-
-
-
Loading...
-
Searching...
-
No Matches
-
-
-
-
- - -
-
-
Context (Bailey-L2m's conflicted copy 2024-06-08).h
-
-
-
1
-
16#ifndef HELIOS_CONTEXT
-
17#define HELIOS_CONTEXT
-
18
-
19#include <utility>
-
20
-
21#include "global.h"
-
22
-
24
-
26namespace helios {
-
27
-
28class Context; //forward declaration of Context class
-
29
-
31enum PrimitiveType{
-
33 PRIMITIVE_TYPE_PATCH = 0,
-
35 PRIMITIVE_TYPE_TRIANGLE = 1,
-
37 PRIMITIVE_TYPE_VOXEL = 2
-
38};
-
39
-
41enum HeliosDataType{
-
43 HELIOS_TYPE_INT = 0,
-
45 HELIOS_TYPE_UINT = 1,
-
47 HELIOS_TYPE_FLOAT = 2,
-
49 HELIOS_TYPE_DOUBLE = 3,
-
51 HELIOS_TYPE_VEC2 = 4,
-
53 HELIOS_TYPE_VEC3 = 5,
-
55 HELIOS_TYPE_VEC4 = 6,
-
57 HELIOS_TYPE_INT2 = 7,
-
59 HELIOS_TYPE_INT3 = 8,
-
61 HELIOS_TYPE_INT4 = 9,
-
63 HELIOS_TYPE_STRING = 10,
-
64};
-
65
-
67class Texture{
-
68public:
-
69
-
70 Texture()= default;
-
71
-
73
-
75 explicit Texture( const char* texture_file );
-
76
-
78 std::string getTextureFile() const;
-
79
-
81 helios::int2 getSize() const;
-
82
-
84 bool hasTransparencyChannel() const;
-
85
-
87 const std::vector<std::vector<bool> >* getTransparencyData() const;
-
88
-
90 float getSolidFraction() const;
-
91
-
92private:
-
93 std::string filename;
-
94 bool hastransparencychannel{};
-
95 std::vector<std::vector<bool> > transparencydata;
-
96 float solidfraction{};
-
97};
-
98
- -
101
-
102 std::vector<int> global_data_int;
-
103 std::vector<uint> global_data_uint;
-
104 std::vector<float> global_data_float;
-
105 std::vector<double> global_data_double;
-
106 std::vector<vec2> global_data_vec2;
-
107 std::vector<vec3> global_data_vec3;
-
108 std::vector<vec4> global_data_vec4;
-
109 std::vector<int2> global_data_int2;
-
110 std::vector<int3> global_data_int3;
-
111 std::vector<int4> global_data_int4;
-
112 std::vector<std::string> global_data_string;
-
113 std::vector<bool> global_data_bool;
-
114
-
115 size_t size;
-
116 HeliosDataType type;
-
117
-
118};
-
119
-
120//--------------------- GEOMETRIC PRIMITIVES -----------------------------------//
-
121
-
122
-
123//---------- COMPOUND OBJECTS ----------------//
-
124
-
126enum ObjectType{
-
128 OBJECT_TYPE_TILE = 0,
-
130 OBJECT_TYPE_SPHERE = 1,
-
132 OBJECT_TYPE_TUBE = 2,
-
134 OBJECT_TYPE_BOX = 3,
-
136 OBJECT_TYPE_DISK = 4,
-
138 OBJECT_TYPE_POLYMESH = 5,
-
140 OBJECT_TYPE_CONE = 6,
-
141};
-
142
- -
144public:
-
145
-
146 virtual ~CompoundObject()= default;
-
147
-
149 uint getObjectID() const;
-
150
-
152 helios::ObjectType getObjectType() const;
-
153
-
155 uint getPrimitiveCount() const;
-
156
-
158 std::vector<uint> getPrimitiveUUIDs() const;
-
159
-
161 bool doesObjectContainPrimitive( uint UUID );
-
162
- -
165
-
167 float getArea() const;
-
168
-
170
-
172 void setColor( const helios::RGBcolor& color );
-
173
-
175
-
178 void setColor( const helios::RGBAcolor& color );
-
179
- -
182
-
184 void useTextureColor();
-
185
-
187 bool hasTexture( ) const;
-
188
-
190 std::string getTextureFile( ) const;
-
191
-
193
-
196 void translate( const helios::vec3& shift );
-
197
-
199
-
203 void rotate( float rot, const char* axis );
-
204
-
206
-
210 void rotate( float rot, const helios::vec3& axis );
-
211
-
212
-
214
-
219 void rotate( float rot, const helios::vec3& origin, const helios::vec3& axis );
-
220
-
222
-
225 void scale( const helios::vec3 &scale );
-
226
-
228
-
231 void getTransformationMatrix( float (&T)[16] ) const;
-
232
-
234
-
237 void setTransformationMatrix( float (&T)[16] );
-
238
-
240
-
243 void setPrimitiveUUIDs( const std::vector<uint> &UUIDs );
-
244
-
246
-
249 void deleteChildPrimitive( uint UUID );
-
250
-
252
-
255 void deleteChildPrimitive( const std::vector<uint> &UUIDs );
-
256
-
258
-
261 bool arePrimitivesComplete() const;
-
262
-
263 //-------- Object Data Methods ---------- //
-
264
-
266
-
270 void setObjectData( const char* label, const int& data );
-
271
-
273
-
277 void setObjectData( const char* label, const uint& data );
-
278
-
280
-
284 void setObjectData( const char* label, const float& data );
-
285
-
287
-
291 void setObjectData( const char* label, const double& data );
-
292
-
294
-
298 void setObjectData( const char* label, const helios::vec2& data );
-
299
-
301
-
305 void setObjectData( const char* label, const helios::vec3& data );
-
306
-
308
-
312 void setObjectData( const char* label, const helios::vec4& data );
-
313
-
315
-
319 void setObjectData( const char* label, const helios::int2& data );
-
320
-
322
-
326 void setObjectData( const char* label, const helios::int3& data );
-
327
-
329
-
333 void setObjectData( const char* label, const helios::int4& data );
-
334
-
336
-
340 void setObjectData( const char* label, const std::string& data );
-
341
-
343
-
350 void setObjectData( const char* label, HeliosDataType type, uint size, void* data );
-
351
-
353
-
357 void getObjectData( const char* label, int& data ) const;
-
358
-
360
-
364 void getObjectData( const char* label, std::vector<int>& data ) const;
-
365
-
367
-
371 void getObjectData( const char* label, uint& data ) const;
-
372
-
374
-
378 void getObjectData( const char* label, std::vector<uint>& data ) const;
-
379
-
381
-
385 void getObjectData( const char* label, float& data ) const;
-
386
-
388
-
392 void getObjectData( const char* label, std::vector<float>& data ) const;
-
393
-
395
-
399 void getObjectData( const char* label, double& data ) const;
-
400
-
402
-
406 void getObjectData( const char* label, std::vector<double>& data ) const;
-
407
-
409
-
413 void getObjectData( const char* label, vec2& data ) const;
-
414
-
416
-
420 void getObjectData( const char* label, std::vector<vec2>& data ) const;
-
421
-
423 void getObjectData( const char* label, vec3& data ) const;
-
424
-
426
-
430 void getObjectData( const char* label, std::vector<vec3>& data ) const;
-
432
-
436 void getObjectData( const char* label, vec4& data ) const;
-
438
-
442 void getObjectData( const char* label, std::vector<vec4>& data ) const;
-
444
-
448 void getObjectData( const char* label, int2& data ) const;
-
450
-
454 void getObjectData( const char* label, std::vector<int2>& data ) const;
-
456
-
460 void getObjectData( const char* label, int3& data ) const;
-
462
-
466 void getObjectData( const char* label, std::vector<int3>& data ) const;
-
468
-
472 void getObjectData( const char* label, int4& data ) const;
-
474
-
478 void getObjectData( const char* label, std::vector<int4>& data ) const;
-
480
-
484 void getObjectData( const char* label, std::string& data ) const;
-
486
-
490 void getObjectData( const char* label, std::vector<std::string>& data ) const;
-
491
-
493
-
498 HeliosDataType getObjectDataType( const char* label ) const;
-
499
-
501
-
505 uint getObjectDataSize( const char* label ) const;
-
506
-
508
-
512 bool doesObjectDataExist( const char* label ) const;
-
513
-
515
-
518 void clearObjectData( const char* label );
-
519
-
521 std::vector<std::string> listObjectData() const;
-
522
-
523protected:
-
524
-
526 uint OID;
-
527
-
529 helios::ObjectType type;
-
530
-
532 std::vector<uint> UUIDs;
-
533
-
535 helios::Context* context;
-
536
-
538 std::string texturefile;
-
539
-
541 float transform[16];
-
542
-
544 bool primitivesarecomplete = true;
-
545
-
546 std::map<std::string,HeliosDataType > object_data_types;
-
547 std::map<std::string, std::vector<int> > object_data_int;
-
548 std::map<std::string, std::vector<uint> > object_data_uint;
-
549 std::map<std::string, std::vector<float> > object_data_float;
-
550 std::map<std::string, std::vector<double> > object_data_double;
-
551 std::map<std::string, std::vector<vec2> > object_data_vec2;
-
552 std::map<std::string, std::vector<vec3> > object_data_vec3;
-
553 std::map<std::string, std::vector<vec4> > object_data_vec4;
-
554 std::map<std::string, std::vector<int2> > object_data_int2;
-
555 std::map<std::string, std::vector<int3> > object_data_int3;
-
556 std::map<std::string, std::vector<int4> > object_data_int4;
-
557 std::map<std::string, std::vector<std::string> > object_data_string;
-
558 std::map<std::string, std::vector<bool> > object_data_bool;
-
559
-
560};
-
561
-
563class Tile : public CompoundObject {
-
564public:
-
565
-
567 Tile(uint a_OID, const std::vector<uint> &a_UUIDs, const int2 &a_subdiv, const char *a_texturefile, helios::Context *a_context);
-
568
-
570 ~Tile() override = default;
-
571
-
573 helios::vec2 getSize() const;
-
574
-
576 vec3 getCenter() const;
-
577
- -
580
-
582
-
586 void setSubdivisionCount( const helios::int2 &subdiv );
-
587
-
589 std::vector<helios::vec3> getVertices() const;
-
590
-
592 vec3 getNormal() const;
-
593
-
595 std::vector<helios::vec2> getTextureUV() const;
-
596
-
597protected:
-
598
-
599 helios::int2 subdiv;
-
600
-
601};
-
602
-
604class Sphere : public CompoundObject {
-
605public:
-
606
-
608 Sphere(uint a_OID, const std::vector<uint> &a_UUIDs, uint a_subdiv, const char *a_texturefile, helios::Context *a_context);
-
609
-
611 ~Sphere() override = default;
-
612
-
614 helios::vec3 getRadius() const;
-
615
-
617 vec3 getCenter() const;
-
618
-
620 uint getSubdivisionCount() const;
-
621
-
623
-
626 void setSubdivisionCount(uint subdiv );
-
627
-
628protected:
-
629
-
630 uint subdiv;
-
631
-
632};
-
633
-
635class Tube: public CompoundObject {
-
636public:
-
637
-
639 Tube(uint a_OID, const std::vector<uint> &a_UUIDs, const std::vector<vec3> &a_nodes, const std::vector<float> &a_radius, const std::vector<helios::RGBcolor> &a_colors, uint a_subdiv, const char *a_texturefile, helios::Context *a_context);
-
640
-
642 ~Tube() override = default;
-
643
-
645 std::vector<helios::vec3> getNodes() const;
-
646
-
648 std::vector<float> getNodeRadii() const;
-
649
-
651 std::vector<helios::RGBcolor> getNodeColors() const;
-
652
-
654 uint getSubdivisionCount() const;
-
655
-
657
-
660 void setSubdivisionCount( uint subdiv );
-
661
-
662protected:
-
663
-
664 std::vector<helios::vec3> nodes;
-
665
-
666 std::vector<float> radius;
-
667
-
668 std::vector<helios::RGBcolor> colors;
-
669
-
670 uint subdiv;
-
671
-
672};
-
673
-
675class Box : public CompoundObject {
-
676public:
-
677
-
679 Box(uint a_OID, const std::vector<uint> &a_UUIDs, const int3 &a_subdiv, const char *a_texturefile, helios::Context *a_context);
-
680
-
682 ~Box() override = default;
-
683
-
685 vec3 getSize() const;
-
686
-
688 vec3 getCenter() const;
-
689
- -
692
-
694
-
697 void setSubdivisionCount( const helios::int3 &subdiv );
-
698
-
699protected:
-
700
-
701 helios::int3 subdiv;
-
702
-
703};
-
704
-
706class Disk : public CompoundObject {
-
707public:
-
708
-
710 Disk(uint a_OID, const std::vector<uint> &a_UUIDs, int2 a_subdiv, const char *a_texturefile, helios::Context *a_context);
-
711
-
713 ~Disk() override = default;
-
714
-
716 vec2 getSize() const;
-
717
-
719 vec3 getCenter() const;
-
720
- -
723
-
725
-
728 void setSubdivisionCount(int2 subdiv );
-
729
-
730protected:
-
731
-
732 int2 subdiv;
-
733
-
734};
-
735
-
737class Polymesh : public CompoundObject {
-
738public:
-
739
-
741 Polymesh(uint a_OID, const std::vector<uint> &a_UUIDs, const char *a_texturefile, helios::Context *a_context);
-
742
-
744 ~Polymesh() override = default;
-
745
-
746protected:
-
747
-
748
-
749};
-
750
-
752class Cone: public CompoundObject {
-
753public:
-
754
-
756 Cone(uint a_OID, const std::vector<uint> &a_UUIDs, const vec3 &a_node0, const vec3 &a_node1, float a_radius0, float a_radius1, uint a_subdiv, const char *a_texturefile, helios::Context *a_context);
-
757
-
759 ~Cone() override = default;
-
760
-
762
-
765 std::vector<helios::vec3> getNodeCoordinates() const;
-
766
-
768
-
772 helios::vec3 getNodeCoordinate(int node_index) const;
-
773
-
775
-
778 std::vector<float> getNodeRadii() const;
-
779
-
781
-
785 float getNodeRadius(int node_index) const;
-
786
-
788 uint getSubdivisionCount() const;
-
789
-
791
-
794 void setSubdivisionCount( uint subdiv );
-
795
- -
798
-
800 float getLength() const;
-
801
-
803
-
806 void scaleLength( float S );
-
807
-
809
-
812 void scaleGirth( float S );
-
813
-
814protected:
-
815
-
816 std::vector<helios::vec3> nodes;
-
817 std::vector<float> radii;
-
818
-
819 uint subdiv;
-
820
-
821};
-
822
-
823
-
825
-
829class Primitive{
-
830public:
-
831
-
833 virtual ~Primitive()= default;
-
834
-
836
-
839 uint getUUID() const;
-
840
-
842
-
845 PrimitiveType getType() const;
-
846
-
848
-
851 void setParentObjectID( uint objID );
-
852
-
854 uint getParentObjectID()const;
-
855
-
857 virtual float getArea() const = 0;
-
858
-
860 virtual helios::vec3 getNormal() const = 0;
-
861
-
863
-
866 void getTransformationMatrix( float (&T)[16] ) const;
-
867
-
869
-
872 void setTransformationMatrix( float (&T)[16] );
-
873
-
875 virtual std::vector<helios::vec3> getVertices( ) const = 0;
-
876
-
878 virtual helios::vec3 getCenter() const = 0;
-
879
-
881 helios::RGBcolor getColor() const;
-
882
-
884 helios::RGBcolor getColorRGB() const;
-
885
-
887 helios::RGBAcolor getColorRGBA() const;
-
888
-
890
-
893 void setColor( const helios::RGBcolor& color );
-
894
-
896
-
899 void setColor( const helios::RGBAcolor& color );
-
900
-
902 bool hasTexture( ) const;
-
903
-
905 std::string getTextureFile( ) const;
-
906
-
908
-
911 void setTextureFile( const char* texture );
-
912
-
914
-
917 std::vector<vec2> getTextureUV( );
-
918
-
919
-
921
-
924 void setTextureUV( const std::vector<vec2> &uv );
-
925
-
927 void overrideTextureColor( );
-
928
-
930 void useTextureColor( );
-
931
-
933 bool isTextureColorOverridden( ) const;
-
934
-
936
-
939 float getSolidFraction() const;
-
940
-
942
-
945 void setSolidFraction( float solidFraction );
-
946
-
948
-
951 void applyTransform( float (&T)[16] );
-
952
-
954
-
957 void translate( const helios::vec3& shift );
-
958
-
960
-
964 virtual void rotate( float rot, const char* axis ) = 0;
-
965
-
967
-
971 virtual void rotate( float rot, const helios::vec3& axis ) = 0;
-
972
-
974
-
979 virtual void rotate( float rot, const helios::vec3 &origin, const helios::vec3 &axis ) = 0;
-
980
-
982
-
985 void scale( const helios::vec3& S );
-
986
-
987 //-------- Primitive Data Methods ---------- //
-
988
-
990
-
994 void setPrimitiveData( const char* label, const int& data );
-
995
-
997
-
1001 void setPrimitiveData( const char* label, const uint& data );
-
1002
-
1004
-
1008 void setPrimitiveData( const char* label, const float& data );
-
1009
-
1011
-
1015 void setPrimitiveData( const char* label, const double& data );
-
1016
-
1018
-
1022 void setPrimitiveData( const char* label, const helios::vec2& data );
-
1023
-
1025
-
1029 void setPrimitiveData( const char* label, const helios::vec3& data );
-
1030
-
1032
-
1036 void setPrimitiveData( const char* label, const helios::vec4& data );
-
1037
-
1039
-
1043 void setPrimitiveData( const char* label, const helios::int2& data );
-
1044
-
1046
-
1050 void setPrimitiveData( const char* label, const helios::int3& data );
-
1051
-
1053
-
1057 void setPrimitiveData( const char* label, const helios::int4& data );
-
1058
-
1060
-
1064 void setPrimitiveData( const char* label, const std::string& data );
-
1066
-
1073 void setPrimitiveData( const char* label, HeliosDataType type, uint size, void* data );
-
1075
-
1079 void getPrimitiveData( const char* label, int& data ) const;
-
1081
-
1085 void getPrimitiveData( const char* label, std::vector<int>& data ) const;
-
1087
-
1091 void getPrimitiveData( const char* label, uint& data ) const;
-
1093
-
1097 void getPrimitiveData( const char* label, std::vector<uint>& data ) const;
-
1099
-
1103 void getPrimitiveData( const char* label, float& data ) const;
-
1105
-
1109 void getPrimitiveData( const char* label, std::vector<float>& data ) const;
-
1111
-
1115 void getPrimitiveData( const char* label, double& data ) const;
-
1117
-
1121 void getPrimitiveData( const char* label, std::vector<double>& data ) const;
-
1123
-
1127 void getPrimitiveData( const char* label, vec2& data ) const;
-
1129
-
1133 void getPrimitiveData( const char* label, std::vector<vec2>& data ) const;
-
1135
-
1139 void getPrimitiveData( const char* label, vec3& data ) const;
-
1141
-
1145 void getPrimitiveData( const char* label, std::vector<vec3>& data ) const;
-
1147
-
1151 void getPrimitiveData( const char* label, vec4& data ) const;
-
1153
-
1157 void getPrimitiveData( const char* label, std::vector<vec4>& data ) const;
-
1159
-
1163 void getPrimitiveData( const char* label, int2& data ) const;
-
1165
-
1169 void getPrimitiveData( const char* label, std::vector<int2>& data ) const;
-
1171
-
1175 void getPrimitiveData( const char* label, int3& data ) const;
-
1177
-
1181 void getPrimitiveData( const char* label, std::vector<int3>& data ) const;
-
1183
-
1187 void getPrimitiveData( const char* label, int4& data ) const;
-
1189
-
1193 void getPrimitiveData( const char* label, std::vector<int4>& data ) const;
-
1195
-
1199 void getPrimitiveData( const char* label, std::string& data ) const;
-
1201
-
1205 void getPrimitiveData( const char* label, std::vector<std::string>& data ) const;
-
1206
-
1208
-
1213 HeliosDataType getPrimitiveDataType( const char* label ) const;
-
1214
-
1216
-
1220 uint getPrimitiveDataSize( const char* label ) const;
-
1221
-
1223
-
1227 bool doesPrimitiveDataExist( const char* label ) const;
-
1228
-
1230
-
1233 void clearPrimitiveData( const char* label );
-
1234
-
1236 std::vector<std::string> listPrimitiveData() const;
-
1237
-
1238 virtual void calculateSolidFraction( const std::map<std::string,Texture> &textures ) = 0;
-
1239
-
1240 friend class Context;
-
1241
-
1242protected:
-
1243
-
1245 uint UUID;
-
1246
-
1248 PrimitiveType prim_type;
-
1249
-
1251 uint parent_object_ID;
-
1252
-
1254 helios::RGBAcolor color;
-
1255
-
1257 std::string texturefile;
-
1259 float transform[16];
-
1260
-
1262 std::vector<vec2> uv;
-
1263
-
1265 float solid_fraction;
-
1266
-
1267 std::map<std::string,HeliosDataType > primitive_data_types;
-
1268 std::map<std::string, std::vector<int> > primitive_data_int;
-
1269 std::map<std::string, std::vector<uint> > primitive_data_uint;
-
1270 std::map<std::string, std::vector<float> > primitive_data_float;
-
1271 std::map<std::string, std::vector<double> > primitive_data_double;
-
1272 std::map<std::string, std::vector<vec2> > primitive_data_vec2;
-
1273 std::map<std::string, std::vector<vec3> > primitive_data_vec3;
-
1274 std::map<std::string, std::vector<vec4> > primitive_data_vec4;
-
1275 std::map<std::string, std::vector<int2> > primitive_data_int2;
-
1276 std::map<std::string, std::vector<int3> > primitive_data_int3;
-
1277 std::map<std::string, std::vector<int4> > primitive_data_int4;
-
1278 std::map<std::string, std::vector<std::string> > primitive_data_string;
-
1279 std::map<std::string, std::vector<bool> > primitive_data_bool;
-
1280
-
1281 bool texturecoloroverridden;
-
1282
-
1283};
-
1284
-
1285
-
1287
-
1292class Patch : public Primitive{
-
1293public:
-
1294
-
1296 Patch( const helios::RGBAcolor& color, uint parent_objID, uint UUID );
-
1297
-
1299 Patch( const char* texturefile, float solid_fraction, uint parent_objID, uint UUID );
-
1300
-
1302 Patch( const char* texturefile, const std::vector<helios::vec2>& uv, const std::map<std::string,Texture> &textures, uint parent_objID, uint UUID );
-
1303
-
1305 ~Patch() override= default;
-
1306
-
1308
-
1309 float getArea() const override;
-
1310
-
1312
-
1313 helios::vec3 getNormal() const override;
-
1314
-
1316
-
1317 std::vector<helios::vec3> getVertices() const override;
-
1318
-
1320
-
1321 helios::vec2 getSize() const;
-
1322
-
1324
-
1327 helios::vec3 getCenter() const override;
-
1328
-
1330
-
1333 void rotate( float rot, const char* axis ) override;
-
1334
-
1336
-
1340 void rotate( float rot, const helios::vec3& axis ) override;
-
1341
-
1343
-
1348 void rotate( float rot, const helios::vec3 &origin, const helios::vec3 &axis ) override;
-
1349
-
1350 void calculateSolidFraction( const std::map<std::string,Texture> &textures ) override;
-
1351
-
1352};
-
1353
-
1355
-
1360class Triangle : public Primitive{
-
1361public:
-
1362
-
1364 Triangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const helios::RGBAcolor& color, uint parent_objID, uint UUID );
-
1365
-
1367 Triangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const char* texturefile, const std::vector<helios::vec2>& uv, float solid_fraction, uint parent_objID, uint UUID );
-
1368
-
1370 Triangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const char* texturefile, const std::vector<helios::vec2>& uv, const std::map<std::string,Texture> &textures, uint parent_objID, uint UUID );
-
1371
-
1373 ~Triangle() override= default;
-
1374
-
1376
-
1379 float getArea() const override;
-
1380
-
1382
-
1385 helios::vec3 getNormal() const override;
-
1386
-
1388
-
1391 std::vector<helios::vec3> getVertices() const override;
-
1392
-
1394
-
1398 helios::vec3 getVertex( int number );
-
1399
-
1401
-
1404 helios::vec3 getCenter() const override;
-
1405
-
1407
-
1411 void rotate( float rot, const char* axis ) override;
-
1412
-
1414
-
1418 void rotate( float rot, const helios::vec3& axis ) override;
-
1419
-
1421
-
1426 void rotate( float rot, const helios::vec3 &origin, const helios::vec3 &axis ) override;
-
1427
-
1428 void calculateSolidFraction( const std::map<std::string,Texture> &textures ) override;
-
1429
-
1430private:
-
1431
-
1433 helios::vec3 vertex0;
-
1434
-
1436 helios::vec3 vertex1;
-
1437
-
1439 helios::vec3 vertex2;
-
1440
-
1441 void makeTransformationMatrix( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2 );
-
1442
-
1443 bool edgeFunction(const helios::vec2 &a, const helios::vec2 &b, const helios::vec2 &c);
-
1444
-
1445};
-
1446
-
1448
-
1451class Voxel : public Primitive{
-
1452public:
-
1453
-
1455 Voxel( const helios::RGBAcolor& color, uint parent_objID, uint UUID );
-
1456
-
1458 ~Voxel() override= default;
-
1459
-
1461
-
1464 float getArea() const override;
-
1465
-
1467 helios::vec3 getNormal() const override;
-
1468
-
1470
-
1473 std::vector<helios::vec3> getVertices() const override;
-
1474
-
1476
-
1479 float getVolume();
-
1480
-
1482
-
1485 helios::vec3 getCenter() const override;
-
1486
-
1488
-
1491 helios::vec3 getSize();
-
1492
-
1494
-
1498 void rotate( float rot, const char* axis ) override;
-
1499
-
1501
-
1505 void rotate( float rot, const helios::vec3& axis ) override;
-
1506
-
1507
-
1509
-
1514 void rotate( float rot, const helios::vec3 &origin, const helios::vec3 &axis ) override;
-
1515
-
1516 void calculateSolidFraction( const std::map<std::string,Texture> &textures ) override;
-
1517
-
1518};
-
1519
- -
1522public:
-
1523
-
1525
-
1530 static int parse_data_float( const pugi::xml_node &node_data, std::vector<float> &data );
-
1531
-
1533
-
1538 static int parse_data_double( const pugi::xml_node &node_data, std::vector<double> &data );
-
1539
-
1541
-
1546 static int parse_data_int( const pugi::xml_node &node_data, std::vector<int> &data );
-
1547
-
1549
-
1554 static int parse_data_uint( const pugi::xml_node &node_data, std::vector<uint> &data );
-
1555
-
1557
-
1562 static int parse_data_string( const pugi::xml_node &node_data, std::vector<std::string> &data );
-
1563
-
1565
-
1570 static int parse_data_vec2( const pugi::xml_node &node_data, std::vector<vec2> &data );
-
1571
-
1573
-
1578 static int parse_data_vec3( const pugi::xml_node &node_data, std::vector<vec3> &data );
-
1579
-
1581
-
1586 static int parse_data_vec4( const pugi::xml_node &node_data, std::vector<vec4> &data );
-
1587
-
1589
-
1594 static int parse_data_int2( const pugi::xml_node &node_data, std::vector<int2> &data );
-
1595
-
1597
-
1602 static int parse_data_int3( const pugi::xml_node &node_data, std::vector<int3> &data );
-
1603
-
1605
-
1610 static int parse_data_int4( const pugi::xml_node &node_data, std::vector<int4> &data );
-
1611
-
1613
-
1618 static int parse_objID( const pugi::xml_node &node_data, uint &objID );
-
1619
-
1621
-
1626 static int parse_transform( const pugi::xml_node &node_data, float (&transform)[16] );
-
1627
-
1629
-
1634 static int parse_texture( const pugi::xml_node &node_data, std::string &texture );
-
1635
-
1637
-
1642 static int parse_textureUV( const pugi::xml_node &node_data, std::vector<vec2> &uvs );
-
1643
-
1645
-
1650 static int parse_solid_fraction( const pugi::xml_node &node_data, float &solid_fraction );
-
1651
-
1653
-
1658 static int parse_vertices( const pugi::xml_node &node_data, std::vector<float> &vertices );
-
1659
-
1661
-
1666 static int parse_subdivisions( const pugi::xml_node &node_data, uint &subdivisions );
-
1667
-
1669
-
1674 static int parse_subdivisions( const pugi::xml_node &node_data, int2 &subdivisions );
-
1675
-
1677
-
1682 static int parse_subdivisions( const pugi::xml_node &node_data, int3 &subdivisions );
-
1683
-
1685
-
1690 static int parse_nodes( const pugi::xml_node &node_data, std::vector<vec3> &nodes );
-
1691
-
1693
-
1698 static int parse_radius( const pugi::xml_node &node_data, std::vector<float> &radius );
-
1699
-
1700};
-
1701
-
1703
- -
1706private:
-
1707
-
1708 //---------- PRIMITIVE/OBJECT HELIOS::VECTORS ----------------//
-
1709
-
1711
-
1715 Primitive* getPrimitivePointer_private( uint UUID ) const;
-
1716
-
1718
-
1722 Patch* getPatchPointer_private( uint UUID ) const;
-
1723
-
1724
-
1726
-
1730 Triangle* getTrianglePointer_private( uint UUID ) const;
-
1731
-
1732
-
1734
-
1738 Voxel* getVoxelPointer_private( uint UUID ) const;
-
1739
-
1741
-
1745 CompoundObject* getObjectPointer_private( uint ObjID ) const;
-
1746
-
1748
-
1752 Tile* getTileObjectPointer_private( uint ObjID ) const;
-
1753
-
1755
-
1759 Sphere* getSphereObjectPointer_private( uint ObjID ) const;
-
1760
-
1762
-
1766 Tube* getTubeObjectPointer_private( uint ObjID ) const;
-
1767
-
1769
-
1773 Box* getBoxObjectPointer_private( uint ObjID ) const;
-
1774
-
1776
-
1780 Disk* getDiskObjectPointer_private( uint ObjID ) const;
-
1781
-
1783
-
1787 Polymesh* getPolymeshObjectPointer_private( uint ObjID ) const;
-
1788
-
1790
-
1794 Cone* getConeObjectPointer_private( uint ObjID ) const;
-
1795
-
1796
-
1798
-
1799 std::map<uint,Primitive*> primitives;
-
1800
-
1802 std::map<uint,CompoundObject*> objects;
-
1803
-
1805 std::map<std::string, std::vector<float> > timeseries_data;
-
1806
-
1808
-
1809 std::map<std::string, std::vector<double> > timeseries_datevalue;
-
1810
-
1811 //------------ TEXTURES ----------------//
-
1812
-
1813 std::map<std::string,Texture> textures;
-
1814
-
1815 void addTexture( const char* texture_file );
-
1816
-
1817 bool doesTextureFileExist(const char* texture_file ) const;
-
1818
-
1819 //----------- GLOBAL DATA -------------//
-
1820
-
1821 std::map<std::string, GlobalData> globaldata;
-
1822
-
1823 //---------- CONTEXT PRIVATE MEMBER VARIABLES ---------//
-
1824 //NOTE: variables are initialized and documented in initializeContext() member method
-
1825
-
1827
-
1830 helios::Date sim_date;
-
1831
-
1833
-
1836 helios::Time sim_time;
-
1837
-
1839 std::minstd_rand0 generator;
-
1840
-
1842 std::uniform_real_distribution<float> unif_distribution;
-
1843
-
1845 std::normal_distribution<float> norm_distribution;
-
1846
-
1847 //---------- CONTEXT I/O ---------//
-
1848
-
1849 std::vector<std::string> XMLfiles;
-
1850
-
1851 struct OBJmaterial{
-
1852
-
1853 RGBcolor color;
-
1854 std::string texture;
-
1855 uint materialID;
-
1856 bool textureHasTransparency = false;
-
1857 bool textureColorIsOverridden = false;
-
1858
-
1859 OBJmaterial( const RGBcolor &a_color, std::string a_texture, uint a_materialID ) : color{a_color}, texture{std::move(a_texture)}, materialID{a_materialID} {};
-
1860
-
1861 };
-
1862
-
1863 static std::map<std::string,OBJmaterial> loadMTL(const std::string &filebase, const std::string &material_file );
-
1864
-
1865 void loadPData( pugi::xml_node p, uint UUID );
-
1866
-
1867 void loadOData( pugi::xml_node p, uint ID );
-
1868
-
1869 void loadOsubPData( pugi::xml_node p, uint ID );
-
1870
-
1871 void writeDataToXMLstream( const char* data_group, const std::vector<std::string> &data_labels, void* ptr, std::ofstream &outfile ) const;
-
1872
-
1873 std::vector<std::string> generateTexturesFromColormap( const std::string &texturefile, const std::vector<RGBcolor> &colormap_data );
-
1874
-
1875 std::vector<RGBcolor> generateColormap( const std::string &colormap, uint Ncolors );
-
1876
-
1877 std::vector<RGBcolor> generateColormap( const std::vector<helios::RGBcolor> &ctable, const std::vector<float> &cfrac, uint Ncolors );
-
1878
-
1879
-
1880 //---------- CONTEXT INITIALIZATION FLAGS ---------//
-
1881
-
1883
-
1886 bool iscontextinitialized;
-
1887
-
1889 bool isgeometrydirty;
-
1890
-
1891 uint currentUUID;
-
1892
-
1893 uint currentObjectID;
-
1894
-
1895public:
-
1896
-
1898 Context();
-
1899
-
1901 ~Context();
-
1902
-
1904 Context( const Context& ) = delete;
-
1905
-
1907 void operator=( const Context& ) = delete;
-
1908
-
1910
-
1913 static int selfTest();
-
1914
-
1916
-
1919 void seedRandomGenerator(uint seed);
-
1920
-
1922
-
1925 std::minstd_rand0* getRandomGenerator();
-
1926
-
1928
-
1929 void markGeometryClean();
-
1930
-
1932
-
1933 void markGeometryDirty();
-
1934
-
1936
-
1937 bool isGeometryDirty() const;
-
1938
-
1940
-
1943 uint addPatch();
-
1944
-
1946
-
1953 uint addPatch( const helios::vec3& center, const helios::vec2& size );
-
1954
-
1956
-
1964 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation );
-
1965
-
1967
-
1974 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
-
1975
-
1977
-
1983 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
-
1984
-
1986
-
1994 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file );
-
1995
-
1997
-
2007 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file, const helios::vec2& uv_center, const helios::vec2& uv_size );
-
2008
-
2010
-
2017 uint addTriangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2 );
-
2018
-
2020
-
2028 uint addTriangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const helios::RGBcolor& color );
-
2029
-
2031
-
2039 uint addTriangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const helios::RGBAcolor& color );
-
2040
-
2042
-
2054 uint addTriangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const char* texture_file, const helios::vec2& uv0, const helios::vec2& uv1, const helios::vec2& uv2 );
-
2055
-
2057
-
2064 uint addVoxel( const helios::vec3& center, const helios::vec3& size );
-
2065
-
2067
-
2075 uint addVoxel( const helios::vec3& center, const helios::vec3& size, const float& rotation );
-
2076
-
2078
-
2085 uint addVoxel( const helios::vec3& center, const helios::vec3& size, const float& rotation, const helios::RGBcolor& color );
-
2086
-
2088
-
2095 uint addVoxel( const helios::vec3& center, const helios::vec3& size, const float& rotation, const helios::RGBAcolor& color );
-
2096
-
2098
-
2102 void translatePrimitive( uint UUID, const vec3& shift );
-
2103
-
2105
-
2109 void translatePrimitive( const std::vector<uint>& UUIDs, const vec3& shift );
-
2110
-
2112
-
2117 void rotatePrimitive( uint UUID, float rot, const char* axis );
-
2118
-
2120
-
2125 void rotatePrimitive( const std::vector<uint>& UUIDs, float rot, const char* axis );
-
2126
-
2128
-
2133 void rotatePrimitive( uint UUID, float rot, const helios::vec3& axis );
-
2134
-
2136
-
2141 void rotatePrimitive(const std::vector<uint>& UUIDs, float rot, const vec3 &axis );
-
2142
-
2144
-
2150 void rotatePrimitive( uint UUID, float rot, const helios::vec3& origin, const helios::vec3& axis );
-
2151
-
2153
-
2159 void rotatePrimitive(const std::vector<uint>& UUIDs, float rot, const helios::vec3& origin, const vec3 &axis );
-
2160
-
2162
-
2166 void scalePrimitive( uint UUID, const helios::vec3& S );
-
2167
-
2169
-
2173 void scalePrimitive( const std::vector<uint>& UUIDs, const helios::vec3& S );
-
2174
-
2176
-
2179 void deletePrimitive( uint UUID );
-
2180
-
2182
-
2185 void deletePrimitive( const std::vector<uint>& UUIDs );
-
2186
-
2188
-
2192 uint copyPrimitive(uint UUID );
-
2193
-
2195
-
2199 std::vector<uint> copyPrimitive(const std::vector<uint> &UUIDs );
-
2200
-
2202
-
2206 void copyPrimitiveData( uint UUID, uint currentUUID);
-
2207
-
2209
-
2214 void renamePrimitiveData( uint UUID, const char* old_label, const char* new_label );
-
2215
-
2217
-
2222 void duplicatePrimitiveData( uint UUID, const char* old_label, const char* new_label );
-
2223
-
2225
-
2228 bool doesPrimitiveExist( uint UUID ) const;
-
2229
-
2231
-
2235 bool doesPrimitiveExist( const std::vector<uint> &UUIDs ) const;
-
2236
-
2238
-
2243 helios::vec2 getPatchSize( uint UUID ) const;
-
2244
-
2245
-
2247
-
2252 helios::vec3 getPatchCenter( uint UUID ) const;
-
2253
-
2255
-
2261 helios::vec3 getTriangleVertex( uint UUID, uint number ) const;
-
2262
-
2264
-
2269 helios::vec3 getVoxelCenter( uint UUID ) const;
-
2270
-
2272
-
2277 helios::vec3 getVoxelSize( uint UUID ) const;
-
2278
-
2280
-
2283 uint getPrimitiveCount() const;
-
2284
-
2286 std::vector<uint> getAllUUIDs() const;
-
2287
-
2289
-
2292 void cleanDeletedUUIDs( std::vector<uint> &UUIDs ) const;
-
2293
-
2295
-
2298 void cleanDeletedUUIDs( std::vector<std::vector<uint>> &UUIDs ) const;
-
2299
-
2301
-
2304 void cleanDeletedUUIDs( std::vector<std::vector<std::vector<uint>>> &UUIDs ) const;
-
2305
-
2306 //-------- Primitive Data Methods ---------- //
-
2307
-
2309
-
2314 void setPrimitiveData( const uint& UUID, const char* label, const int& data );
-
2315
-
2317
-
2322 void setPrimitiveData( const uint& UUID, const char* label, const uint& data );
-
2323
-
2325
-
2330 void setPrimitiveData( const uint& UUID, const char* label, const float& data );
-
2331
-
2333
-
2337 void setPrimitiveData( const uint& UUID, const char* label, const double& data );
-
2338
-
2340
-
2345 void setPrimitiveData( const uint& UUID, const char* label, const helios::vec2& data );
-
2346
-
2348
-
2353 void setPrimitiveData( const uint& UUID, const char* label, const helios::vec3& data );
-
2354
-
2356
-
2361 void setPrimitiveData( const uint& UUID, const char* label, const helios::vec4& data );
-
2362
-
2364
-
2369 void setPrimitiveData( const uint& UUID, const char* label, const helios::int2& data );
-
2370
-
2372
-
2377 void setPrimitiveData( const uint& UUID, const char* label, const helios::int3& data );
-
2378
-
2380
-
2385 void setPrimitiveData( const uint& UUID, const char* label, const helios::int4& data );
-
2386
-
2388
-
2393 void setPrimitiveData( const uint& UUID, const char* label, const std::string& data );
-
2394
-
2396
-
2403 void setPrimitiveData( const uint& UUIDs, const char* label, HeliosDataType type, uint size, void* data );
-
2404
-
2406
-
2411 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const int& data );
-
2412
-
2414
-
2419 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const uint& data );
-
2420
-
2422
-
2427 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const float& data );
-
2428
-
2430
-
2434 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const double& data );
-
2435
-
2437
-
2442 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::vec2& data );
-
2443
-
2445
-
2450 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::vec3& data );
-
2451
-
2453
-
2458 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::vec4& data );
-
2459
-
2461
-
2466 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::int2& data );
-
2467
-
2469
-
2474 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::int3& data );
-
2475
-
2477
-
2482 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::int4& data );
-
2483
-
2485
-
2490 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const std::string& data );
-
2491
-
2493
-
2498 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const int& data );
-
2499
-
2501
-
2506 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const uint& data );
-
2507
-
2509
-
2514 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const float& data );
-
2515
-
2517
-
2521 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const double& data );
-
2522
-
2524
-
2529 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::vec2& data );
-
2530
-
2532
-
2537 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::vec3& data );
-
2538
-
2540
-
2545 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::vec4& data );
-
2546
-
2548
-
2553 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::int2& data );
-
2554
-
2556
-
2561 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::int3& data );
-
2562
-
2564
-
2569 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::int4& data );
-
2570
-
2572
-
2577 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const std::string& data );
-
2578
-
2580
-
2585 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const int& data );
-
2586
-
2588
-
2593 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const uint& data );
-
2594
-
2596
-
2601 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const float& data );
-
2602
-
2604
-
2608 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const double& data );
-
2609
-
2611
-
2616 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::vec2& data );
-
2617
-
2619
-
2624 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::vec3& data );
-
2625
-
2627
-
2632 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::vec4& data );
-
2633
-
2635
-
2640 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::int2& data );
-
2641
-
2643
-
2648 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::int3& data );
-
2649
-
2651
-
2656 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::int4& data );
-
2657
-
2659
-
2664 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const std::string& data );
-
2665
-
2667
-
2672 void getPrimitiveData( uint UUID, const char* label, int& data ) const;
-
2673
-
2675
-
2680 void getPrimitiveData( uint UUID, const char* label, std::vector<int>& data ) const;
-
2681
-
2683
-
2688 void getPrimitiveData( uint UUID, const char* label, uint& data ) const;
-
2689
-
2691
-
2696 void getPrimitiveData( uint UUID, const char* label, std::vector<uint>& data ) const;
-
2697
-
2699
-
2704 void getPrimitiveData( uint UUID, const char* label, float& data ) const;
-
2705
-
2707
-
2712 void getPrimitiveData( uint UUID, const char* label, std::vector<float>& data ) const;
-
2713
-
2715
-
2720 void getPrimitiveData( uint UUID, const char* label, double& data ) const;
-
2721
-
2723
-
2728 void getPrimitiveData( uint UUID, const char* label, std::vector<double>& data ) const;
-
2729
-
2731
-
2736 void getPrimitiveData( uint UUID, const char* label, vec2& data ) const;
-
2737
-
2739
-
2744 void getPrimitiveData( uint UUID, const char* label, std::vector<vec2>& data ) const;
-
2745
-
2747
-
2752 void getPrimitiveData( uint UUID, const char* label, vec3& data ) const;
-
2753
-
2755
-
2760 void getPrimitiveData( uint UUID, const char* label, std::vector<vec3>& data ) const;
-
2761
-
2763
-
2768 void getPrimitiveData( uint UUID, const char* label, vec4& data ) const;
-
2769
-
2771
-
2776 void getPrimitiveData( uint UUID, const char* label, std::vector<vec4>& data ) const;
-
2777
-
2779
-
2784 void getPrimitiveData( uint UUID, const char* label, int2& data ) const;
-
2785
-
2787
-
2792 void getPrimitiveData( uint UUID, const char* label, std::vector<int2>& data ) const;
-
2793
-
2795
-
2800 void getPrimitiveData( uint UUID, const char* label, int3& data ) const;
-
2801
-
2803
-
2808 void getPrimitiveData( uint UUID, const char* label, std::vector<int3>& data ) const;
-
2809
-
2811
-
2816 void getPrimitiveData( uint UUID, const char* label, int4& data ) const;
-
2817
-
2819
-
2824 void getPrimitiveData( uint UUID, const char* label, std::vector<int4>& data ) const;
-
2825
-
2827
-
2832 void getPrimitiveData( uint UUID, const char* label, std::string& data ) const;
-
2833
-
2835
-
2840 void getPrimitiveData( uint UUID, const char* label, std::vector<std::string>& data ) const;
-
2841
-
2843
-
2849 HeliosDataType getPrimitiveDataType( uint UUID, const char* label ) const;
-
2850
-
2852
-
2857 uint getPrimitiveDataSize( uint UUID, const char* label ) const;
-
2858
-
2860
-
2865 bool doesPrimitiveDataExist( uint UUID, const char* label ) const;
-
2866
-
2868
-
2872 void clearPrimitiveData( uint UUID, const char* label );
-
2873
-
2875
-
2879 void clearPrimitiveData( const std::vector<uint>& UUIDs, const char* label );
-
2880
-
2882
-
2886 PrimitiveType getPrimitiveType( uint UUID ) const;
-
2887
-
2889
-
2893 void setPrimitiveParentObjectID( uint UUID, uint objID );
-
2894
-
2896
-
2900 void setPrimitiveParentObjectID( const std::vector<uint> &UUIDs, uint objID );
-
2901
-
2903
-
2906 uint getPrimitiveParentObjectID( uint UUID )const;
-
2907
-
2908
-
2910
-
2913 std::vector<uint> getUniquePrimitiveParentObjectIDs(std::vector<uint> UUIDs) const;
-
2914
-
2915
-
2917
-
2920 std::vector<uint> getUniquePrimitiveParentObjectIDs(std::vector<uint> UUIDs, bool include_ObjID_zero) const;
-
2921
-
2922
-
2924
-
2927 float getPrimitiveArea( uint UUID ) const;
-
2928
-
2930
-
2935 void getPrimitiveBoundingBox( uint UUID, vec3 &min_corner, vec3 &max_corner ) const;
-
2936
-
2938
-
2943 void getPrimitiveBoundingBox( const std::vector<uint> &UUID, vec3 &min_corner, vec3 &max_corner ) const;
-
2944
-
2946
-
2949 float getObjectArea( uint ObjID ) const;
-
2950
-
2952
-
2955 uint getObjectPrimitiveCount( uint ObjID ) const;
-
2956
-
2958
-
2961 helios::vec3 getObjectCenter( uint ObjID ) const;
-
2962
-
2964
-
2968 void setObjectColor( uint ObjID, const helios::RGBcolor& color );
-
2969
-
2971
-
2975 void setObjectColor( const std::vector<uint> &ObjIDs, const helios::RGBcolor& color );
-
2976
-
2978
-
2982 void setObjectColor( uint ObjID, const helios::RGBAcolor& color );
-
2983
-
2985
-
2989 void setObjectColor( const std::vector<uint> &ObjIDs, const helios::RGBAcolor& color );
-
2990
-
2992
-
2995 std::string getObjectTextureFile( uint ObjID ) const;
-
2996
-
2998
-
3002 void getObjectTransformationMatrix( uint ObjID, float (&T)[16] ) const;
-
3003
-
3005
-
3009 void setObjectTransformationMatrix( uint ObjID, float (&T)[16] );
-
3010
-
3012
-
3016 void setObjectTransformationMatrix( const std::vector<uint> &ObjIDs, float (&T)[16] );
-
3017
-
3019
-
3022 bool objectHasTexture( uint ObjID ) const;
-
3023
-
3025
-
3029 bool doesObjectContainPrimitive(uint ObjID, uint UUID );
-
3030
-
3032
-
3035 void overrideObjectTextureColor( uint ObjID );
-
3036
-
3038
-
3041 void overrideObjectTextureColor( const std::vector<uint> &ObjIDs );
-
3042
-
3044
-
3047 void useObjectTextureColor( uint ObjID );
-
3048
-
3050
-
3053 void useObjectTextureColor( const std::vector<uint> &ObjIDs );
-
3054
-
3056
-
3061 void getObjectBoundingBox( uint ObjID, vec3 &min_corner, vec3 &max_corner ) const;
-
3062
-
3064
-
3069 void getObjectBoundingBox( const std::vector<uint> &ObjID, vec3 &min_corner, vec3 &max_corner ) const;
-
3070
-
3072
-
3075 void printObjectInfo(uint ObjID) const;
-
3076
-
3078 std::vector<std::string> listObjectData(uint ObjID) const;
-
3079
-
3081 std::vector<std::string> listPrimitiveData(uint UUID) const;
-
3082
-
3084
-
3088 float getPrimitiveSolidFraction( uint UUID ) const;
-
3089
-
3091
-
3094 helios::vec3 getPrimitiveNormal( uint UUID ) const;
-
3095
-
3097
-
3101 void getPrimitiveTransformationMatrix( uint UUID, float (&T)[16] ) const;
-
3102
-
3104
-
3108 void setPrimitiveTransformationMatrix( uint UUID, float (&T)[16] );
-
3109
-
3111
-
3115 void setPrimitiveTransformationMatrix( const std::vector<uint> &UUIDs, float (&T)[16] );
-
3116
-
3118
-
3121 std::vector<helios::vec3> getPrimitiveVertices( uint UUID ) const;
-
3122
-
3124
-
3127 helios::RGBcolor getPrimitiveColor( uint UUID ) const;
-
3128
-
3130
-
3133 helios::RGBcolor getPrimitiveColorRGB( uint UUID ) const;
-
3134
-
3136
-
3139 helios::RGBAcolor getPrimitiveColorRGBA( uint UUID ) const;
-
3140
-
3142
-
3146 void setPrimitiveColor( uint UUID, const helios::RGBcolor& color );
-
3147
-
3149
-
3153 void setPrimitiveColor( const std::vector<uint> &UUIDs, const helios::RGBcolor& color );
-
3154
-
3156
-
3160 void setPrimitiveColor( uint UUID, const helios::RGBAcolor& color );
-
3161
-
3163
-
3167 void setPrimitiveColor( const std::vector<uint> &UUIDs, const helios::RGBAcolor& color );
-
3168
-
3170
-
3174 std::string getPrimitiveTextureFile( uint UUID ) const;
-
3175
-
3176
-
3178
-
3182 void setPrimitiveTextureFile( uint UUID, const std::string &texturefile );
-
3183
-
3185
-
3189 helios::int2 getPrimitiveTextureSize( uint UUID ) const;
-
3190
-
3192
-
3195 std::vector<vec2> getPrimitiveTextureUV( uint UUID ) const;
-
3196
-
3198
-
3202 bool primitiveTextureHasTransparencyChannel(uint UUID ) const;
-
3203
-
3205
-
3209 const std::vector<std::vector<bool>> * getPrimitiveTextureTransparencyData(uint UUID) const;
-
3210
-
3212
-
3215 void overridePrimitiveTextureColor( uint UUID );
-
3216
-
3218
-
3221 void overridePrimitiveTextureColor( const std::vector<uint> &UUIDs );
-
3222
-
3224
-
3227 void usePrimitiveTextureColor( uint UUID );
-
3228
-
3230
-
3233 void usePrimitiveTextureColor( const std::vector<uint> &UUIDs );
-
3234
-
3236
-
3239 bool isPrimitiveTextureColorOverridden( uint UUID ) const;
-
3240
-
3242
-
3245 void printPrimitiveInfo(uint UUID) const;
-
3246
-
3247 //-------- Compound Object Data Methods ---------- //
-
3248
-
3250
-
3255 void setObjectData( uint objID, const char* label, const int& data );
-
3256
-
3258
-
3263 void setObjectData( uint objID, const char* label, const uint& data );
-
3264
-
3266
-
3271 void setObjectData( uint objID, const char* label, const float& data );
-
3272
-
3274
-
3278 void setObjectData( uint objID, const char* label, const double& data );
-
3279
-
3281
-
3286 void setObjectData( uint objID, const char* label, const helios::vec2& data );
-
3287
-
3289
-
3294 void setObjectData( uint objID, const char* label, const helios::vec3& data );
-
3295
-
3297
-
3302 void setObjectData( uint objID, const char* label, const helios::vec4& data );
-
3303
-
3305
-
3310 void setObjectData( uint objID, const char* label, const helios::int2& data );
-
3311
-
3313
-
3318 void setObjectData( uint objID, const char* label, const helios::int3& data );
-
3319
-
3321
-
3326 void setObjectData( uint objID, const char* label, const helios::int4& data );
-
3327
-
3329
-
3334 void setObjectData( uint objID, const char* label, const std::string& data );
-
3335
-
3337
-
3344 void setObjectData( uint objIDs, const char* label, HeliosDataType type, uint size, void* data );
-
3345
-
3347
-
3352 void setObjectData( const std::vector<uint>& objIDs, const char* label, const int& data );
-
3353
-
3355
-
3360 void setObjectData( const std::vector<uint>& objIDs, const char* label, const uint& data );
-
3361
-
3363
-
3368 void setObjectData( const std::vector<uint>& objIDs, const char* label, const float& data );
-
3369
-
3371
-
3375 void setObjectData( const std::vector<uint>& objIDs, const char* label, const double& data );
-
3376
-
3378
-
3383 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::vec2& data );
-
3384
-
3386
-
3391 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::vec3& data );
-
3392
-
3394
-
3399 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::vec4& data );
-
3400
-
3402
-
3407 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::int2& data );
-
3408
-
3410
-
3415 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::int3& data );
-
3416
-
3418
-
3423 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::int4& data );
-
3424
-
3426
-
3431 void setObjectData( const std::vector<uint>& objIDs, const char* label, const std::string& data );
-
3432
-
3434
-
3439 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const int& data );
-
3440
-
3442
-
3447 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const uint& data );
-
3448
-
3450
-
3455 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const float& data );
-
3456
-
3458
-
3462 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const double& data );
-
3463
-
3465
-
3470 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::vec2& data );
-
3471
-
3473
-
3478 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::vec3& data );
-
3479
-
3481
-
3486 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::vec4& data );
-
3487
-
3489
-
3494 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::int2& data );
-
3495
-
3497
-
3502 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::int3& data );
-
3503
-
3505
-
3510 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::int4& data );
-
3511
-
3513
-
3518 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const std::string& data );
-
3520
-
3525 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const int& data );
-
3526
-
3528
-
3533 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const uint& data );
-
3534
-
3536
-
3541 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const float& data );
-
3542
-
3544
-
3548 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const double& data );
-
3549
-
3551
-
3556 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::vec2& data );
-
3557
-
3559
-
3564 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::vec3& data );
-
3565
-
3567
-
3572 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::vec4& data );
-
3573
-
3575
-
3580 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::int2& data );
-
3581
-
3583
-
3588 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::int3& data );
-
3589
-
3591
-
3596 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::int4& data );
-
3597
-
3599
-
3604 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const std::string& data );
-
3605
-
3607
-
3612 void getObjectData( uint objID, const char* label, int& data ) const;
-
3613
-
3615
-
3620 void getObjectData( uint objID, const char* label, std::vector<int>& data ) const;
-
3621
-
3623
-
3628 void getObjectData( uint objID, const char* label, uint& data ) const;
-
3629
-
3631
-
3636 void getObjectData( uint objID, const char* label, std::vector<uint>& data ) const;
-
3637
-
3639
-
3644 void getObjectData( uint objID, const char* label, float& data ) const;
-
3645
-
3647
-
3652 void getObjectData( uint objID, const char* label, std::vector<float>& data ) const;
-
3653
-
3655
-
3660 void getObjectData( uint objID, const char* label, double& data ) const;
-
3661
-
3663
-
3668 void getObjectData( uint objID, const char* label, std::vector<double>& data ) const;
-
3669
-
3671
-
3676 void getObjectData( uint objID, const char* label, vec2& data ) const;
-
3677
-
3679
-
3684 void getObjectData( uint objID, const char* label, std::vector<vec2>& data ) const;
-
3685
-
3687
-
3692 void getObjectData( uint objID, const char* label, vec3& data ) const;
-
3693
-
3695
-
3700 void getObjectData( uint objID, const char* label, std::vector<vec3>& data ) const;
-
3701
-
3703
-
3708 void getObjectData( uint objID, const char* label, vec4& data ) const;
-
3709
-
3711
-
3716 void getObjectData( uint objID, const char* label, std::vector<vec4>& data ) const;
-
3717
-
3719
-
3724 void getObjectData( uint objID, const char* label, int2& data ) const;
-
3725
-
3727
-
3732 void getObjectData( uint objID, const char* label, std::vector<int2>& data ) const;
-
3733
-
3735
-
3740 void getObjectData( uint objID, const char* label, int3& data ) const;
-
3741
-
3743
-
3748 void getObjectData( uint objID, const char* label, std::vector<int3>& data ) const;
-
3749
-
3751
-
3756 void getObjectData( uint objID, const char* label, int4& data ) const;
-
3757
-
3759
-
3764 void getObjectData( uint objID, const char* label, std::vector<int4>& data ) const;
-
3765
-
3767
-
3772 void getObjectData( uint objID, const char* label, std::string& data ) const;
-
3773
-
3775
-
3780 void getObjectData( uint objID, const char* label, std::vector<std::string>& data ) const;
-
3781
-
3783
-
3789 HeliosDataType getObjectDataType( uint objID, const char* label ) const;
-
3790
-
3792
-
3797 uint getObjectDataSize( uint objID, const char* label ) const;
-
3798
-
3800
-
3805 bool doesObjectDataExist( uint objID, const char* label ) const;
-
3806
-
3808
-
3812 void clearObjectData( uint objID, const char* label );
-
3813
-
3815
-
3819 void clearObjectData( const std::vector<uint>& objIDs, const char* label );
-
3820
-
3822
-
3826 bool areObjectPrimitivesComplete( uint objID ) const;
-
3827
-
3828
-
3829
-
3830 //-------- Global Data Methods ---------- //
-
3831
-
3833
-
3837 void setGlobalData( const char* label, const int& data );
-
3838
-
3840
-
3844 void setGlobalData( const char* label, const uint& data );
-
3845
-
3847
-
3851 void setGlobalData( const char* label, const float& data );
-
3852
-
3854
-
3858 void setGlobalData( const char* label, const double& data );
-
3859
-
3861
-
3865 void setGlobalData( const char* label, const helios::vec2& data );
-
3866
-
3868
-
3872 void setGlobalData( const char* label, const helios::vec3& data );
-
3873
-
3875
-
3879 void setGlobalData( const char* label, const helios::vec4& data );
-
3880
-
3882
-
3886 void setGlobalData( const char* label, const helios::int2& data );
-
3887
-
3889
-
3893 void setGlobalData( const char* label, const helios::int3& data );
-
3894
-
3896
-
3901 void setGlobalData( const char* label, const helios::int4& data );
-
3902
-
3904
-
3908 void setGlobalData( const char* label, const std::string& data );
-
3909
-
3911
-
3916 void setGlobalData( const char* label, HeliosDataType type, size_t size, void* data );
-
3917
-
3919
-
3923 void renameGlobalData( const char* old_label, const char* new_label );
-
3924
-
3926
-
3930 void duplicateGlobalData(const char* old_label, const char* new_label );
-
3931
-
3933
-
3936 void clearGlobalData( const char* label );
-
3937
-
3939
-
3943 void getGlobalData( const char* label, int& data ) const;
-
3944
-
3946
-
3950 void getGlobalData( const char* label, std::vector<int>& data ) const;
-
3951
-
3953
-
3957 void getGlobalData( const char* label, uint& data ) const;
-
3958
-
3960
-
3964 void getGlobalData( const char* label, std::vector<uint>& data ) const;
-
3965
-
3967
-
3971 void getGlobalData( const char* label, float& data ) const;
-
3972
-
3974
-
3978 void getGlobalData( const char* label, std::vector<float>& data ) const;
-
3979
-
3981
-
3985 void getGlobalData( const char* label, double& data ) const;
-
3986
-
3988
-
3992 void getGlobalData( const char* label, std::vector<double>& data ) const;
-
3993
-
3995
-
3999 void getGlobalData( const char* label, helios::vec2& data ) const;
-
4000
-
4002
-
4006 void getGlobalData( const char* label, std::vector<helios::vec2>& data ) const;
-
4007
-
4009
-
4013 void getGlobalData( const char* label, helios::vec3& data ) const;
-
4014
-
4016
-
4020 void getGlobalData( const char* label, std::vector<helios::vec3>& data ) const;
-
4021
-
4023
-
4027 void getGlobalData( const char* label, helios::vec4& data ) const;
-
4028
-
4030
-
4034 void getGlobalData( const char* label, std::vector<helios::vec4>& data ) const;
-
4035
-
4037
-
4041 void getGlobalData( const char* label, helios::int2& data ) const;
-
4042
-
4044
-
4048 void getGlobalData( const char* label, std::vector<helios::int2>& data ) const;
-
4049
-
4051
-
4055 void getGlobalData( const char* label, helios::int3& data ) const;
-
4056
-
4058
-
4062 void getGlobalData( const char* label, std::vector<helios::int3>& data ) const;
-
4063
-
4065
-
4069 void getGlobalData( const char* label, helios::int4& data ) const;
-
4070
-
4072
-
4076 void getGlobalData( const char* label, std::vector<helios::int4>& data ) const;
-
4077
-
4079
-
4083 void getGlobalData( const char* label, std::string& data ) const;
-
4084
-
4086
-
4090 void getGlobalData( const char* label, std::vector<std::string>& data ) const;
-
4091
-
4093
-
4097 HeliosDataType getGlobalDataType( const char* label ) const;
-
4098
-
4100
-
4104 size_t getGlobalDataSize( const char* label ) const;
-
4105
-
4107
-
4111 bool doesGlobalDataExist( const char* label ) const;
-
4112
-
4114
-
4119 void incrementGlobalData( const char* label, int increment );
-
4120
-
4122
-
4127 void incrementGlobalData( const char* label, uint increment );
-
4128
-
4130
-
4135 void incrementGlobalData( const char* label, float increment );
-
4136
-
4138
-
4143 void incrementGlobalData( const char* label, double increment );
-
4144
-
4145 //--------- Compound Objects Methods -------------//
-
4146
-
4148
-
4151 CompoundObject* getObjectPointer( uint ObjID ) const;
-
4152
-
4154
-
4157 uint getObjectCount() const;
-
4158
-
4160
-
4163 bool doesObjectExist( uint ObjID ) const;
-
4164
-
4166
-
4169 std::vector<uint> getAllObjectIDs() const;
-
4170
-
4172
-
4175 void deleteObject(uint ObjID );
-
4176
-
4178
-
4181 void deleteObject(const std::vector<uint> &ObjIDs );
-
4182
-
4184
-
4188 uint copyObject(uint ObjID );
-
4189
-
4191
-
4195 std::vector<uint> copyObject(const std::vector<uint> &ObjIDs );
-
4196
-
4198
-
4202 void copyObjectData( uint objID, uint currentObjID);
-
4203
-
4205
-
4209 void duplicateObjectData( uint objID, const char* old_label, const char* new_label );
-
4210
-
4212
-
4216 void renameObjectData( uint objID, const char* old_label, const char* new_label );
-
4217
-
4219
-
4225 std::vector<uint> filterObjectsByData( const std::vector<uint> &ObjIDs, const char* object_data, float threshold, const char* comparator) const;
-
4226
-
4228
-
4232 void translateObject(uint ObjID, const vec3& shift );
-
4233
-
4235
-
4239 void translateObject(const std::vector<uint>& ObjIDs, const vec3& shift );
-
4240
-
4242
-
4247 void rotateObject(uint ObjID, float rot, const char* axis );
-
4248
-
4250
-
4255 void rotateObject(const std::vector<uint>& ObjIDs, float rot, const char* axis );
-
4256
-
4258
-
4263 void rotateObject(uint ObjID, float rot, const vec3& axis );
-
4264
-
4266
-
4271 void rotateObject(const std::vector<uint>& ObjIDs, float rot, const vec3& axis );
-
4272
-
4274
-
4280 void rotateObject( uint ObjID, float rot, const vec3& origin, const vec3& axis );
-
4281
-
4283
-
4289 void rotateObject( const std::vector<uint>& ObjIDs, float rot, const vec3& origin, const vec3& axis );
-
4290
-
4292
-
4296 void scaleObject( uint ObjID, const helios::vec3 &scalefact );
-
4297
-
4299
-
4303 void scaleObject( const std::vector<uint>& ObjIDs, const helios::vec3 &scalefact );
-
4304
-
4306
-
4309 std::vector<uint> getObjectPrimitiveUUIDs( uint ObjID ) const;
-
4310
-
4312
-
4315 std::vector<uint> getObjectPrimitiveUUIDs( const std::vector<uint> &ObjIDs) const;
-
4316
-
4318
-
4321 std::vector<uint> getObjectPrimitiveUUIDs( const std::vector<std::vector<uint> > &ObjIDs) const;
-
4322
-
4324
-
4327 helios::ObjectType getObjectType( uint ObjID ) const;
-
4328
-
4330
-
4333 Tile* getTileObjectPointer(uint ObjID ) const;
-
4334
-
4336
-
4339 float getTileObjectAreaRatio(const uint &ObjectID) const;
-
4340
-
4342
-
4345 std::vector<float> getTileObjectAreaRatio(const std::vector<uint> &ObjectID) const;
-
4346
-
4348
-
4352 void setTileObjectSubdivisionCount(const std::vector<uint> &ObjectIDs, int2 new_subdiv);
-
4353
-
4355
-
4359 void setTileObjectSubdivisionCount(const std::vector<uint> &ObjectIDs, float area_ratio);
-
4360
-
4361
-
4363
-
4368 helios::vec3 getTileObjectCenter(uint &ObjectID) const;
-
4369
-
4370
-
4372
-
4375 helios::vec2 getTileObjectSize(uint &ObjectID) const;
-
4376
-
4378
-
4381 helios::int2 getTileObjectSubdivisionCount(uint &ObjectID) const;
-
4382
-
4384
-
4387 helios::vec3 getTileObjectNormal(uint &ObjectID) const;
-
4388
-
4390
-
4393 std::vector<helios::vec2> getTileObjectTextureUV(uint &ObjectID) const;
-
4394
-
4396
-
4399 std::vector<helios::vec3> getTileObjectVertices(uint &ObjectID) const;
-
4400
-
4402
-
4405 Sphere* getSphereObjectPointer(uint ObjID ) const;
-
4406
-
4408
-
4411 helios::vec3 getSphereObjectCenter(uint &ObjectID) const;
-
4412
-
4414
-
4417 helios::vec3 getSphereObjectRadius(uint &ObjID) const;
-
4418
-
4420
-
4423 uint getSphereObjectSubdivisionCount(uint &ObjectID) const;
-
4424
-
4426
-
4428 Tube* getTubeObjectPointer(uint ObjID ) const;
-
4429
-
4431
-
4434 uint getTubeObjectSubdivisionCount(uint &ObjectID) const;
-
4435
-
4437
-
4440 std::vector<helios::vec3> getTubeObjectNodes(uint &ObjectID) const;
-
4441
-
4443
-
4446 std::vector<float> getTubeObjectNodeRadii(uint &ObjectID) const;
-
4447
-
4449
-
4452 std::vector<RGBcolor> getTubeObjectNodeColors(uint &ObjectID) const;
-
4453
-
4454
-
4456
-
4459 Box* getBoxObjectPointer(uint ObjID ) const;
-
4460
-
4462
-
4465 helios::vec3 getBoxObjectCenter(uint &ObjectID) const;
-
4466
-
4468
-
4471 helios::vec3 getBoxObjectSize(uint &ObjectID) const;
-
4472
-
4474
-
4477 helios::int3 getBoxObjectSubdivisionCount(uint &ObjectID) const;
-
4478
-
4480
-
4483 Disk* getDiskObjectPointer(uint ObjID ) const;
-
4484
-
4486
-
4489 helios::vec3 getDiskObjectCenter(uint &ObjectID) const;
-
4490
-
4492
-
4495 helios::vec2 getDiskObjectSize(uint &ObjectID) const;
-
4496
-
4498
-
4501 uint getDiskObjectSubdivisionCount(uint &ObjectID) const;
-
4502
-
4504
-
4506 Polymesh* getPolymeshObjectPointer(uint ObjID ) const;
-
4507
-
4509
-
4512 Cone* getConeObjectPointer( uint ObjID ) const;
-
4513
-
4515
-
4518 uint getConeObjectSubdivisionCount(uint &ObjectID) const;
-
4519
-
4521
-
4524 std::vector<helios::vec3> getConeObjectNodes(uint &ObjectID) const;
-
4525
-
4527
-
4530 std::vector<float> getConeObjectNodeRadii(uint &ObjectID) const;
-
4531
-
4533
-
4536 helios::vec3 getConeObjectNode(uint &ObjectID, int number) const;
-
4537
-
4539
-
4542 float getConeObjectNodeRadius(uint &ObjectID, int number) const;
-
4543
-
4545
-
4548 helios::vec3 getConeObjectAxisUnitVector(uint &ObjectID) const;
-
4549
-
4551
-
4555 float getConeObjectLength(uint &ObjectID) const;
-
4556
-
4558
-
4567 uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv);
-
4568
-
4570
-
4579 uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const RGBcolor &color );
-
4580
-
4582
-
4591 uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const char* texturefile );
-
4592
-
4594
-
4602 uint addSphereObject(uint Ndivs, const vec3 &center, float radius );
-
4603
-
4605
-
4613 uint addSphereObject(uint Ndivs, const vec3 &center, float radius, const RGBcolor &color );
-
4614
-
4616
-
4624 uint addSphereObject(uint Ndivs, const vec3 &center, float radius, const char* texturefile );
-
4625
-
4627
-
4635 uint addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius );
-
4636
-
4638
-
4646 uint addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius, const RGBcolor &color );
-
4647
-
4649
-
4657 uint addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius, const char* texturefile );
-
4658
-
4660
-
4669 uint addTubeObject(uint Ndivs, const std::vector<vec3> &nodes, const std::vector<float> &radius );
-
4670
-
4672
-
4681 uint addTubeObject( uint Ndivs, const std::vector<vec3> &nodes, const std::vector<float> &radius, const std::vector<RGBcolor> &color );
-
4682
-
4684
-
4693 uint addTubeObject( uint Ndivs, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile );
-
4694
-
4696
-
4705 uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv );
-
4706
-
4708
-
4717 uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color );
-
4718
-
4720
-
4729 uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile );
-
4730
-
4732
-
4742 uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color, bool reverse_normals );
-
4743
-
4745
-
4754 uint addBoxObject(vec3 center, const vec3 &size, const int3 &subdiv, const char* texturefile, bool reverse_normals );
-
4755
-
4757
-
4766 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size );
-
4767
-
4769
-
4778 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation );
-
4779
-
4781
-
4790 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
-
4791
-
4793
-
4802 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
-
4803
-
4805
-
4815 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file );
-
4816
-
4818
-
4827 uint addDiskObject(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
-
4828
-
4830
-
4839 uint addDiskObject(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
-
4840
-
4842
-
4852 uint addDiskObject(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file );
-
4853
-
4855
-
4860 uint addPolymeshObject(const std::vector<uint> &UUIDs );
-
4861
-
4863
-
4874 uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1 );
-
4875
-
4877
-
4888 uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const RGBcolor &color );
-
4889
-
4891
-
4902 uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const char* texturefile );
-
4903
-
4905
-
4913 std::vector<uint> addSphere(uint Ndivs, const vec3 &center, float radius );
-
4914
-
4916
-
4924 std::vector<uint> addSphere(uint Ndivs, const vec3 &center, float radius, const RGBcolor &color );
-
4925
-
4927
-
4935 std::vector<uint> addSphere(uint Ndivs, const vec3 &center, float radius, const char* texturefile );
-
4936
-
4938
-
4947 std::vector<uint> addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv );
-
4948
-
4950
-
4959 std::vector<uint> addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const RGBcolor &color );
-
4960
-
4962
-
4971 std::vector<uint> addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const char* texturefile );
-
4972
-
4974
-
4983 std::vector<uint> addTube(uint Ndivs, const std::vector<vec3> &nodes, const std::vector<float> &radius );
-
4984
-
4986
-
4995 std::vector<uint> addTube(uint Ndivs, const std::vector<vec3> &nodes, const std::vector<float> &radius, const std::vector<RGBcolor> &color );
-
4996
-
4998
-
5007 std::vector<uint> addTube(uint Ndivs, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile );
-
5008
-
5010
-
5019 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv );
-
5020
-
5022
-
5031 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color );
-
5032
-
5034
-
5043 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile );
-
5044
-
5046
-
5056 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color, bool reverse_normals );
-
5057
-
5059
-
5068 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile, bool reverse_normals );
-
5069
-
5071
-
5080 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size );
-
5081
-
5083
-
5092 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation );
-
5093
-
5095
-
5104 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
-
5105
-
5107
-
5116 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
-
5117
-
5119
-
5129 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file );
-
5130
-
5132
-
5141 std::vector<uint> addDisk(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
-
5142
-
5144
-
5153 std::vector<uint> addDisk(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
-
5154
-
5156
-
5166 std::vector<uint> addDisk(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file );
-
5167
-
5169
-
5179 std::vector<uint> addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1 );
-
5180
-
5182
-
5192 std::vector<uint> addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, RGBcolor &color );
-
5193
-
5195
-
5205 std::vector<uint> addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const char* texturefile );
-
5206
-
5208 /*** \param "label" Name of timeseries variable (e.g., temperature)
-
5209 * \param "value" Value of timeseries data point
-
5210 * \param "date" Date vector corresponding to the time of `value' (see \ref helios::Date "Date")
-
5211 * \param "time" Time vector corresponding to the time of `value' (see \ref helios::time "Time")
-
5212 * \ingroup timeseries
-
5213 */
-
5214 void addTimeseriesData(const char* label, float value, const Date &date, const Time &time );
-
5215
-
5217
-
5222 void setCurrentTimeseriesPoint(const char* label, uint index );
-
5223
-
5225
-
5232 float queryTimeseriesData(const char* label, const Date &date, const Time &time ) const;
-
5233
-
5235
-
5240 float queryTimeseriesData( const char* label ) const;
-
5241
-
5243
-
5249 float queryTimeseriesData( const char* label, uint index ) const;
-
5250
-
5252
-
5258 Time queryTimeseriesTime( const char* label, uint index ) const;
-
5259
-
5261
-
5267 Date queryTimeseriesDate( const char* label, uint index ) const;
-
5268
-
5270
-
5274 uint getTimeseriesLength( const char* label ) const;
-
5275
-
5277
-
5281 bool doesTimeseriesVariableExist( const char* label ) const;
-
5282
-
5284 void loadTabularTimeseriesData( const std::string &data_file, const std::vector<std::string> &column_labels, const std::string &delimiter, const std::string &date_string_format="YYYYMMDD", uint headerlines=0 );
-
5285
-
5287
-
5292 void getDomainBoundingBox( helios::vec2& xbounds, helios::vec2& ybounds, helios::vec2& zbounds ) const;
-
5293
-
5295
-
5301 void getDomainBoundingBox( const std::vector<uint>& UUIDs, helios::vec2& xbounds, helios::vec2& ybounds, helios::vec2& zbounds ) const;
-
5302
-
5304
-
5308 void getDomainBoundingSphere( helios::vec3& center, float& radius ) const;
-
5309
-
5311
-
5316 void getDomainBoundingSphere( const std::vector<uint>& UUIDs, helios::vec3& center, float& radius ) const;
-
5317
-
5319
-
5322 void cropDomainX(const vec2 &xbounds );
-
5323
-
5325
-
5328 void cropDomainY(const vec2 &ybounds );
-
5329
-
5331
-
5334 void cropDomainZ(const vec2 &zbounds );
-
5335
-
5337
-
5343 void cropDomain(const std::vector<uint> &UUIDs, const vec2 &xbounds, const vec2 &ybounds, const vec2 &zbounds );
-
5344
-
5346
-
5351 void cropDomain(const vec2 &xbounds, const vec2 &ybounds, const vec2 &zbounds );
-
5352
-
5354
-
5360 void colorPrimitiveByDataPseudocolor( const std::vector<uint> &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors );
-
5361
-
5363
-
5371 void colorPrimitiveByDataPseudocolor( const std::vector<uint> &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors, float data_min, float data_max );
-
5372
-
5374
-
5380 std::vector<uint> loadXML( const char* filename, bool quiet = false );
-
5381
-
5383
-
5386 std::vector<std::string> getLoadedXMLFiles();
-
5387
-
5389
-
5393 void writeXML( const char* filename, bool quiet = false ) const;
-
5394
-
5396
-
5401 void writeXML( const char* filename, const std::vector<uint> &UUIDs, bool quiet = false ) const;
-
5402
-
5404
-
5409 void writeXML_byobject( const char* filename, const std::vector<uint> &UUIDs, bool quiet = false ) const;
-
5410
-
5412
-
5417 void writePrimitiveData( std::string filename, const std::vector<std::string> &column_format, bool print_header = false ) const;
-
5418
-
5420
-
5426 void writePrimitiveData( std::string filename, const std::vector<std::string> &column_format, const std::vector<uint> &UUIDs, bool print_header = false ) const;
-
5427
-
5429
-
5435 std::vector<uint> loadPLY(const char* filename, bool silent=false );
-
5436
-
5438
-
5447 std::vector<uint> loadPLY(const char* filename, const vec3 &origin, float height, const std::string &upaxis="YUP", bool silent=false );
-
5448
-
5450
-
5460 std::vector<uint> loadPLY(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const std::string &upaxis="YUP", bool silent=false );
-
5461
-
5463
-
5472 std::vector<uint> loadPLY(const char* filename, const vec3 &origin, float height, const RGBcolor &default_color, const std::string &upaxis="YUP", bool silent=false );
-
5473
-
5475
-
5485 std::vector<uint> loadPLY(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, const std::string &upaxis="YUP", bool silent=false );
-
5486
-
5488
-
5491 void writePLY( const char* filename ) const;
-
5492
-
5494
-
5498 std::vector<uint> loadOBJ(const char* filename, bool silent=false );
-
5499
-
5501
-
5510 std::vector<uint> loadOBJ(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, bool silent=false );
-
5511
-
5513
-
5523 std::vector<uint> loadOBJ(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, const char* upaxis, bool silent=false );
-
5524
-
5525
-
5527
-
5537 std::vector<uint> loadOBJ(const char* filename, const vec3 &origin, const helios::vec3 &scale, const SphericalCoord &rotation, const RGBcolor &default_color, const char* upaxis, bool silent=false );
-
5538
-
5540
-
5543 void writeOBJ( const std::string &filename ) const;
-
5544
-
5546
-
5550 void writeOBJ( const std::string &filename, const std::vector<uint> &UUIDs ) const;
-
5551
-
5553
-
5558 void writeOBJ( const std::string &filename, const std::vector<uint> &UUIDs, const std::vector<std::string> &primitive_dat_fields ) const;
-
5559
-
5561
-
5567 void setDate( int day, int month, int year );
-
5568
-
5570
-
5574 void setDate( helios::Date date );
-
5575
-
5577
-
5582 void setDate( int Julian_day, int year );
-
5583
-
5585
-
5589 helios::Date getDate() const;
-
5590
-
5592
-
5596 const char* getMonthString() const;
-
5597
-
5599
-
5603 int getJulianDate() const;
-
5604
-
5606
-
5611 void setTime( int minute, int hour );
-
5612
-
5614
-
5620 void setTime( int second, int minute, int hour );
-
5621
-
5623
-
5627 void setTime( helios::Time time );
-
5628
-
5630
-
5634 helios::Time getTime() const;
-
5635
-
5637
-
5640 float randu();
-
5641
-
5643
-
5648 float randu( float min, float max );
-
5649
-
5651
-
5656 int randu( int min, int max );
-
5657
-
5659 float randn();
-
5660
-
5662
-
5667 float randn( float mean, float stddev );
-
5668
-
5670
-
5674 void duplicatePrimitiveData( const char* existing_data_label, const char* copy_data_label );
-
5675
-
5677
-
5682 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, float &mean ) const;
-
5683
-
5685
-
5690 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, double &mean ) const;
-
5691
-
5693
-
5698 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &mean ) const;
-
5699
-
5701
-
5706 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &mean ) const;
-
5707
-
5709
-
5714 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &mean ) const;
-
5715
-
5717
-
5722 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, float &awt_mean ) const;
-
5723
-
5725
-
5730 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, double &awt_mean ) const;
-
5731
-
5733
-
5738 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &awt_mean ) const;
-
5739
-
5741
-
5746 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &awt_mean ) const;
-
5747
-
5749
-
5754 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &awt_mean ) const;
-
5755
-
5757
-
5762 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, float &sum ) const;
-
5763
-
5765
-
5770 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, double &sum ) const;
-
5771
-
5773
-
5778 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &sum ) const;
-
5779
-
5781
-
5786 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &sum ) const;
-
5787
-
5789
-
5794 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &sum ) const;
-
5795
-
5797
-
5802 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, float &awt_sum ) const;
-
5803
-
5805
-
5810 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, double &sum ) const;
-
5811
-
5813
-
5818 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &sum ) const;
-
5819
-
5821
-
5826 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &sum ) const;
-
5827
-
5829
-
5834 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &sum ) const;
-
5835
-
5837
-
5843 void scalePrimitiveData( const std::vector<uint> &UUIDs, const std::string &label, float scaling_factor );
-
5844
-
5846
-
5851 void scalePrimitiveData( const std::string &label, float scaling_factor );
-
5852
-
5854
-
5860 void incrementPrimitiveData( const std::vector<uint> &UUIDs, const char* label, int increment );
-
5861
-
5863
-
5869 void incrementPrimitiveData( const std::vector<uint> &UUIDs, const char* label, uint increment );
-
5870
-
5872
-
5878 void incrementPrimitiveData( const std::vector<uint> &UUIDs, const char* label, float increment );
-
5879
-
5881
-
5887 void incrementPrimitiveData( const std::vector<uint> &UUIDs, const char* label, double increment );
-
5888
-
5890
-
5896 void aggregatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::vector<std::string> &primitive_data_labels, const std::string &result_primitive_data_label );
-
5897
-
5899
-
5905 void aggregatePrimitiveDataProduct( const std::vector<uint> &UUIDs, const std::vector<std::string> &primitive_data_labels, const std::string &result_primitive_data_label );
-
5906
-
5908
-
5912 float sumPrimitiveSurfaceArea( const std::vector<uint> &UUIDs ) const;
-
5913
-
5915
-
5923 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, float filter_value, const std::string &comparator );
-
5924
-
5926
-
5934 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, double filter_value, const std::string &comparator );
-
5935
-
5936
-
5938
-
5946 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, int filter_value, const std::string &comparator );
-
5947
-
5949
-
5957 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, uint filter_value, const std::string &comparator );
-
5958
-
5960
-
5967 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, const std::string &filter_value );
-
5968
-
5969};
-
5970
-
5971}
-
5972
-
5973
-
5974
-
5975#endif
- -
void setSubdivisionCount(const helios::int3 &subdiv)
Set the number of box sub-patch divisions.
Definition: Context.cpp:3391
-
helios::int3 getSubdivisionCount() const
Get the number of sub-patch divisions of the box object in each Cartesian direction.
Definition: Context.cpp:3387
-
vec3 getCenter() const
Get the Cartesian coordinates of the center of the box object.
Definition: Context.cpp:3371
-
~Box() override=default
Box destructor.
-
vec3 getSize() const
Get the dimensions of the box object in each Cartesian direction.
Definition: Context.cpp:3352
- -
uint getObjectDataSize(const char *label) const
Get the size/length of object data.
-
void setPrimitiveUUIDs(const std::vector< uint > &UUIDs)
Method to set the UUIDs of object child primitives.
Definition: Context.cpp:2360
-
uint getPrimitiveCount() const
Return the number of primitives contained in the object.
Definition: Context.cpp:2123
-
void overrideTextureColor()
Override the color in the texture map for all primitives in the Compound Object, in which case the pr...
Definition: Context.cpp:2193
-
uint getObjectID() const
Get the unique identifier for the object.
Definition: Context.cpp:2115
-
std::string getTextureFile() const
Method to return the texture map file of an Object.
Definition: Context.cpp:2221
-
std::vector< std::string > listObjectData() const
Return labels for all object data for this particular object.
-
void scale(const helios::vec3 &scale)
Method to scale a compound object in the x-, y- and z-directions.
Definition: Context.cpp:2327
-
void deleteChildPrimitive(uint UUID)
Delete a single child member of the object.
Definition: Context.cpp:2364
-
bool hasTexture() const
Method to check whether this object has texture data.
Definition: Context.cpp:2213
-
void setTransformationMatrix(float(&T)[16])
Method to set the Affine transformation matrix of a Compound Object.
Definition: Context.cpp:2352
-
bool arePrimitivesComplete() const
Method to query whether all object primitives are in tact.
Definition: Context.cpp:2379
-
float getArea() const
Calculate the total one-sided surface area of the Compound Object.
Definition: Context.cpp:2157
-
void rotate(float rot, const char *axis)
Method to rotate a Compound Object about the x-, y-, or z-axis.
Definition: Context.cpp:2245
-
void translate(const helios::vec3 &shift)
Method to translate/shift a Compound Object.
Definition: Context.cpp:2225
-
bool doesObjectDataExist(const char *label) const
Check if object data 'label' exists.
-
helios::ObjectType getObjectType() const
Get an enumeration specifying the type of the object.
Definition: Context.cpp:2119
-
std::vector< uint > getPrimitiveUUIDs() const
Get the UUIDs for all primitives contained in the object.
Definition: Context.cpp:2128
-
HeliosDataType getObjectDataType(const char *label) const
Get the Helios data type of object data.
-
void clearObjectData(const char *label)
Clear the object data for this object.
-
void getTransformationMatrix(float(&T)[16]) const
Method to return the Affine transformation matrix of a Compound Object.
Definition: Context.cpp:2346
-
void getObjectData(const char *label, int &data) const
Get data associated with a object element (integer scalar)
-
void setColor(const helios::RGBcolor &color)
Method to set the diffuse color for all primitives in the Compound Object.
Definition: Context.cpp:2173
-
void setObjectData(const char *label, const int &data)
Add data value (int) associated with a object element.
-
void useTextureColor()
For all primitives in the Compound Object, use the texture map to color the primitives rather than th...
Definition: Context.cpp:2203
-
bool doesObjectContainPrimitive(uint UUID)
Check whether a primitive is a member of the object based on its UUID.
Definition: Context.cpp:2134
-
helios::vec3 getObjectCenter() const
Calculate the Cartesian (x,y,z) point of the center of a bounding box for the Compound Object.
Definition: Context.cpp:2140
- -
uint getSubdivisionCount() const
Get the number of sub-triangle divisions of the cone object.
Definition: Context.cpp:3560
-
float getNodeRadius(int node_index) const
Get the radius of a cone object node.
Definition: Context.cpp:3546
-
void setSubdivisionCount(uint subdiv)
Set the number of radial sub-triangle divisions.
Definition: Context.cpp:3564
-
helios::vec3 getNodeCoordinate(int node_index) const
Get the Cartesian coordinates of a cone object node.
Definition: Context.cpp:3514
-
helios::vec3 getAxisUnitVector() const
Get a unit vector pointing in the direction of the cone central axis.
Definition: Context.cpp:3568
-
std::vector< helios::vec3 > getNodeCoordinates() const
Get the Cartesian coordinates of each of the cone object nodes.
Definition: Context.cpp:3499
-
void scaleLength(float S)
Method to scale the length of the cone.
Definition: Context.cpp:3601
-
~Cone() override=default
Cone destructor.
-
void scaleGirth(float S)
Method to scale the girth of the cone.
Definition: Context.cpp:3650
-
float getLength() const
Get the length of the cone along the axial direction.
Definition: Context.cpp:3586
-
std::vector< float > getNodeRadii() const
Get the radius at each of the cone object nodes.
Definition: Context.cpp:3529
-
Stores the state associated with simulation.
-
void setPrimitiveColor(uint UUID, const helios::RGBcolor &color)
Method to set the diffuse color of a Primitive.
Definition: Context.cpp:6579
-
void getPrimitiveTransformationMatrix(uint UUID, float(&T)[16]) const
Method to return the Affine transformation matrix of a Primitive.
Definition: Context.cpp:6548
-
void scalePrimitiveData(const std::vector< uint > &UUIDs, const std::string &label, float scaling_factor)
Multiply primitive data values by a constant scaling factor for a subset of primitives.
-
std::vector< uint > loadPLY(const char *filename, bool silent=false)
Load geometry contained in a Stanford polygon file (.ply). Model will be placed at the origin with no...
-
helios::RGBcolor getPrimitiveColor(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition: Context.cpp:6567
-
std::vector< uint > loadXML(const char *filename, bool quiet=false)
Load inputs specified in an XML file.
-
uint copyObject(uint ObjID)
Make a copy of a Compound Objects from the context.
Definition: Context.cpp:2452
-
float randn()
Draw a random number from a normal distribution with mean = 0, stddev = 1.
Definition: Context.cpp:1147
-
Disk * getDiskObjectPointer(uint ObjID) const
Get a pointer to a Disk Compound Object.
Definition: Context.cpp:3409
-
void overrideObjectTextureColor(uint ObjID)
Override the color in the texture map for all primitives in the Compound Object, in which case the pr...
Definition: Context.cpp:7400
-
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition: Context.cpp:1349
-
void getObjectBoundingBox(uint ObjID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single object.
Definition: Context.cpp:7420
-
float getConeObjectLength(uint &ObjectID) const
get the length of a Cone object from the context
Definition: Context.cpp:7638
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition: Context.cpp:6493
-
void loadTabularTimeseriesData(const std::string &data_file, const std::vector< std::string > &column_labels, const std::string &delimiter, const std::string &date_string_format="YYYYMMDD", uint headerlines=0)
Load tabular weather data from text file into timeseries.
-
Box * getBoxObjectPointer(uint ObjID) const
Get a pointer to a Box Compound Object.
Definition: Context.cpp:3345
-
void cleanDeletedUUIDs(std::vector< uint > &UUIDs) const
Delete UUIDs from vector if primitives no longer exist (1D vector)
Definition: Context.cpp:1670
-
std::vector< helios::vec3 > getTubeObjectNodes(uint &ObjectID) const
get the nodes of a Tube object from the context
Definition: Context.cpp:7578
-
void getPrimitiveData(uint UUID, const char *label, int &data) const
Get data associated with a primitive element.
-
helios::vec2 getDiskObjectSize(uint &ObjectID) const
get the size of a Disk object from the context
Definition: Context.cpp:7606
-
int getJulianDate() const
Get simulation date by Julian day.
Definition: Context.cpp:1083
-
void deletePrimitive(uint UUID)
Delete a single primitive from the context.
Definition: Context.cpp:1442
-
helios::vec3 getConeObjectAxisUnitVector(uint &ObjectID) const
get the axis unit vector of a Cone object from the context
Definition: Context.cpp:7634
-
bool doesObjectDataExist(uint objID, const char *label) const
Check if primitive data 'label' exists.
-
helios::vec2 getTileObjectSize(uint &ObjectID) const
get the size of a tile object from the context
Definition: Context.cpp:7542
-
~Context()
Context destructor.
Definition: Context.cpp:6410
-
uint getPrimitiveParentObjectID(uint UUID) const
Method to return the ID of the parent object the primitive belongs to (default is object 0)
Definition: Context.cpp:6457
-
std::vector< uint > getAllObjectIDs() const
Get the IDs for all Compound Objects in the Context.
Definition: Context.cpp:2402
-
Cone * getConeObjectPointer(uint ObjID) const
Get a pointer to a Cone Compound Object.
Definition: Context.cpp:3492
-
void seedRandomGenerator(uint seed)
Set seed for random generator.
Definition: Context.cpp:45
-
void getObjectData(uint objID, const char *label, int &data) const
Get data associated with a compound object.
-
void printPrimitiveInfo(uint UUID) const
Prints primitive properties to console (useful for debugging purposes)
Definition: Context.cpp:6665
-
void markGeometryClean()
Mark the Context geometry as ``clean", meaning that the geometry has not been modified since last set...
Definition: Context.cpp:141
-
void getDomainBoundingSphere(helios::vec3 &center, float &radius) const
Get the center and radius of a sphere that bounds all primitives in the domain.
Definition: Context.cpp:1983
-
CompoundObject * getObjectPointer(uint ObjID) const
Get a pointer to a Compound Object.
Definition: Context.cpp:2387
-
void rotateObject(uint ObjID, float rot, const char *axis)
Rotate a single compound object about the x, y, or z axis.
Definition: Context.cpp:2657
-
helios::vec3 getTileObjectCenter(uint &ObjectID) const
Get the Cartesian (x,y,z) center position of a tile object.
Definition: Context.cpp:7538
-
helios::vec3 getPatchCenter(uint UUID) const
Get the Cartesian (x,y,z) center position of a patch element.
Definition: Context.cpp:1599
-
std::vector< uint > filterPrimitivesByData(const std::vector< uint > &UUIDs, const std::string &primitive_data_label, float filter_value, const std::string &comparator)
Filter a set of primitives based on their primitive data and a condition and float value.
-
std::vector< float > getTubeObjectNodeRadii(uint &ObjectID) const
get the node radii of a Tube object from the context
Definition: Context.cpp:7582
-
uint getObjectPrimitiveCount(uint ObjID) const
Method to return the number of primitives contained in the object.
Definition: Context.cpp:7346
-
std::vector< helios::vec3 > getConeObjectNodes(uint &ObjectID) const
get the nodes of a Cone object from the context
Definition: Context.cpp:7618
-
std::vector< std::string > getLoadedXMLFiles()
Get names of XML files that are currently loaded.
-
uint getTubeObjectSubdivisionCount(uint &ObjectID) const
get the subdivision count of a Tube object from the context
Definition: Context.cpp:7574
-
uint getPrimitiveDataSize(uint UUID, const char *label) const
Get the size/length of primitive data.
-
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition: Context.cpp:1121
-
void calculatePrimitiveDataSum(const std::vector< uint > &UUIDs, const std::string &label, float &sum) const
Calculate sum of primitive data values (float) for a subset of primitives.
-
helios::RGBAcolor getPrimitiveColorRGBA(uint UUID) const
Method to return the diffuse color of a Primitive with transparency.
Definition: Context.cpp:6575
-
void incrementPrimitiveData(const std::vector< uint > &UUIDs, const char *label, int increment)
Increase value of primitive data (int) by some value.
-
helios::vec3 getObjectCenter(uint ObjID) const
Method to return the Cartesian (x,y,z) point of the center of a bounding box for the object.
Definition: Context.cpp:7350
-
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition: Context.cpp:6599
-
uint getObjectCount() const
Get the total number of objects that have been created in the Context.
Definition: Context.cpp:2394
-
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition: Context.cpp:6615
-
void cropDomainZ(const vec2 &zbounds)
Crop the domain in the z-direction such that all primitives lie within some specified z interval.
Definition: Context.cpp:2061
-
uint getDiskObjectSubdivisionCount(uint &ObjectID) const
get the subdivision count of a Disk object from the context
Definition: Context.cpp:7610
-
std::vector< RGBcolor > getTubeObjectNodeColors(uint &ObjectID) const
get the node colors of a Tube object from the context
Definition: Context.cpp:7586
-
Polymesh * getPolymeshObjectPointer(uint ObjID) const
Get a pointer to a Polygon Mesh Compound Object.
Definition: Context.cpp:3469
-
void cropDomainX(const vec2 &xbounds)
Crop the domain in the x-direction such that all primitives lie within some specified x interval.
Definition: Context.cpp:2011
-
void setDate(int day, int month, int year)
Set simulation date by day, month, year.
Definition: Context.cpp:1010
-
void renamePrimitiveData(uint UUID, const char *old_label, const char *new_label)
Rename primitive data for a primitive.
-
void setPrimitiveParentObjectID(uint UUID, uint objID)
Method to set the ID of the parent object the primitive belongs to (default is object 0)
Definition: Context.cpp:6428
-
bool primitiveTextureHasTransparencyChannel(uint UUID) const
Check if primitive texture map has a transparency channel.
Definition: Context.cpp:6619
-
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition: Context.cpp:1363
-
void usePrimitiveTextureColor(uint UUID)
Use the texture map to color the primitive rather than the constant RGB color. This is function rever...
Definition: Context.cpp:6647
-
bool doesObjectContainPrimitive(uint ObjID, uint UUID)
Method to check if an Object contains a Primitive.
Definition: Context.cpp:7396
-
void duplicateObjectData(uint objID, const char *old_label, const char *new_label)
Duplicate/copy existing object data.
-
const char * getMonthString() const
Get a string corresponding to the month of the simulation date.
Definition: Context.cpp:1054
-
std::vector< uint > filterObjectsByData(const std::vector< uint > &ObjIDs, const char *object_data, float threshold, const char *comparator) const
Get a vector of object IDs that meet filtering criteria based on object data.
Definition: Context.cpp:2560
-
void setObjectColor(uint ObjID, const helios::RGBcolor &color)
Method to set the diffuse color of an Object.
Definition: Context.cpp:7376
-
bool isGeometryDirty() const
Query whether the Context geometry is ``dirty", meaning has the geometry been modified since last set...
Definition: Context.cpp:149
-
Context()
Context default constructor.
Definition: Context.cpp:20
-
bool doesGlobalDataExist(const char *label) const
Check if global data 'label' exists.
-
void aggregatePrimitiveDataProduct(const std::vector< uint > &UUIDs, const std::vector< std::string > &primitive_data_labels, const std::string &result_primitive_data_label)
Multiply primitive data values for each primitive together and store result in new primitive data.
-
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition: Context.cpp:6424
-
helios::vec3 getVoxelSize(uint UUID) const
Get the size of a voxel element.
Definition: Context.cpp:1637
-
void setObjectData(uint objID, const char *label, const int &data)
Add data value (int) associated with a compound object.
-
void clearObjectData(uint objID, const char *label)
Clear primitive data for a single primitive based on its objID.
-
void copyPrimitiveData(uint UUID, uint currentUUID)
copy all primitive data from one primitive to another
-
float getPrimitiveSolidFraction(uint UUID) const
Get fraction of primitive surface area that is non-transparent.
Definition: Context.cpp:6661
-
void translateObject(uint ObjID, const vec3 &shift)
Translate a single compound object.
Definition: Context.cpp:2647
-
void cropDomain(const std::vector< uint > &UUIDs, const vec2 &xbounds, const vec2 &ybounds, const vec2 &zbounds)
Crop specified UUIDs such that they lie within some specified axis-aligned box.
Definition: Context.cpp:2086
-
void cropDomainY(const vec2 &ybounds)
Crop the domain in the y-direction such that all primitives lie within some specified y interval.
Definition: Context.cpp:2036
-
helios::ObjectType getObjectType(uint ObjID) const
Get an enumeration specifying the type of the object.
Definition: Context.cpp:2731
-
void colorPrimitiveByDataPseudocolor(const std::vector< uint > &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors)
Overwrite primitive color based on a pseudocolor mapping of primitive data values.
Definition: Context.cpp:6100
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
-
helios::int2 getTileObjectSubdivisionCount(uint &ObjectID) const
get the subdivision count of a tile object from the context
Definition: Context.cpp:7546
-
void copyObjectData(uint objID, uint currentObjID)
copy all object data from one compound object to another
-
std::vector< std::string > listPrimitiveData(uint UUID) const
Return labels for all primitive data for this particular primitive.
-
std::vector< uint > getObjectPrimitiveUUIDs(uint ObjID) const
Get primitive UUIDs associated with compound object (single object ID input)
Definition: Context.cpp:2697
-
helios::vec3 getTileObjectNormal(uint &ObjectID) const
get the normal of a tile object from the context
Definition: Context.cpp:7550
-
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition: Context.cpp:1484
-
helios::int2 getPrimitiveTextureSize(uint UUID) const
Get the size (number of pixels) of primitive texture map image.
Definition: Context.cpp:6607
-
uint getConeObjectSubdivisionCount(uint &ObjectID) const
get the subdivision count of a Cone object from the context
Definition: Context.cpp:7614
-
void writeOBJ(const std::string &filename) const
Write geometry in the Context to a Wavefront file (.obj)
-
helios::vec3 getBoxObjectSize(uint &ObjectID) const
get the size of a Box object from the context
Definition: Context.cpp:7594
-
void renameGlobalData(const char *old_label, const char *new_label)
Rename global data.
-
helios::vec3 getBoxObjectCenter(uint &ObjectID) const
get the center of a Box object from the context
Definition: Context.cpp:7590
-
helios::vec3 getTriangleVertex(uint UUID, uint number) const
Get a single vertex of a Triangle based on an index.
Definition: Context.cpp:1617
-
helios::Time getTime() const
Get the simulation time.
Definition: Context.cpp:1117
-
helios::RGBcolor getPrimitiveColorRGB(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition: Context.cpp:6571
-
Context(const Context &)=delete
Deleted copy constructor to prevent copying of Context.
-
std::vector< uint > loadOBJ(const char *filename, bool silent=false)
Load geometry contained in a Wavefront OBJ file (.obj). Model will be placed at the origin without an...
-
void getDomainBoundingBox(helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const
Get a box that bounds all primitives in the domain.
Definition: Context.cpp:1913
-
void duplicatePrimitiveData(uint UUID, const char *old_label, const char *new_label)
Duplicate/copy primitive data.
-
void setPrimitiveTextureFile(uint UUID, const std::string &texturefile)
Set the texture map file for a primitive.
Definition: Context.cpp:6603
-
helios::vec3 getSphereObjectCenter(uint &ObjectID) const
get the center of a Sphere object from the context
Definition: Context.cpp:7562
-
Sphere * getSphereObjectPointer(uint ObjID) const
Get a pointer to a Sphere Compound Object.
Definition: Context.cpp:3203
-
void overridePrimitiveTextureColor(uint UUID)
Override the color in the texture map for all primitives in the Compound Object, in which case the pr...
Definition: Context.cpp:6637
-
void calculatePrimitiveDataMean(const std::vector< uint > &UUIDs, const std::string &label, float &mean) const
Calculate mean of primitive data values (float) for a subset of primitives.
-
std::vector< helios::vec2 > getTileObjectTextureUV(uint &ObjectID) const
get the texture UV coordinates of a tile object from the context
Definition: Context.cpp:7554
-
helios::vec3 getSphereObjectRadius(uint &ObjID) const
get the radius of a Sphere object from the context
Definition: Context.cpp:7566
-
std::vector< uint > getUniquePrimitiveParentObjectIDs(std::vector< uint > UUIDs) const
Method to return unique parent object IDs for a vector of primitive UUIDs.
Definition: Context.cpp:6462
-
HeliosDataType getGlobalDataType(const char *label) const
Get the Helios data type of global data.
-
helios::Date getDate() const
Get simulation date.
Definition: Context.cpp:1050
-
void printObjectInfo(uint ObjID) const
Prints object properties to console (useful for debugging purposes)
Definition: Context.cpp:6939
-
std::minstd_rand0 * getRandomGenerator()
Get the random number generator engine.
Definition: Context.cpp:49
-
size_t getGlobalDataSize(const char *label) const
Get the size/length of global data.
-
void getGlobalData(const char *label, int &data) const
Get global data value (scalar integer)
-
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition: Context.cpp:1659
-
const std::vector< std::vector< bool > > * getPrimitiveTextureTransparencyData(uint UUID) const
Get the transparency channel pixel data from primitive texture map. If transparency channel does not ...
Definition: Context.cpp:6627
-
bool doesObjectExist(uint ObjID) const
Check whether Compound Object exists in the Context.
Definition: Context.cpp:2398
-
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
-
void clearGlobalData(const char *label)
Delete/clear global data.
-
void renameObjectData(uint objID, const char *old_label, const char *new_label)
Rename existing object data.
-
void writePLY(const char *filename) const
Write geometry in the Context to a Stanford polygon file (.ply)
-
void setGlobalData(const char *label, const int &data)
Add global data value (int)
-
bool isPrimitiveTextureColorOverridden(uint UUID) const
Check if color of texture map is overridden by the diffuse R-G-B color of the primitive.
Definition: Context.cpp:6657
-
void deleteObject(uint ObjID)
Delete a single Compound Object from the context.
Definition: Context.cpp:2419
-
float getObjectArea(uint ObjID) const
Method to return the one-sided surface area of an object.
Definition: Context.cpp:7342
-
std::string getObjectTextureFile(uint ObjID) const
Method to return the texture map file of an Object.
Definition: Context.cpp:7354
-
std::vector< helios::vec3 > getTileObjectVertices(uint &ObjectID) const
get the vertices of a tile object from the context
Definition: Context.cpp:7558
-
void aggregatePrimitiveDataSum(const std::vector< uint > &UUIDs, const std::vector< std::string > &primitive_data_labels, const std::string &result_primitive_data_label)
Sum multiple primitive data values for each primitive together and store result in new primitive data...
-
void scalePrimitive(uint UUID, const helios::vec3 &S)
Scale a primitive using its UUID.
Definition: Context.cpp:1422
-
Tube * getTubeObjectPointer(uint ObjID) const
Get a pointer to a Tube Compound Object.
Definition: Context.cpp:3280
-
helios::vec2 getPatchSize(uint UUID) const
Get the size of a patch element.
Definition: Context.cpp:1590
-
void addTimeseriesData(const char *label, float value, const Date &date, const Time &time)
Add a data point to timeseries of data.
Definition: Context.cpp:1700
-
void writePrimitiveData(std::string filename, const std::vector< std::string > &column_format, bool print_header=false) const
Write primitive data to an ASCII text file for all primitives in the Context.
-
void markGeometryDirty()
Mark the Context geometry as ``dirty", meaning that the geometry has been modified since last set as ...
Definition: Context.cpp:145
-
void getPrimitiveBoundingBox(uint UUID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single primitive.
Definition: Context.cpp:6497
-
void writeXML(const char *filename, bool quiet=false) const
Write Context geometry and data to XML file for all UUIDs in the context.
-
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition: Context.cpp:6544
-
uint getObjectDataSize(uint objID, const char *label) const
Get the size/length of primitive data.
-
void calculatePrimitiveDataAreaWeightedSum(const std::vector< uint > &UUIDs, const std::string &label, float &awt_sum) const
Calculate sum of primitive data values (float) for a subset of primitives, where each value in the su...
-
std::vector< float > getConeObjectNodeRadii(uint &ObjectID) const
get the node radii of a Cone object from the context
Definition: Context.cpp:7622
-
void incrementGlobalData(const char *label, int increment)
Increase value of global data (int) by some value.
-
void clearPrimitiveData(uint UUID, const char *label)
Clear primitive data for a single primitive based on its UUID.
-
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
-
float getConeObjectNodeRadius(uint &ObjectID, int number) const
get a node radius of a Cone object from the context
Definition: Context.cpp:7630
-
helios::vec3 getDiskObjectCenter(uint &ObjectID) const
get the center of a Disk object from the context
Definition: Context.cpp:7602
-
float getTileObjectAreaRatio(const uint &ObjectID) const
Get the area ratio of a tile object (total object area / sub-patch area)
Definition: Context.cpp:2735
-
helios::vec3 getVoxelCenter(uint UUID) const
Get the Cartesian (x,y,z) center position of a voxel element.
Definition: Context.cpp:1646
-
void calculatePrimitiveDataAreaWeightedMean(const std::vector< uint > &UUIDs, const std::string &label, float &awt_mean) const
Calculate mean of primitive data values (float) for a subset of primitives, where each value in the m...
-
uint getSphereObjectSubdivisionCount(uint &ObjectID) const
get the subdivision count of a Sphere object from the context
Definition: Context.cpp:7570
-
helios::int3 getBoxObjectSubdivisionCount(uint &ObjectID) const
get the subdivision count of a Box object from the context
Definition: Context.cpp:7598
-
bool doesPrimitiveExist(uint UUID) const
Check if primitive exists for a given UUID.
Definition: Context.cpp:1565
-
bool areObjectPrimitivesComplete(uint objID) const
Method to query whether all object primitives are in tact.
Definition: Context.cpp:2383
-
Tile * getTileObjectPointer(uint ObjID) const
Get a pointer to a Tile Compound Object.
Definition: Context.cpp:3103
-
void useObjectTextureColor(uint ObjID)
For all primitives in the Compound Object, use the texture map to color the primitives rather than th...
Definition: Context.cpp:7410
-
helios::vec3 getConeObjectNode(uint &ObjectID, int number) const
get a node of a Cone object from the context
Definition: Context.cpp:7626
-
std::vector< std::string > listObjectData(uint ObjID) const
Return labels for all object data for this particular object.
-
void writeXML_byobject(const char *filename, const std::vector< uint > &UUIDs, bool quiet=false) const
Write Context geometry and data to XML file for a subset of compound object IDs in the context.
-
void setTime(int minute, int hour)
Set simulation time.
Definition: Context.cpp:1087
-
std::vector< helios::vec3 > getPrimitiveVertices(uint UUID) const
Method to return the (x,y,z) coordinates of the vertices of a Primitive.
Definition: Context.cpp:6562
-
void duplicateGlobalData(const char *old_label, const char *new_label)
Make a copy of global data.
-
void setObjectTransformationMatrix(uint ObjID, float(&T)[16])
Method to set the Affine transformation matrix of an Object.
Definition: Context.cpp:7362
-
void operator=(const Context &)=delete
Deleted assignment operator to prevent copying of Context.
-
static int selfTest()
Run a self-test of the Context. The Context self-test runs through validation checks of Context-relat...
Definition: selfTest.cpp:20
-
HeliosDataType getObjectDataType(uint objID, const char *label) const
Get the Helios data type of primitive data.
-
void setPrimitiveTransformationMatrix(uint UUID, float(&T)[16])
Method to set the Affine transformation matrix of a Primitive.
Definition: Context.cpp:6552
-
float sumPrimitiveSurfaceArea(const std::vector< uint > &UUIDs) const
Sum the one-sided surface area of a group of primitives.
-
void getObjectTransformationMatrix(uint ObjID, float(&T)[16]) const
Method to return the Affine transformation matrix of an Object.
Definition: Context.cpp:7358
-
void setTileObjectSubdivisionCount(const std::vector< uint > &ObjectIDs, int2 new_subdiv)
Change the subdivision count of a tile object.
Definition: Context.cpp:2773
-
bool objectHasTexture(uint ObjID) const
Method to check whether an Object has texture data.
Definition: Context.cpp:7372
-
void scaleObject(uint ObjID, const helios::vec3 &scalefact)
Method to scale a compound object in the x-, y- and z-directions.
Definition: Context.cpp:2687
- -
vec2 getSize() const
Get the lateral dimensions of the disk object.
Definition: Context.cpp:3416
-
int2 getSubdivisionCount() const
Get the number of sub-triangle divisions of the disk object.
Definition: Context.cpp:3448
-
~Disk() override=default
Disk destructor.
-
vec3 getCenter() const
Get the Cartesian coordinates of the center of the disk object.
Definition: Context.cpp:3432
-
void setSubdivisionCount(int2 subdiv)
Set the number of disk sub-triangle divisions.
Definition: Context.cpp:3452
- -
~Polymesh() override=default
Polymesh destructor.
- -
uint getSubdivisionCount() const
Get the number of sub-patch divisions of the sphere object.
Definition: Context.cpp:3256
-
helios::vec3 getRadius() const
Get the radius of the sphere.
Definition: Context.cpp:3210
-
vec3 getCenter() const
Get the Cartesian coordinates of the center of the sphere object.
Definition: Context.cpp:3240
-
void setSubdivisionCount(uint subdiv)
Set the number of sphere tesselation divisions.
Definition: Context.cpp:3260
-
~Sphere() override=default
Sphere destructor.
- -
std::string getTextureFile() const
Get the name/path of the texture map file.
Definition: Context.cpp:121
-
helios::int2 getSize() const
Get the size of the texture in pixels (horizontal x vertical)
Definition: Context.cpp:125
-
bool hasTransparencyChannel() const
Check whether the texture has a transparency channel.
Definition: Context.cpp:129
-
float getSolidFraction() const
Get the solid fraction of the texture transparency channel (if it exists)
Definition: Context.cpp:137
-
const std::vector< std::vector< bool > > * getTransparencyData() const
Get the data in the texture transparency channel (if it exists)
Definition: Context.cpp:133
- -
~Tile() override=default
Tile destructor.
-
vec3 getCenter() const
Get the Cartesian coordinates of the center of the tile object.
Definition: Context.cpp:3117
-
helios::int2 getSubdivisionCount() const
Get the number of sub-patch divisions of the tile.
Definition: Context.cpp:3134
-
void setSubdivisionCount(const helios::int2 &subdiv)
Set the number of tile sub-patch divisions.
Definition: Context.cpp:3138
-
std::vector< helios::vec2 > getTextureUV() const
Get the normalized (u,v) coordinates of the texture at each of the four corners of the tile object.
Definition: Context.cpp:3182
-
helios::vec2 getSize() const
Get the dimensions of the entire tile object.
Definition: Context.cpp:3110
-
std::vector< helios::vec3 > getVertices() const
Get the Cartesian coordinates of each of the four corners of the tile object.
Definition: Context.cpp:3143
-
vec3 getNormal() const
Get a unit vector normal to the tile object surface.
Definition: Context.cpp:3176
- -
~Tube() override=default
Tube destructor.
-
std::vector< float > getNodeRadii() const
Get the radius at each of the tube object nodes.
Definition: Context.cpp:3302
-
std::vector< helios::RGBcolor > getNodeColors() const
Get the colors at each of the tube object nodes.
Definition: Context.cpp:3319
-
std::vector< helios::vec3 > getNodes() const
Get the Cartesian coordinates of each of the tube object nodes.
Definition: Context.cpp:3287
-
uint getSubdivisionCount() const
Get the number of sub-triangle divisions of the tube object.
Definition: Context.cpp:3323
-
void setSubdivisionCount(uint subdiv)
Set the number of sphere tesselation divisions.
Definition: Context.cpp:3327
- -
static int parse_data_vec3(const pugi::xml_node &node_data, std::vector< vec3 > &data)
Parse vector data of type 'vec3' within an XML tag.
-
static int parse_data_int2(const pugi::xml_node &node_data, std::vector< int2 > &data)
Parse vector data of type 'int2' within an XML tag.
-
static int parse_radius(const pugi::xml_node &node_data, std::vector< float > &radius)
Parse the value within a <radius> (radius at nodes of a tube or cone) tag.
-
static int parse_data_float(const pugi::xml_node &node_data, std::vector< float > &data)
Parse vector data of type 'float' within an XML tag.
-
static int parse_transform(const pugi::xml_node &node_data, float(&transform)[16])
Parse the value within a <transform> (transformation matrix) tag.
-
static int parse_data_uint(const pugi::xml_node &node_data, std::vector< uint > &data)
Parse vector data of type 'uint' within an XML tag.
-
static int parse_subdivisions(const pugi::xml_node &node_data, uint &subdivisions)
Parse the value within a <subdivisions> (object sub-primitive resolution) tag.
-
static int parse_data_vec4(const pugi::xml_node &node_data, std::vector< vec4 > &data)
Parse vector data of type 'vac4' within an XML tag.
-
static int parse_data_int3(const pugi::xml_node &node_data, std::vector< int3 > &data)
Parse vector data of type 'int3' within an XML tag.
-
static int parse_data_string(const pugi::xml_node &node_data, std::vector< std::string > &data)
Parse vector data of type 'string' within an XML tag.
-
static int parse_data_int(const pugi::xml_node &node_data, std::vector< int > &data)
Parse vector data of type 'int' within an XML tag.
-
static int parse_texture(const pugi::xml_node &node_data, std::string &texture)
Parse the value within an <texture> (path to image texture) tag.
-
static int parse_data_vec2(const pugi::xml_node &node_data, std::vector< vec2 > &data)
Parse vector data of type 'vec2' within an XML tag.
-
static int parse_data_double(const pugi::xml_node &node_data, std::vector< double > &data)
Parse vector data of type 'double' within an XML tag.
-
static int parse_solid_fraction(const pugi::xml_node &node_data, float &solid_fraction)
Parse the value within a <solid_fraction> (primitive solid fraction) tag.
-
static int parse_objID(const pugi::xml_node &node_data, uint &objID)
Parse the value within an <objID> (object ID) tag.
-
static int parse_textureUV(const pugi::xml_node &node_data, std::vector< vec2 > &uvs)
Parse the value within a <textureUV> (texture coordinates) tag.
-
static int parse_nodes(const pugi::xml_node &node_data, std::vector< vec3 > &nodes)
Parse the value within a <nodes> (coordinates defining nodes of a tube or cone) tag.
-
static int parse_data_int4(const pugi::xml_node &node_data, std::vector< int4 > &data)
Parse vector data of type 'int4' within an XML tag.
-
static int parse_vertices(const pugi::xml_node &node_data, std::vector< float > &vertices)
Parse the value within a <vertices> (primitive vertex coordinates) tag.
- -
uint addDiskObject(uint Ndivs, const helios::vec3 &center, const helios::vec2 &size)
Add new Disk geometric primitive to the Context given its center, and size.
Definition: Context.cpp:4637
-
uint addTubeObject(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition: Context.cpp:4112
-
uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone compound object to the Context.
Definition: Context.cpp:4813
-
std::vector< uint > addDisk(uint Ndivs, const helios::vec3 &center, const helios::vec2 &size)
Add new Disk geometric primitive to the Context given its center, and size.
Definition: Context.cpp:5784
-
std::vector< uint > addBox(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition: Context.cpp:5572
-
uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition: Context.cpp:4375
-
uint addPolymeshObject(const std::vector< uint > &UUIDs)
Add new Polymesh Compound Object.
Definition: Context.cpp:4785
-
std::vector< uint > addSphere(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition: Context.cpp:5052
-
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition: Context.cpp:5333
-
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition: Context.cpp:5218
-
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition: Context.cpp:3937
-
std::vector< uint > addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone to the Context.
Definition: Context.cpp:5890
-
uint addSphereObject(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition: Context.cpp:3698
-
float min(const std::vector< float > &vect)
Minimum value of a vector of floats.
Definition: global.cpp:905
-
float max(const std::vector< float > &vect)
Maximum value of a vector of floats.
Definition: global.cpp:951
-
float sum(const std::vector< float > &vect)
Sum of a vector of floats.
Definition: global.cpp:874
-
float mean(const std::vector< float > &vect)
Mean value of a vector of floats.
Definition: global.cpp:889
-
uint addTriangle(const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2)
Add new Triangle geometric primitive.
Definition: Context.cpp:1271
-
uint getPrimitiveCount() const
Get the total number of Primitives in the Context.
Definition: Context.cpp:1655
-
uint addVoxel(const helios::vec3 &center, const helios::vec3 &size)
Add new Voxel geometric primitive.
Definition: Context.cpp:1315
-
uint addPatch()
Add new default Patch geometric primitive, which is centered at the origin (0,0,0),...
Definition: Context.cpp:1155
-
void setCurrentTimeseriesPoint(const char *label, uint index)
Set the Context date and time by providing the index of a timeseries data point.
Definition: Context.cpp:1763
-
Time queryTimeseriesTime(const char *label, uint index) const
Get the time associated with a timeseries data point.
Definition: Context.cpp:1835
-
uint getTimeseriesLength(const char *label) const
Get the length of timeseries data.
Definition: Context.cpp:1891
-
float queryTimeseriesData(const char *label, const Date &date, const Time &time) const
Get a timeseries data point by specifying a date and time vector.
Definition: Context.cpp:1771
-
bool doesTimeseriesVariableExist(const char *label) const
Query whether a timeseries variable exists.
Definition: Context.cpp:1903
-
Date queryTimeseriesDate(const char *label, uint index) const
Get the date associated with a timeseries data point.
Definition: Context.cpp:1871
- - -
R-G-B-A color vector.
-
R-G-B color vector.
-
Vector of spherical coordinates (elevation,azimuth)
- -
Vector of two elements of type 'int'.
-
Vector of three elements of type 'int'.
-
Vector of four elements of type 'int'.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
-
Vector of four elements of type 'float'.
-
- - - - diff --git a/doc/html/_context_8cpp.html b/doc/html/_context_8cpp.html index 18c53e8c1..8df290885 100644 --- a/doc/html/_context_8cpp.html +++ b/doc/html/_context_8cpp.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+ +
InputOutput.cpp File Reference
+
+
+
#include "PlantArchitecture.h"
+
+

Go to the source code of this file.

+ + + + +

+Functions

size_t findShootClosingBracket (const std::string &lstring)
 
+

Detailed Description

+

Routines for reading and writing plant geometry in the plant architecture plug-in.

+

Copyright (C) 2016-2024 Brian Bailey

+

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.

+

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

+ +

Definition in file InputOutput.cpp.

+

Function Documentation

+ +

◆ findShootClosingBracket()

+ +
+
+ + + + + + + + +
size_t findShootClosingBracket (const std::string & lstring)
+
+ +

Definition at line 250 of file InputOutput.cpp.

+ +
+
+
+ + + + diff --git a/doc/html/_input_output_8cpp_source.html b/doc/html/_input_output_8cpp_source.html new file mode 100644 index 000000000..b6b2755d0 --- /dev/null +++ b/doc/html/_input_output_8cpp_source.html @@ -0,0 +1,506 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
InputOutput.cpp
+
+
+Go to the documentation of this file.
1
+
16#include "PlantArchitecture.h"
+
17
+
18using namespace helios;
+
19
+
20std::string PlantArchitecture::makeShootString(const std::string &current_string, const std::shared_ptr<Shoot> &shoot, const std::vector<std::shared_ptr<Shoot>> & shoot_tree) const{
+
21
+
22 std::string outstring = current_string;
+
23
+
24 if(shoot->parent_shoot_ID != -1 ) {
+
25 outstring += "[";
+
26 }
+
27
+
28 outstring += "{" + std::to_string(rad2deg(shoot->base_rotation.pitch)) + "," + std::to_string(rad2deg(shoot->base_rotation.yaw)) + "," + std::to_string(rad2deg(shoot->base_rotation.roll)) + "," + std::to_string(shoot->shoot_parameters.gravitropic_curvature.val() /*\todo */) + "," + shoot->shoot_type_label + "}";
+
29
+
30 uint node_number = 0;
+
31 for( auto &phytomer: shoot->phytomers ){
+
32
+
33 float length = phytomer->internode_length;
+
34 float radius = phytomer->internode_radius_initial;
+
35
+
36 outstring += "Internode(" + std::to_string(length) + "," + std::to_string(radius) + "," + std::to_string(phytomer->phytomer_parameters.internode.pitch.val() /*\todo */ ) + ")";
+
37
+
38 outstring += "Petiole(" + std::to_string(phytomer->phytomer_parameters.petiole.length.val() /*\todo */ ) + "," + std::to_string(phytomer->phytomer_parameters.petiole.pitch.val() /*\todo */) + ")";
+
39
+
40 outstring += "Leaf(" + std::to_string(phytomer->phytomer_parameters.leaf.prototype_scale.val() /*\todo */) + "," + std::to_string(phytomer->phytomer_parameters.leaf.pitch.val() /*\todo */) + "," + std::to_string(phytomer->phytomer_parameters.leaf.yaw.val() /*\todo */) + "," + std::to_string(phytomer->phytomer_parameters.leaf.roll.val() /*\todo */) + ")";
+
41
+
42 if( shoot->childIDs.find(node_number)!=shoot->childIDs.end() ){
+
43 outstring = makeShootString(outstring, shoot_tree.at(shoot->childIDs.at(node_number)), shoot_tree );
+
44 }
+
45
+
46 node_number++;
+
47 }
+
48
+
49 if(shoot->parent_shoot_ID != -1 ) {
+
50 outstring += "]";
+
51 }
+
52
+
53 return outstring;
+
54
+
55}
+
56
+
57std::string PlantArchitecture::getPlantString(uint plantID) const{
+
58
+
59 auto plant_shoot_tree = &plant_instances.at(plantID).shoot_tree;
+
60
+
61 std::string out_string;
+
62
+
63 for( auto &shoot: *plant_shoot_tree ){
+
64 out_string = makeShootString(out_string, shoot, *plant_shoot_tree );
+
65 }
+
66
+
67 return out_string;
+
68
+
69}
+
70
+
71void PlantArchitecture::parseShootArgument(const std::string &shoot_argument, const std::map<std::string, PhytomerParameters> &phytomer_parameters, ShootParameters &shoot_parameters, AxisRotation &base_rotation, std::string &phytomer_label) {
+
72
+
73 //shoot argument order {}:
+
74 // 1. shoot base pitch/insertion angle (degrees)
+
75 // 2. shoot base yaw angle (degrees)
+
76 // 3. shoot roll angle (degrees)
+
77 // 4. gravitropic curvature (degrees/meter)
+
78 // 5. [optional] phytomer parameters string
+
79
+
80 size_t pos_shoot_start = 0;
+
81
+
82 std::string s_argument = shoot_argument;
+
83
+
84 pos_shoot_start = s_argument.find(',');
+
85 if( pos_shoot_start == std::string::npos ){
+
86 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): Shoot brackets '{}' does not have the correct number of values given.");
+
87 }
+
88 float insertion_angle = std::stof(s_argument.substr(0, pos_shoot_start));
+
89 s_argument.erase(0, pos_shoot_start + 1);
+
90 base_rotation.pitch = deg2rad(insertion_angle);
+
91
+
92 pos_shoot_start = s_argument.find(',');
+
93 if( pos_shoot_start == std::string::npos ){
+
94 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): Shoot brackets '{}' does not have the correct number of values given.");
+
95 }
+
96 float shoot_yaw = std::stof(s_argument.substr(0, pos_shoot_start));
+
97 s_argument.erase(0, pos_shoot_start + 1);
+
98 base_rotation.yaw = deg2rad(shoot_yaw);
+
99
+
100 pos_shoot_start = s_argument.find(',');
+
101 if( pos_shoot_start == std::string::npos ){
+
102 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): Shoot brackets '{}' does not have the correct number of values given.");
+
103 }
+
104 float shoot_roll = std::stof(s_argument.substr(0, pos_shoot_start));
+
105 s_argument.erase(0, pos_shoot_start + 1);
+
106 base_rotation.roll = deg2rad(shoot_roll);
+
107
+
108 pos_shoot_start = s_argument.find(',');
+
109 if( pos_shoot_start == std::string::npos ){
+
110 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): Shoot brackets '{}' does not have the correct number of values given.");
+
111 }
+
112 float shoot_curvature = std::stof(s_argument.substr(0, pos_shoot_start));
+
113 s_argument.erase(0, pos_shoot_start + 1);
+
114 shoot_parameters.gravitropic_curvature = shoot_curvature;
+
115
+
116 if( pos_shoot_start != std::string::npos ) {
+
117 pos_shoot_start = s_argument.find(',');
+
118 phytomer_label = s_argument.substr(0, pos_shoot_start);
+
119 s_argument.erase(0, pos_shoot_start + 1);
+
120 if (phytomer_parameters.find(phytomer_label) == phytomer_parameters.end()) {
+
121 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): Phytomer parameters with label " + phytomer_label + " was not provided to PlantArchitecture::generatePlantFromString().");
+
122 }
+
123 shoot_parameters.phytomer_parameters = phytomer_parameters.at(phytomer_label);
+
124 }else{
+
125 phytomer_label = phytomer_parameters.begin()->first;
+
126 shoot_parameters.phytomer_parameters = phytomer_parameters.begin()->second;
+
127 }
+
128
+
129}
+
130
+
131void PlantArchitecture::parseInternodeArgument(const std::string &internode_argument, float &internode_radius, float &internode_length, PhytomerParameters &phytomer_parameters) {
+
132
+
133 //internode argument order Internode():
+
134 // 1. internode length (m)
+
135 // 2. internode radius (m)
+
136 // 3. internode pitch (degrees)
+
137
+
138 size_t pos_inode_start = 0;
+
139
+
140 std::string inode_argument = internode_argument;
+
141
+
142 pos_inode_start = inode_argument.find(',');
+
143 if( pos_inode_start == std::string::npos ){
+
144 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): 'Internode()' does not have the correct number of values given.");
+
145 }
+
146 internode_length = std::stof(inode_argument.substr(0, pos_inode_start));
+
147 inode_argument.erase(0, pos_inode_start + 1);
+
148
+
149 pos_inode_start = inode_argument.find(',');
+
150 if( pos_inode_start == std::string::npos ){
+
151 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): 'Internode()' does not have the correct number of values given.");
+
152 }
+
153 internode_radius = std::stof(inode_argument.substr(0, pos_inode_start));
+
154 inode_argument.erase(0, pos_inode_start + 1);
+
155
+
156 pos_inode_start = inode_argument.find(',');
+
157 if( pos_inode_start != std::string::npos ){
+
158 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): 'Internode()' does not have the correct number of values given.");
+
159 }
+
160 float internode_pitch = std::stof(inode_argument.substr(0, pos_inode_start));
+
161 inode_argument.erase(0, pos_inode_start + 1);
+
162 phytomer_parameters.internode.pitch = internode_pitch;
+
163
+
164}
+
165
+
166void PlantArchitecture::parsePetioleArgument(const std::string& petiole_argument, PhytomerParameters &phytomer_parameters ){
+
167
+
168 //petiole argument order Petiole():
+
169 // 1. petiole length (m)
+
170 // 2. petiole pitch (degrees)
+
171
+
172 if( petiole_argument.empty() ){
+
173 phytomer_parameters.petiole.length = 0;
+
174 return;
+
175 }
+
176
+
177 size_t pos_petiole_start = 0;
+
178
+
179 std::string pet_argument = petiole_argument;
+
180
+
181 pos_petiole_start = pet_argument.find(',');
+
182 if( pos_petiole_start == std::string::npos ){
+
183 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): 'Petiole()' does not have the correct number of values given.");
+
184 }
+
185 float petiole_length = std::stof(pet_argument.substr(0, pos_petiole_start));
+
186 pet_argument.erase(0, pos_petiole_start + 1);
+
187 phytomer_parameters.petiole.length = petiole_length;
+
188
+
189 pos_petiole_start = pet_argument.find(',');
+
190 if( pos_petiole_start != std::string::npos ){
+
191 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): 'Petiole()' does not have the correct number of values given.");
+
192 }
+
193 float petiole_pitch = std::stof(pet_argument.substr(0, pos_petiole_start));
+
194 pet_argument.erase(0, pos_petiole_start + 1);
+
195 phytomer_parameters.petiole.pitch = petiole_pitch;
+
196
+
197}
+
198
+
199void PlantArchitecture::parseLeafArgument(const std::string& leaf_argument, PhytomerParameters &phytomer_parameters ){
+
200
+
201 //leaf argument order Leaf():
+
202 // 1. leaf scale factor
+
203 // 2. leaf pitch (degrees)
+
204 // 3. leaf yaw (degrees)
+
205 // 4. leaf roll (degrees)
+
206
+
207 if( leaf_argument.empty() ){
+
208 phytomer_parameters.leaf.prototype_scale = 0;
+
209 return;
+
210 }
+
211
+
212 size_t pos_leaf_start = 0;
+
213
+
214 std::string l_argument = leaf_argument;
+
215
+
216 pos_leaf_start = l_argument.find(',');
+
217 if( pos_leaf_start == std::string::npos ){
+
218 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): 'Leaf()' does not have the correct number of values given.");
+
219 }
+
220 float leaf_scale = std::stof(l_argument.substr(0, pos_leaf_start));
+
221 l_argument.erase(0, pos_leaf_start + 1);
+
222 phytomer_parameters.leaf.prototype_scale = leaf_scale;
+
223
+
224 pos_leaf_start = l_argument.find(',');
+
225 if( pos_leaf_start == std::string::npos ){
+
226 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): 'Leaf()' does not have the correct number of values given.");
+
227 }
+
228 float leaf_pitch = std::stof(l_argument.substr(0, pos_leaf_start));
+
229 l_argument.erase(0, pos_leaf_start + 1);
+
230 phytomer_parameters.leaf.pitch = leaf_pitch;
+
231
+
232 pos_leaf_start = l_argument.find(',');
+
233 if( pos_leaf_start == std::string::npos ){
+
234 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): 'Leaf()' does not have the correct number of values given.");
+
235 }
+
236 float leaf_yaw = std::stof(l_argument.substr(0, pos_leaf_start));
+
237 l_argument.erase(0, pos_leaf_start + 1);
+
238 phytomer_parameters.leaf.yaw = leaf_yaw;
+
239
+
240 pos_leaf_start = l_argument.find(',');
+
241 if( pos_leaf_start != std::string::npos ){
+
242 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): 'Leaf()' does not have the correct number of values given.");
+
243 }
+
244 float leaf_roll = std::stof(l_argument.substr(0, pos_leaf_start));
+
245 l_argument.erase(0, pos_leaf_start + 1);
+
246 phytomer_parameters.leaf.roll = leaf_roll;
+
247
+
248}
+
249
+
250size_t findShootClosingBracket(const std::string &lstring ){
+
251
+
252
+
253 size_t pos_open = lstring.find_first_of('[',1);
+
254 size_t pos_close = lstring.find_first_of(']', 1);
+
255
+
256 if( pos_open>pos_close ){
+
257 return pos_close;
+
258 }
+
259
+
260 while( pos_open!=std::string::npos ){
+
261 pos_open = lstring.find('[', pos_close+1);
+
262 pos_close = lstring.find(']', pos_close+1);
+
263 }
+
264
+
265 return pos_close;
+
266
+
267}
+
268
+
269void PlantArchitecture::parseStringShoot(const std::string &LString_shoot, uint plantID, int parentID, uint parent_node, const std::map<std::string, PhytomerParameters> &phytomer_parameters, ShootParameters &shoot_parameters) {
+
270
+
271 std::string lstring_tobeparsed = LString_shoot;
+
272
+
273 size_t pos_inode_start = 0;
+
274 std::string inode_delimiter = "Internode(";
+
275 std::string petiole_delimiter = "Petiole(";
+
276 std::string leaf_delimiter = "Leaf(";
+
277 bool base_shoot = true;
+
278 uint baseID;
+
279 AxisRotation shoot_base_rotation;
+
280
+
281 //parse shoot arguments
+
282 if( LString_shoot.front() != '{' ){
+
283 helios_runtime_error("ERROR (PlantArchitecture::parseStringShoot): Shoot string is not formatted correctly. All shoots should start with a curly bracket containing two arguments {X,Y}.");
+
284 }
+
285 size_t pos_shoot_end = lstring_tobeparsed.find('}');
+
286 std::string shoot_argument = lstring_tobeparsed.substr(1, pos_shoot_end - 1);
+
287 std::string phytomer_label;
+
288 parseShootArgument(shoot_argument, phytomer_parameters, shoot_parameters, shoot_base_rotation, phytomer_label);
+
289 lstring_tobeparsed.erase(0, pos_shoot_end + 1);
+
290
+
291 uint shoot_node_count = 0;
+
292 while ((pos_inode_start = lstring_tobeparsed.find(inode_delimiter)) != std::string::npos) {
+
293
+
294 if( pos_inode_start!=0 ){
+
295 helios_runtime_error("ERROR (PlantArchitecture::parseStringShoot): Shoot string is not formatted correctly.");
+
296 }
+
297
+
298 size_t pos_inode_end = lstring_tobeparsed.find(')');
+
299 std::string inode_argument = lstring_tobeparsed.substr(pos_inode_start + inode_delimiter.length(), pos_inode_end - pos_inode_start - inode_delimiter.length());
+
300 float internode_radius = 0;
+
301 float internode_length = 0;
+
302 parseInternodeArgument(inode_argument, internode_radius, internode_length, shoot_parameters.phytomer_parameters);
+
303 lstring_tobeparsed.erase(0, pos_inode_end + 1);
+
304
+
305 size_t pos_petiole_start = lstring_tobeparsed.find(petiole_delimiter);
+
306 size_t pos_petiole_end = lstring_tobeparsed.find(')');
+
307 std::string petiole_argument;
+
308 if( pos_petiole_start==0 ){
+
309 petiole_argument = lstring_tobeparsed.substr(pos_petiole_start + petiole_delimiter.length(), pos_petiole_end - pos_petiole_start - petiole_delimiter.length());
+
310 }else{
+
311 petiole_argument = "";
+
312 }
+
313 parsePetioleArgument(petiole_argument, shoot_parameters.phytomer_parameters);
+
314 if( pos_petiole_start==0 ) {
+
315 lstring_tobeparsed.erase(0, pos_petiole_end + 1);
+
316 }
+
317
+
318 size_t pos_leaf_start = lstring_tobeparsed.find(leaf_delimiter);
+
319 size_t pos_leaf_end = lstring_tobeparsed.find(')');
+
320 std::string leaf_argument;
+
321 if( pos_leaf_start==0 ){
+
322 leaf_argument = lstring_tobeparsed.substr(pos_leaf_start + leaf_delimiter.length(), pos_leaf_end - pos_leaf_start - leaf_delimiter.length());
+
323 }else{
+
324 leaf_argument = "";
+
325 }
+
326 parseLeafArgument(leaf_argument, shoot_parameters.phytomer_parameters);
+
327 if( pos_leaf_start==0 ) {
+
328 lstring_tobeparsed.erase(0, pos_leaf_end + 1);
+
329 }
+
330
+
331 //override phytomer creation function
+
332 shoot_parameters.phytomer_parameters.phytomer_creation_function = nullptr;
+
333
+
334 if( base_shoot ){ //this is the first phytomer of the shoot
+
335 defineShootType("shoot_"+phytomer_label, shoot_parameters);
+
336
+
337 if( parentID<0 ) { //this is the first shoot of the plant
+
338 baseID = addBaseStemShoot(plantID, 1, shoot_base_rotation, internode_radius, internode_length, 1.f, 1.f, "shoot_"+phytomer_label );
+
339 }else{ //this is a child of an existing shoot
+
340 baseID = addChildShoot(plantID, parentID, parent_node, 1, shoot_base_rotation, internode_radius, internode_length, 1.f, 1.f, "shoot_" + phytomer_label, 0);
+
341 }
+
342
+
343 base_shoot = false;
+
344 }else{
+
345 addPhytomerToShoot(plantID, baseID, shoot_parameters.phytomer_parameters, internode_radius, internode_length, 1, 1);
+
346 }
+
347
+
348 while( !lstring_tobeparsed.empty() && lstring_tobeparsed.substr(0,1) == "[" ){
+
349 size_t pos_shoot_bracket_end = findShootClosingBracket(lstring_tobeparsed);
+
350 if( pos_shoot_bracket_end == std::string::npos ){
+
351 helios_runtime_error("ERROR (PlantArchitecture::parseStringShoot): Shoot string is not formatted correctly. Shoots must be closed with a ']'.");
+
352 }
+
353 std::string lstring_child = lstring_tobeparsed.substr(1, pos_shoot_bracket_end-1 );
+
354 parseStringShoot(lstring_child, plantID, (int) baseID, shoot_node_count, phytomer_parameters, shoot_parameters);
+
355 lstring_tobeparsed.erase(0, pos_shoot_bracket_end + 1);
+
356 }
+
357
+
358 shoot_node_count++;
+
359 }
+
360
+
361}
+
362
+
363uint PlantArchitecture::generatePlantFromString(const std::string &generation_string, const PhytomerParameters &phytomer_parameters) {
+
364 std::map<std::string,PhytomerParameters> phytomer_parameters_map;
+
365 phytomer_parameters_map["default"] = phytomer_parameters;
+
366 return generatePlantFromString(generation_string, phytomer_parameters_map);
+
367}
+
368
+
369uint PlantArchitecture::generatePlantFromString(const std::string &generation_string, const std::map<std::string,PhytomerParameters> &phytomer_parameters) {
+
370
+
371 //check that first characters are 'Internode'
+
372// if( lsystems_string.substr(0,10)!="Internode(" ){
+
373// helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): First characters of string must be 'Internode('");
+
374// }
+
375 if(generation_string.front() != '{'){
+
376 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): First character of string must be '{'");
+
377 }
+
378
+
379 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
+
380 shoot_parameters.max_nodes = 200;
+
381 shoot_parameters.vegetative_bud_break_probability = 0;
+
382 shoot_parameters.vegetative_bud_break_time = 0;
+
383 shoot_parameters.phyllochron = 0;
+
384
+
385 //assign default phytomer parameters. This can be changed later if the optional phytomer parameters label is provided in the shoot argument '{}'.
+
386 if( phytomer_parameters.empty() ){
+
387 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): Phytomer parameters must be provided.");
+
388 }
+
389
+
390 uint plantID;
+
391
+
392 plantID = addPlantInstance(nullorigin, 0);
+
393
+
394 size_t pos_first_child_shoot = generation_string.find('[');
+
395
+
396 if( pos_first_child_shoot==std::string::npos ) {
+
397 pos_first_child_shoot = generation_string.length();
+
398 }
+
399
+
400 parseStringShoot(generation_string, plantID, -1, 0, phytomer_parameters, shoot_parameters);
+
401
+
402
+
403 return plantID;
+
404
+
405}
+ +
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
+
int addPhytomerToShoot(uint plantID, uint shootID, const PhytomerParameters &phytomer_parameters, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction)
Add a new phytomer at the terminal bud of a shoot.
+
void defineShootType(const std::string &shoot_type_label, const ShootParameters &shoot_params)
Define a new shoot type based on a set of ShootParameters.
+
uint addBaseStemShoot(uint plantID, uint current_node_number, const AxisRotation &base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label)
Define the stem/trunk shoot (base of plant) to start a new plant. This requires a plant instance has ...
+
uint addChildShoot(uint plantID, int parent_shoot_ID, uint parent_node_index, uint current_node_number, const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label, uint petiole_index=0)
Manually add a child shoot at the axillary bud of a phytomer.
+
std::minstd_rand0 * getRandomGenerator()
Get the random number generator engine.
Definition: Context.cpp:49
+
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition: global.cpp:29
+
float rad2deg(float rad)
Convert radians to degrees.
Definition: global.cpp:551
+
float deg2rad(float deg)
Convert degrees to radians.
Definition: global.cpp:547
+ + +
void(* phytomer_creation_function)(std::shared_ptr< Phytomer > phytomer_ptr, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age)
+ +
+ + + + diff --git a/doc/html/_leaf_optics_8cpp.html b/doc/html/_leaf_optics_8cpp.html index 5856d1913..f0087b39f 100644 --- a/doc/html/_leaf_optics_8cpp.html +++ b/doc/html/_leaf_optics_8cpp.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+ +
PlantArchitecture.cpp File Reference
+
+
+
#include "PlantArchitecture.h"
+#include <utility>
+
+

Go to the source code of this file.

+ + + + + + + + + + +

+Functions

float interpolateTube (const std::vector< float > &P, float frac)
 Interpolate the radius of a point along a tube.
 
helios::vec3 interpolateTube (const std::vector< vec3 > &P, float frac)
 Interpolate the position of a point along a tube.
 
std::vector< uint > makeTubeFromCones (uint radial_subdivisions, const std::vector< helios::vec3 > &vertices, const std::vector< float > &radii, const std::vector< helios::RGBcolor > &colors, helios::Context *context_ptr)
 
+

Detailed Description

+

Primary source file for plant architecture plug-in.

+

Copyright (C) 2016-2024 Brian Bailey

+

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.

+

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

+ +

Definition in file PlantArchitecture.cpp.

+

Function Documentation

+ +

◆ interpolateTube() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
float interpolateTube (const std::vector< float > & P,
float frac 
)
+
+ +

Interpolate the radius of a point along a tube.

+
Parameters
+ + + +
[in]PVector of radii making up the tube.
[in]fracFractional position along the tube.
+
+
+ +

Definition at line 22 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ interpolateTube() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
helios::vec3 interpolateTube (const std::vector< helios::vec3 > & P,
float frac 
)
+
+ +

Interpolate the position of a point along a tube.

+
Parameters
+ + + +
[in]PVector of 3D points making up the tube.
[in]fracFractional position along the tube.
+
+
+ +

Definition at line 52 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ makeTubeFromCones()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
std::vector< uint > makeTubeFromCones (uint radial_subdivisions,
const std::vector< helios::vec3 > & vertices,
const std::vector< float > & radii,
const std::vector< helios::RGBcolor > & colors,
helios::Contextcontext_ptr 
)
+
+ +

Definition at line 2473 of file PlantArchitecture.cpp.

+ +
+
+
+ + + + diff --git a/doc/html/_plant_architecture_8cpp_source.html b/doc/html/_plant_architecture_8cpp_source.html new file mode 100644 index 000000000..f873a02bb --- /dev/null +++ b/doc/html/_plant_architecture_8cpp_source.html @@ -0,0 +1,2678 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
PlantArchitecture.cpp
+
+
+Go to the documentation of this file.
1
+
16#include "PlantArchitecture.h"
+
17
+
18#include <utility>
+
19
+
20using namespace helios;
+
21
+
22float interpolateTube( const std::vector<float> &P, float frac ){
+
23
+
24 assert( frac>=0 && frac<=1 );
+
25 assert( !P.empty() );
+
26
+
27 float dl=1.f/float(P.size());
+
28
+
29 float f = 0;
+
30 for( int i=0; i<P.size()-1; i++ ){
+
31
+
32 float fplus = f+dl;
+
33
+
34 if( fplus>=1.f ){
+
35 fplus = 1.f+1e-3;
+
36 }
+
37
+
38 if( frac>=f && (frac<=fplus || fabs(frac-fplus)<0.0001 ) ){
+
39
+
40 float V = P.at(i) + (frac-f)/(fplus-f)*(P.at(i+1)-P.at(i));
+
41
+
42 return V;
+
43 }
+
44
+
45 f=fplus;
+
46 }
+
47
+
48 return P.front();
+
49
+
50}
+
51
+
52helios::vec3 interpolateTube( const std::vector<vec3> &P, float frac ){
+
53
+
54 assert( frac>=0 && frac<=1 );
+
55 assert( !P.empty() );
+
56
+
57 float dl=0.f;
+
58 for( int i=0; i<P.size()-1; i++ ){
+
59 dl+=(P.at(i+1)-P.at(i)).magnitude();
+
60 }
+
61
+
62 float f = 0;
+
63 for( int i=0; i<P.size()-1; i++ ){
+
64
+
65 float dseg = (P.at(i+1)-P.at(i)).magnitude();
+
66
+
67 float fplus = f+dseg/dl;
+
68
+
69 if( fplus>=1.f ){
+
70 fplus = 1.f+1e-3;
+
71 }
+
72
+
73 if( frac>=f && (frac<=fplus || fabs(frac-fplus)<0.0001 ) ){
+
74
+
75 vec3 V = P.at(i) + (frac-f)/(fplus-f)*(P.at(i+1)-P.at(i));
+
76
+
77 return V;
+
78 }
+
79
+
80 f=fplus;
+
81 }
+
82
+
83 return P.front();
+
84
+
85}
+
86
+
87PlantArchitecture::PlantArchitecture( helios::Context* context_ptr ) : context_ptr(context_ptr){
+
88 generator = context_ptr->getRandomGenerator();
+
89}
+
90
+ +
92
+
93PhytomerParameters::PhytomerParameters( std::minstd_rand0 *generator ) {
+
94
+
95 //--- internode ---//
+
96 internode.pitch.initialize( 20, generator );
+
97 internode.phyllotactic_angle.initialize(137.5, generator );
+
98 internode.color = RGB::forestgreen;
+
99 internode.length_segments = 1;
+
100 internode.radial_subdivisions = 7;
+
101
+
102 //--- petiole ---//
+
103 petiole.petioles_per_internode = 1;
+
104 petiole.pitch.initialize( 90, generator );
+
105 petiole.radius.initialize( 0.001, generator );
+
106 petiole.length.initialize( 0.05, generator );
+
107 petiole.curvature.initialize(0, generator);
+
108 petiole.taper.initialize( 0, generator );
+
109 petiole.color = RGB::forestgreen;
+
110 petiole.length_segments = 1;
+
111 petiole.radial_subdivisions = 7;
+
112
+
113 //--- leaf ---//
+
114 leaf.leaves_per_petiole = 1;
+
115 leaf.pitch.initialize( 0, generator );
+
116 leaf.yaw.initialize( 0, generator );
+
117 leaf.roll.initialize( 0, generator );
+
118 leaf.leaflet_offset.initialize( 0, generator );
+
119 leaf.leaflet_scale = 1;
+
120 leaf.prototype_scale.initialize(0.05,generator);
+
121 leaf.subdivisions = 1;
+
122
+
123 //--- peduncle ---//
+
124 peduncle.length.initialize(0.05,generator);
+
125 peduncle.radius.initialize(0.001, generator);
+
126 peduncle.pitch.initialize(0,generator);
+
127 peduncle.roll.initialize(0,generator);
+
128 peduncle.curvature.initialize(0,generator);
+
129 peduncle.length_segments = 3;
+
130 peduncle.radial_subdivisions = 7;
+
131
+
132 //--- inflorescence ---//
+
133 inflorescence.flowers_per_rachis.initialize(1, generator);
+
134 inflorescence.flower_offset.initialize(0, generator);
+
135 inflorescence.flower_arrangement_pattern = "alternate";
+
136 inflorescence.pitch.initialize(0,generator);
+
137 inflorescence.roll.initialize(0,generator);
+
138 inflorescence.flower_prototype_scale.initialize(0.0075,generator);
+
139 inflorescence.fruit_prototype_scale.initialize(0.0075,generator);
+
140 inflorescence.fruit_gravity_factor_fraction.initialize(0, generator);
+
141
+
142}
+
143
+ +
145
+
146ShootParameters::ShootParameters( std::minstd_rand0 *generator ) {
+
147
+
148 // ---- Geometric Parameters ---- //
+
149
+
150 max_nodes.initialize( 10, generator );
+
151
+
152 internode_radius_initial.initialize(0.001,generator);
+
153 internode_radius_max.initialize(1e6, generator);
+
154
+
155 child_insertion_angle_tip.initialize(20, generator);
+
156 child_insertion_angle_decay_rate.initialize(0, generator);
+
157
+
158 child_internode_length_max.initialize(0.02, generator);
+
159 child_internode_length_min.initialize(0.002, generator);
+
160 child_internode_length_decay_rate.initialize(0, generator);
+
161
+
162 base_roll.initialize(0, generator);
+
163 base_yaw.initialize(0, generator);
+
164
+
165 gravitropic_curvature.initialize(0, generator );
+
166 tortuosity.initialize(0, generator );
+
167
+
168 // ---- Growth Parameters ---- //
+
169
+
170 phyllochron.initialize(1, generator);
+
171 leaf_flush_count = 1;
+
172
+
173 elongation_rate.initialize(0.2, generator);
+
174 girth_growth_rate.initialize(0, generator);
+
175
+
176 vegetative_bud_break_time.initialize(5, generator);
+
177 vegetative_bud_break_probability.initialize(0,generator);
+
178 flower_bud_break_probability.initialize(0,generator);
+
179 fruit_set_probability.initialize(0,generator);
+
180
+
181
+
182 flowers_require_dormancy = false;
+
183 growth_requires_dormancy = false;
+
184
+
185 determinate_shoot_growth = true;
+
186
+
187}
+
188
+
189void ShootParameters::defineChildShootTypes( const std::vector<std::string> &a_child_shoot_type_labels, const std::vector<float> &a_child_shoot_type_probabilities ){
+
190
+
191 if( a_child_shoot_type_labels.size()!=a_child_shoot_type_probabilities.size() ){
+
192 helios_runtime_error("ERROR (ShootParameters::defineChildShootTypes): Child shoot type labels and probabilities must be the same size.");
+
193 }else if( a_child_shoot_type_labels.empty() ){
+
194 helios_runtime_error("ERROR (ShootParameters::defineChildShootTypes): Input argument vectors were empty.");
+
195 }else if( sum(a_child_shoot_type_probabilities)!=1.f ){
+
196 helios_runtime_error("ERROR (ShootParameters::defineChildShootTypes): Child shoot type probabilities must sum to 1.");
+
197 }
+
198
+
199 child_shoot_type_labels = a_child_shoot_type_labels;
+
200 child_shoot_type_probabilities = a_child_shoot_type_probabilities;
+
201
+
202}
+
203
+
204
+
205void PlantArchitecture::defineShootType( const std::string &shoot_type_label, const ShootParameters &shoot_params ) {
+
206 if( shoot_types.find(shoot_type_label)!=shoot_types.end() ){
+
207 //std::cerr <<"WARNING (PlantArchitecture::defineShootType): Shoot type label of " << shoot_type_label << " already exists." << std::endl;
+
208 shoot_types.at(shoot_type_label) = shoot_params;
+
209 }else {
+
210 shoot_types.emplace(shoot_type_label, shoot_params);
+
211 }
+
212}
+
213
+
214helios::vec3 Phytomer::getInternodeAxisVector(float stem_fraction) const{
+
215 return getAxisVector( stem_fraction, internode_vertices );
+
216}
+
217
+
218helios::vec3 Phytomer::getPetioleAxisVector(float stem_fraction, uint petiole_index) const {
+
219 if( petiole_index>=petiole_vertices.size() ){
+
220 helios_runtime_error("ERROR (Phytomer::getPetioleAxisVector): Petiole index out of range.");
+
221 }
+
222 return getAxisVector( stem_fraction, petiole_vertices.at(petiole_index) );
+
223}
+
224
+
225helios::vec3 Phytomer::getAxisVector( float stem_fraction, const std::vector<helios::vec3> &axis_vertices ) const{
+
226
+
227 assert( stem_fraction>=0 && stem_fraction<=1 );
+
228
+
229 float df = 0.1f;
+
230 float frac_plus, frac_minus;
+
231 if( stem_fraction+df<=1 ) {
+
232 frac_minus = stem_fraction;
+
233 frac_plus = stem_fraction + df;
+
234 }else{
+
235 frac_minus = stem_fraction-df;
+
236 frac_plus = stem_fraction;
+
237 }
+
238
+
239 vec3 node_minus = interpolateTube( axis_vertices, frac_minus );
+
240 vec3 node_plus = interpolateTube( axis_vertices, frac_plus );
+
241
+
242 vec3 norm = node_plus-node_minus;
+
243 norm.normalize();
+
244
+
245 return norm;
+
246
+
247}
+
248
+
249float Phytomer::getInternodeLength() const{
+
250
+
251 // \todo
+
252 return 0;
+
253}
+
254
+
255float Phytomer::getPetioleLength() const{
+
256
+
257 // \todo
+
258 return 0;
+
259}
+
260
+
261float Phytomer::getInternodeRadius( float stem_fraction ) const{
+
262
+
263 return interpolateTube( internode_radii, stem_fraction );
+
264
+
265}
+
266
+
267void Phytomer::setVegetativeBudState( BudState state ){
+
268 for( auto& petiole : vegetative_buds ){
+
269 for( auto& bud : petiole ) {
+
270 setVegetativeBudState(state, bud);
+
271 }
+
272 }
+
273}
+
274
+
275void Phytomer::setVegetativeBudState(BudState state, uint petiole_index, uint bud_index) {
+
276 if( petiole_index>=vegetative_buds.size() ){
+
277 helios_runtime_error("ERROR (Phytomer::setVegetativeBudState): Petiole index out of range.");
+
278 }
+
279 if( bud_index>=vegetative_buds.at(petiole_index).size() ){
+
280 helios_runtime_error("ERROR (Phytomer::setVegetativeBudState): Bud index out of range.");
+
281 }
+
282 setVegetativeBudState( state, vegetative_buds.at(petiole_index).at(bud_index) );
+
283}
+
284
+
285void Phytomer::setVegetativeBudState( BudState state, VegetativeBud &vbud ){
+
286 vbud.state = state;
+
287}
+
288
+
289void Phytomer::setFloralBudState( BudState state ) {
+
290 for( auto &petiole :floral_buds ) {
+
291 for ( auto &fbud : petiole ) {
+
292 setFloralBudState(state, fbud);
+
293 }
+
294 }
+
295}
+
296
+
297void Phytomer::setFloralBudState(BudState state, uint petiole_index, uint bud_index) {
+
298 if (petiole_index >= floral_buds.size()) {
+
299 helios_runtime_error("ERROR (Phytomer::setFloralBudState): Petiole index out of range.");
+
300 }
+
301 if (bud_index >= floral_buds.at(petiole_index).size()) {
+
302 helios_runtime_error("ERROR (Phytomer::setFloralBudState): Bud index out of range.");
+
303 }
+
304 setFloralBudState(state, floral_buds.at(petiole_index).at(bud_index));
+
305}
+
306
+
307void Phytomer::setFloralBudState(BudState a_state, FloralBud &fbud ) {
+
308
+
309 // If state is already at the desired state, do nothing
+
310 if (fbud.state == a_state) {
+
311 return;
+
312 } else if (a_state == BUD_DORMANT || a_state == BUD_ACTIVE ) {
+
313 fbud.state = a_state;
+
314 return;
+
315 }
+
316
+
317 // Delete geometry from previous reproductive state (if present)
+
318 context_ptr->deleteObject(inflorescence_objIDs.at(fbud.parent_petiole_index).at(fbud.bud_index));
+
319 inflorescence_objIDs.at(fbud.parent_petiole_index).at(fbud.bud_index).resize(0);
+
320 inflorescence_bases.at(fbud.parent_petiole_index).at(fbud.bud_index).resize(0);
+
321
+
322 if( build_context_geometry_peduncle ) {
+
323 context_ptr->deleteObject(peduncle_objIDs.at(fbud.parent_petiole_index).at(fbud.bud_index));
+
324 peduncle_objIDs.at(fbud.parent_petiole_index).at(fbud.bud_index).resize(0);
+
325 }
+
326
+
327 fbud.state = a_state;
+
328
+
329 if( a_state != BUD_DEAD ) { //add new reproductive organs
+
330
+
331 float pitch_adjustment;
+
332 float yaw_adjustment;
+
333 if (vegetative_buds.empty()) {
+
334 pitch_adjustment = 0;
+
335 yaw_adjustment = 0;
+
336 } else {
+
337 pitch_adjustment = fbud.bud_index * 0.1f * M_PI / float(vegetative_buds.size());
+
338 yaw_adjustment = -0.25f * M_PI + fbud.bud_index * 0.5f * M_PI / float(vegetative_buds.size());
+
339 }
+
340 addInflorescence(internode_vertices.back(), make_AxisRotation(pitch_adjustment, yaw_adjustment, 0), make_vec3(0, 0, 1), fbud);
+
341 fbud.time_counter = 0;
+
342 if (fbud.state == BUD_FRUITING) {
+
343 setInflorescenceScaleFraction(fbud, 0.1);
+
344 }
+
345
+
346 }
+
347
+
348
+
349}
+
350
+
351int Shoot::addPhytomer(const PhytomerParameters &params, const helios::vec3 internode_base_position, const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction,
+
352 float leaf_scale_factor_fraction) {
+
353
+
354 auto shoot_tree_ptr = &plant_architecture_ptr->plant_instances.at(plantID).shoot_tree;
+
355
+
356 //Determine the parent internode and petiole axes for rotation of the new phytomer
+
357 vec3 parent_internode_axis;
+
358 vec3 parent_petiole_axis;
+
359 if( phytomers.empty() ) { //very first phytomer on shoot
+
360 if(parent_shoot_ID == -1 ) { //very first shoot of the plant
+
361 parent_internode_axis = make_vec3(0, 0, 1);
+
362 parent_petiole_axis = make_vec3(0, -1, 0);
+
363 }else{ //first phytomer of a new shoot
+
364 assert(parent_shoot_ID < shoot_tree_ptr->size() && parent_node_index < shoot_tree_ptr->at(parent_shoot_ID)->phytomers.size() );
+
365 parent_internode_axis = shoot_tree_ptr->at(parent_shoot_ID)->phytomers.at(parent_node_index)->getInternodeAxisVector(1.f);
+
366 parent_petiole_axis = shoot_tree_ptr->at(parent_shoot_ID)->phytomers.at(parent_node_index)->getPetioleAxisVector(0.f, parent_petiole_index);
+
367 }
+
368 }else{ //additional phytomer being added to an existing shoot
+
369 parent_internode_axis = phytomers.back()->getInternodeAxisVector(1.f);
+
370 parent_petiole_axis = phytomers.back()->getPetioleAxisVector(0.f, 0);
+
371 }
+
372
+
373 std::shared_ptr<Phytomer> phytomer = std::make_shared<Phytomer>(params, this, phytomers.size(), parent_internode_axis, parent_petiole_axis, internode_base_position, shoot_base_rotation, internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, rank, plant_architecture_ptr->build_context_geometry_internode, plant_architecture_ptr->build_context_geometry_petiole, plant_architecture_ptr->build_context_geometry_peduncle, context_ptr);
+
374
+
375 //Initialize phytomer vegetative bud types and state
+
376 for( auto& petiole : phytomer->vegetative_buds ) {
+
377 for (auto &vbud: petiole) {
+
378
+
379 //sample the bud shoot type and initialize its state
+
380 std::string child_shoot_type_label;
+
381 if (sampleChildShootType(child_shoot_type_label)) {
+
382 phytomer->setVegetativeBudState( BUD_DORMANT, vbud );
+
383 vbud.shoot_type_label = child_shoot_type_label;
+
384 } else {
+
385 phytomer->setVegetativeBudState( BUD_DEAD, vbud );
+
386 }
+
387
+
388 // if the shoot type does not require dormancy, bud should be set to active
+
389 if (!shoot_parameters.growth_requires_dormancy && vbud.state != BUD_DEAD) {
+
390 phytomer->setVegetativeBudState( BUD_ACTIVE, vbud );
+
391 }
+
392
+
393 }
+
394 }
+
395
+
396 //Initialize phytomer floral bud types and state
+
397 uint petiole_index = 0;
+
398 for( auto& petiole : phytomer->floral_buds ) {
+
399 uint bud_index = 0;
+
400 for (auto &fbud: petiole) {
+
401
+
402 //Set state of phytomer buds
+
403 phytomer->setFloralBudState(BUD_DORMANT, fbud);
+
404
+
405 // if the shoot type does not require dormancy, bud should be set to active
+
406 if (!shoot_parameters.flowers_require_dormancy && fbud.state != BUD_DEAD) {
+
407 phytomer->setFloralBudState(BUD_ACTIVE, fbud);
+
408 }
+
409
+
410 fbud.parent_petiole_index = petiole_index;
+
411 fbud.bud_index = bud_index;
+
412
+
413 bud_index++;
+
414 }
+
415 petiole_index++;
+
416 }
+
417
+
418 shoot_tree_ptr->at(ID)->phytomers.push_back(phytomer);
+
419
+
420 //Set output object data 'age'
+
421 phytomer->age = 0;
+
422 if( phytomer->build_context_geometry_internode ) {
+
423 context_ptr->setObjectData(phytomer->internode_objIDs, "age", phytomer->age);
+
424 context_ptr->setObjectData(phytomer->internode_objIDs, "rank", rank);
+
425 context_ptr->setPrimitiveData( context_ptr->getObjectPrimitiveUUIDs(phytomer->internode_objIDs), "plantID", (int)plantID );
+
426 }
+
427 if( phytomer->build_context_geometry_petiole ) {
+
428 context_ptr->setObjectData(phytomer->petiole_objIDs, "age", phytomer->age);
+
429 context_ptr->setObjectData(phytomer->petiole_objIDs, "rank", phytomer->rank);
+
430 context_ptr->setPrimitiveData( context_ptr->getObjectPrimitiveUUIDs(phytomer->petiole_objIDs), "plantID", (int)plantID );
+
431 }
+
432 context_ptr->setObjectData(phytomer->leaf_objIDs, "age", phytomer->age);
+
433 context_ptr->setObjectData(phytomer->leaf_objIDs, "rank", phytomer->rank);
+
434 context_ptr->setPrimitiveData( context_ptr->getObjectPrimitiveUUIDs(phytomer->leaf_objIDs), "plantID", (int)plantID );
+
435
+
436 for( auto &petiole : phytomer->leaf_objIDs ){
+
437 for( uint objID : petiole ){
+
438 context_ptr->setPrimitiveData( context_ptr->getObjectPrimitiveUUIDs(objID), "leafID", (int)objID );
+
439 }
+
440 }
+
441
+
442 if( phytomer->phytomer_parameters.phytomer_creation_function != nullptr ) {
+
443 phytomer->phytomer_parameters.phytomer_creation_function(phytomer, current_node_number, this->parent_node_index, shoot_parameters.max_nodes.val(), rank, plant_architecture_ptr->plant_instances.at(plantID).current_age);
+
444 }
+
445
+
446 return (int)phytomers.size()-1;
+
447
+
448}
+
449
+
450void Shoot::breakDormancy(){
+
451
+
452 dormant = false;
+
453
+
454 int phytomer_ind = 0;
+
455 for( auto &phytomer : phytomers ) {
+
456
+
457 bool is_terminal_phytomer = (phytomer_ind == current_node_number - 1);
+
458 for( auto& petiole : phytomer->floral_buds ) {
+
459 for (auto &fbud: petiole) {
+
460 if (fbud.state != BUD_DEAD) {
+
461 phytomer->setFloralBudState( BUD_ACTIVE, fbud );
+
462 }
+
463 if (meristem_is_alive && is_terminal_phytomer) {
+
464 phytomer->setFloralBudState( BUD_ACTIVE, fbud );
+
465 }
+
466 fbud.time_counter = 0;
+
467 }
+
468 }
+
469 for( auto& petiole : phytomer->vegetative_buds ) {
+
470 for (auto &vbud: petiole) {
+
471 if (vbud.state != BUD_DEAD) {
+
472 phytomer->setVegetativeBudState(BUD_ACTIVE, vbud);
+
473 }
+
474 }
+
475 }
+
476
+
477 phytomer_ind++;
+
478 }
+
479
+
480}
+
481
+
482void Shoot::makeDormant(){
+
483
+
484 dormant = true;
+
485 dormancy_cycles++;
+
486
+
487 for( auto &phytomer : phytomers ){
+
488 for( auto& petiole : phytomer->floral_buds ) {
+
489 //all currently active lateral buds die at dormancy
+
490 for (auto &fbud: petiole) {
+
491 if (fbud.state != BUD_DORMANT) {
+
492 phytomer->setFloralBudState( BUD_DEAD, fbud );
+
493 }
+
494 }
+
495 }
+
496 for( auto& petiole : phytomer->vegetative_buds ) {
+
497 for (auto &vbud: petiole) {
+
498 if (vbud.state != BUD_DORMANT) {
+
499 phytomer->setVegetativeBudState(BUD_DEAD, vbud);
+
500 }
+
501 }
+
502 }
+
503 phytomer->removeLeaf();
+
504 phytomer->time_since_dormancy = 0;
+
505 }
+
506
+
507}
+
508
+
509void Shoot::terminateApicalBud(){
+
510 this->meristem_is_alive = false;
+
511}
+
512
+
513void Shoot::terminateAxillaryVegetativeBuds() {
+
514
+
515 for( auto &phytomer : phytomers ){
+
516 for( auto& petiole : phytomer->vegetative_buds ) {
+
517 for (auto &vbud: petiole) {
+
518 phytomer->setVegetativeBudState( BUD_DEAD, vbud );
+
519 }
+
520 }
+
521 }
+
522
+
523}
+
524
+
525Phytomer::Phytomer(const PhytomerParameters &params, Shoot *parent_shoot, uint phytomer_index, const helios::vec3 &parent_internode_axis, const helios::vec3 &parent_petiole_axis, helios::vec3 internode_base_origin,
+
526 const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, uint rank, bool build_context_geometry_internode, bool build_context_geometry_petiole,
+
527 bool build_context_geometry_peduncle, helios::Context *context_ptr)
+
528 : context_ptr(context_ptr), rank(rank), build_context_geometry_internode(build_context_geometry_internode), build_context_geometry_petiole(build_context_geometry_petiole), build_context_geometry_peduncle(build_context_geometry_peduncle){
+
529
+
530 phytomer_parameters = params; //note this needs to be an assignment operation not a copy in order to re-randomize all the parameters
+
531
+
532 ShootParameters parent_shoot_parameters = parent_shoot->shoot_parameters;
+
533
+
534 this->internode_radius_initial = internode_radius;
+
535 this->internode_radius_max = parent_shoot_parameters.internode_radius_max.val();
+
536 this->internode_length_max = internode_length_max;
+
537 this->shoot_index = make_int2(phytomer_index, parent_shoot_parameters.max_nodes.val()); //.x is the index of the phytomer along the shoot, .y is the maximum number of phytomers on the parent shoot.
+
538 this->rank = parent_shoot->rank;
+
539
+
540// if( internode_radius==0.f || internode_length_max==0.f || parent_shoot_parameters.internode_radius_max.val()==0.f ){
+
541// build_context_geometry_internode = false;
+
542// }
+
543
+
544 //Number of longitudinal segments for internode and petiole
+
545 //if Ndiv=0, use Ndiv=1 (but don't add any primitives to Context)
+
546 uint Ndiv_internode_length = std::max(uint(1), phytomer_parameters.internode.length_segments);
+
547 uint Ndiv_internode_radius = std::max(uint(3), phytomer_parameters.internode.radial_subdivisions);
+
548 uint Ndiv_petiole_length = std::max(uint(1), phytomer_parameters.petiole.length_segments);
+
549 uint Ndiv_petiole_radius = std::max(uint(3), phytomer_parameters.petiole.radial_subdivisions);
+
550
+
551 //Flags to determine whether internode geometry should be built in the Context. Not building all geometry can save memory and computation time.
+
552 if( phytomer_parameters.internode.length_segments==0 || phytomer_parameters.internode.radial_subdivisions<3 ){
+
553 build_context_geometry_internode = false;
+
554 }
+
555 if( phytomer_parameters.petiole.length_segments==0 || phytomer_parameters.petiole.radial_subdivisions<3 ){
+
556 build_context_geometry_petiole = false;
+
557 }
+
558
+
559 if( phytomer_parameters.petiole.petioles_per_internode<1 ){
+
560 build_context_geometry_petiole = false;
+
561 phytomer_parameters.petiole.petioles_per_internode = 1;
+
562 phytomer_parameters.leaf.leaves_per_petiole = 0;
+
563 }
+
564
+
565 if( phytomer_parameters.petiole.petioles_per_internode==0 ){
+
566 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Number of petioles per internode must be greater than zero.");
+
567 }
+
568
+
569 current_internode_scale_factor = internode_length_scale_factor_fraction;
+
570 current_leaf_scale_factor = leaf_scale_factor_fraction;
+
571
+
572 //Initialize internode variables
+
573 internode_length = internode_length_scale_factor_fraction * internode_length_max;
+
574 float dr_internode = internode_length / float(phytomer_parameters.internode.length_segments);
+
575 float dr_internode_max = internode_length_max / float(phytomer_parameters.internode.length_segments);
+
576 internode_vertices.resize(Ndiv_internode_length + 1);
+
577 internode_vertices.at(0) = internode_base_origin;
+
578 internode_radii.resize(Ndiv_internode_length + 1 );
+
579 internode_radii.at(0) = internode_radius;
+
580 float internode_pitch = deg2rad(phytomer_parameters.internode.pitch.val());
+
581 phytomer_parameters.internode.pitch.resample();
+
582
+
583 //initialize petiole variables
+
584 petiole_length.resize(phytomer_parameters.petiole.petioles_per_internode);
+
585 petiole_vertices.resize( phytomer_parameters.petiole.petioles_per_internode );
+
586 petiole_radii.resize( phytomer_parameters.petiole.petioles_per_internode );
+
587 std::vector<float> dr_petiole(phytomer_parameters.petiole.petioles_per_internode);
+
588 std::vector<float> dr_petiole_max(phytomer_parameters.petiole.petioles_per_internode);
+
589 for( int p=0; p<phytomer_parameters.petiole.petioles_per_internode; p++ ) {
+
590
+
591 petiole_vertices.at(p).resize(Ndiv_petiole_length + 1);
+
592 petiole_radii.at(p).resize(Ndiv_petiole_length + 1);
+
593
+
594 petiole_length.at(p) = leaf_scale_factor_fraction * phytomer_parameters.petiole.length.val();
+
595 dr_petiole.at(p) = petiole_length.at(p) / float(phytomer_parameters.petiole.length_segments);
+
596 dr_petiole_max.at(p) = phytomer_parameters.petiole.length.val() / float(phytomer_parameters.petiole.length_segments);
+
597 phytomer_parameters.petiole.length.resample();
+
598
+
599 petiole_radii.at(p).at(0) = leaf_scale_factor_fraction * phytomer_parameters.petiole.radius.val();
+
600
+
601 }
+
602 if( build_context_geometry_petiole ) {
+
603 petiole_objIDs.resize(phytomer_parameters.petiole.petioles_per_internode);
+
604 }
+
605
+
606 //initialize leaf variables
+
607 leaf_bases.resize(phytomer_parameters.petiole.petioles_per_internode);
+
608 leaf_objIDs.resize(phytomer_parameters.petiole.petioles_per_internode);
+
609
+
610 internode_colors.resize(Ndiv_internode_length + 1 );
+
611 internode_colors.at(0) = phytomer_parameters.internode.color;
+
612 petiole_colors.resize(Ndiv_petiole_length + 1 );
+
613 petiole_colors.at(0) = phytomer_parameters.petiole.color;
+
614
+
615 vec3 internode_axis = parent_internode_axis;
+
616
+
617 vec3 petiole_rotation_axis = cross(parent_internode_axis, parent_petiole_axis );
+
618 if(petiole_rotation_axis == make_vec3(0, 0, 0) ){
+
619 petiole_rotation_axis = make_vec3(1, 0, 0);
+
620 }
+
621
+
622 if( phytomer_index==0 ){ //if this is the first phytomer along a shoot, apply the origin rotation about the parent axis)
+
623
+
624 //pitch rotation for phytomer base
+
625 if( internode_pitch!=0.f ) {
+
626 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, petiole_rotation_axis, 0.5f*internode_pitch );
+
627 }
+
628
+
629 //roll rotation for shoot base rotation
+
630 float roll_nudge = 0.f;
+
631 if( shoot_base_rotation.roll/180.f == floor(shoot_base_rotation.roll/180.f) ) {
+
632 roll_nudge = 0.2;
+
633 }
+
634 if( shoot_base_rotation.roll!=0.f || roll_nudge!=0.f ){
+
635 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, parent_internode_axis,shoot_base_rotation.roll + roll_nudge ); //small additional rotation is to make sure the petiole is not exactly vertical
+
636 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, parent_internode_axis,shoot_base_rotation.roll + roll_nudge );
+
637 }
+
638
+
639 vec3 base_pitch_axis = -1*cross(parent_internode_axis, parent_petiole_axis );
+
640
+
641 //pitch rotation for shoot base rotation
+
642 if( shoot_base_rotation.pitch!=0.f ) {
+
643 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, base_pitch_axis, -shoot_base_rotation.pitch);
+
644 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, base_pitch_axis, -shoot_base_rotation.pitch);
+
645 }
+
646
+
647 //yaw rotation for shoot base rotation
+
648 if( shoot_base_rotation.yaw!=0 ){
+
649 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, parent_internode_axis, shoot_base_rotation.yaw);
+
650 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, parent_internode_axis, shoot_base_rotation.yaw );
+
651 }
+
652
+
653 }else {
+
654
+
655 //pitch rotation for phytomer base
+
656 if ( internode_pitch != 0) {
+
657 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, petiole_rotation_axis,-1.25f*internode_pitch );
+
658 }
+
659
+
660 }
+
661
+
662 vec3 shoot_bending_axis = cross( internode_axis, make_vec3(0,0,1) );
+
663
+
664 internode_axis.normalize();
+
665 if( internode_axis==make_vec3(0,0,1) ){
+
666 shoot_bending_axis = make_vec3(0,1,0);
+
667 }
+
668
+
669 // create internode
+
670 for(int i=1; i <= Ndiv_internode_length; i++ ){
+
671
+
672 //apply curvature
+
673 if( fabs(parent_shoot_parameters.gravitropic_curvature.val()) > 0 ) {
+
674 float dt = 1.f / float(Ndiv_internode_length);
+
675 parent_shoot->curvature_perturbation += - 0.5f*parent_shoot->curvature_perturbation*dt + 5*parent_shoot_parameters.tortuosity.val()*context_ptr->randn()*sqrt(dt);
+
676 float curvature_angle = deg2rad((parent_shoot_parameters.gravitropic_curvature.val()+parent_shoot->curvature_perturbation) * dr_internode_max);
+
677 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, shoot_bending_axis, curvature_angle);
+
678 }
+
679
+
680 internode_vertices.at(i) = internode_vertices.at(i - 1) + dr_internode * internode_axis;
+
681
+
682 internode_radii.at(i) = internode_radius;
+
683 internode_colors.at(i) = phytomer_parameters.internode.color;
+
684
+
685 }
+
686
+
687 if( build_context_geometry_internode ) {
+
688 internode_objIDs = makeTubeFromCones(Ndiv_internode_radius, internode_vertices, internode_radii, internode_colors, context_ptr);
+
689 }
+
690
+
691 //--- create petiole ---//
+
692
+
693 vec3 petiole_axis = internode_axis;
+
694
+
695 //petiole pitch rotation
+
696 float petiole_pitch = phytomer_parameters.petiole.pitch.val();
+
697 phytomer_parameters.petiole.pitch.resample();
+
698 if( fabs(petiole_pitch)<5.f ) {
+
699 petiole_pitch = 5.f;
+
700 }
+
701 petiole_axis = rotatePointAboutLine(petiole_axis, nullorigin, petiole_rotation_axis, std::abs(deg2rad(petiole_pitch)) );
+
702
+
703 //petiole yaw rotation
+
704 if( phytomer_index!=0 && phytomer_parameters.internode.phyllotactic_angle.val()!=0 ){ //not first phytomer along shoot
+
705 petiole_axis = rotatePointAboutLine(petiole_axis, nullorigin, internode_axis, deg2rad(phytomer_parameters.internode.phyllotactic_angle.val()) );
+
706 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, internode_axis, deg2rad(phytomer_parameters.internode.phyllotactic_angle.val()) );
+
707 phytomer_parameters.internode.phyllotactic_angle.resample();
+
708 }
+
709
+
710 for(int petiole=0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++ ) { //looping over petioles
+
711
+
712 if( petiole > 0 ) {
+
713 float budrot = float(petiole) * 2.f * M_PI / float(phytomer_parameters.petiole.petioles_per_internode);
+
714 petiole_axis = rotatePointAboutLine(petiole_axis, nullorigin, internode_axis, budrot );
+
715 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, internode_axis, budrot );
+
716 }
+
717
+
718 petiole_vertices.at(petiole).at(0) = internode_vertices.back();
+
719
+
720 for (int j = 1; j <= Ndiv_petiole_length; j++) {
+
721
+
722 if( fabs(phytomer_parameters.petiole.curvature.val())>0 ) {
+
723 petiole_axis = rotatePointAboutLine(petiole_axis, nullorigin, petiole_rotation_axis, -deg2rad(phytomer_parameters.petiole.curvature.val() * dr_petiole_max.at(petiole)));
+
724 phytomer_parameters.petiole.curvature.resample();
+
725 }
+
726
+
727 petiole_vertices.at(petiole).at(j) = petiole_vertices.at(petiole).at(j - 1) + dr_petiole.at(petiole) * petiole_axis;
+
728
+
729 petiole_radii.at(petiole).at(j) = leaf_scale_factor_fraction * phytomer_parameters.petiole.radius.val() * (1.f - phytomer_parameters.petiole.taper.val() / float(Ndiv_petiole_length) * float(j) );
+
730 petiole_colors.at(j) = phytomer_parameters.petiole.color;
+
731
+
732 }
+
733
+
734 if( build_context_geometry_petiole && petiole_radii.at(petiole).front() > 0.f ) {
+
735 petiole_objIDs.at(petiole) = makeTubeFromCones(Ndiv_petiole_radius, petiole_vertices.at(petiole), petiole_radii.at(petiole), petiole_colors, context_ptr);
+
736 }
+
737
+
738 //--- create buds ---//
+
739
+
740 std::vector<VegetativeBud> vegetative_buds_new;
+
741 vegetative_buds_new.resize( phytomer_parameters.internode.max_vegetative_buds_per_petiole.val() );
+
742 phytomer_parameters.internode.max_vegetative_buds_per_petiole.resample();
+
743
+
744 vegetative_buds.push_back(vegetative_buds_new);
+
745
+
746 std::vector<FloralBud> floral_buds_new;
+
747 floral_buds_new.resize( phytomer_parameters.internode.max_floral_buds_per_petiole.val() );
+
748 phytomer_parameters.internode.max_floral_buds_per_petiole.resample();
+
749
+
750 floral_buds.push_back(floral_buds_new);
+
751 resize_vector(inflorescence_objIDs, 0, phytomer_parameters.internode.max_floral_buds_per_petiole.val(), phytomer_parameters.petiole.petioles_per_internode);
+
752 if( build_context_geometry_peduncle ) {
+
753 resize_vector(peduncle_objIDs, 0, phytomer_parameters.internode.max_floral_buds_per_petiole.val(), phytomer_parameters.petiole.petioles_per_internode);
+
754 }
+
755 resize_vector( inflorescence_bases, 0, phytomer_parameters.internode.max_floral_buds_per_petiole.val(), phytomer_parameters.petiole.petioles_per_internode );
+
756
+
757 //--- create leaves ---//
+
758
+
759 if( phytomer_parameters.leaf.prototype_function == nullptr ){
+
760 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Leaf prototype function was not defined for shoot type " + parent_shoot->shoot_type_label + ".");
+
761 }
+
762
+
763 vec3 petiole_tip_axis = getPetioleAxisVector(1.f, petiole);
+
764
+
765 vec3 leaf_rotation_axis = cross(internode_axis, petiole_tip_axis );
+
766
+
767 for(int leaf=0; leaf < phytomer_parameters.leaf.leaves_per_petiole; leaf++ ){
+
768
+
769 float ind_from_tip = float(leaf)-float(phytomer_parameters.leaf.leaves_per_petiole-1)/2.f;
+
770
+
771 uint objID_leaf = phytomer_parameters.leaf.prototype_function(context_ptr, phytomer_parameters.leaf.subdivisions, ind_from_tip, shoot_index.x, shoot_index.y );
+
772
+
773 // -- scaling -- //
+
774
+
775 vec3 leaf_scale = leaf_scale_factor_fraction * phytomer_parameters.leaf.prototype_scale.val() * make_vec3(1,1,1);
+
776 if( phytomer_parameters.leaf.leaves_per_petiole>0 && phytomer_parameters.leaf.leaflet_scale.val()!=1.f && ind_from_tip!=0 ){
+
777 leaf_scale = powf(phytomer_parameters.leaf.leaflet_scale.val(),fabs(ind_from_tip))*leaf_scale;
+
778 }
+
779
+
780 context_ptr->scaleObject( objID_leaf, leaf_scale );
+
781
+
782 float compound_rotation = 0;
+
783 if( phytomer_parameters.leaf.leaves_per_petiole>1 ) {
+
784 if (phytomer_parameters.leaf.leaflet_offset.val() == 0) {
+
785 float dphi = M_PI / (floor(0.5 * float(phytomer_parameters.leaf.leaves_per_petiole - 1)) + 1);
+
786 compound_rotation = -float(M_PI) + dphi * (leaf + 0.5f);
+
787 } else {
+
788 if( leaf == float(phytomer_parameters.leaf.leaves_per_petiole-1)/2.f ){ //tip leaf
+
789 compound_rotation = 0;
+
790 }else if( leaf < float(phytomer_parameters.leaf.leaves_per_petiole-1)/2.f ) {
+
791 compound_rotation = -0.5*M_PI;
+
792 }else{
+
793 compound_rotation = 0.5*M_PI;
+
794 }
+
795 }
+
796 }
+
797
+
798 // -- rotations -- //
+
799
+
800 //roll rotation
+
801 float roll_rot = 0;
+
802 if( phytomer_parameters.leaf.leaves_per_petiole==1 ){
+
803 int sign = (shoot_index.x%2==0) ? 1 : -1;
+
804 roll_rot = (acos_safe(internode_axis.z)-deg2rad(phytomer_parameters.leaf.roll.val()))*sign;
+
805 } else if( ind_from_tip!= 0){
+
806 roll_rot = (asin_safe(petiole_tip_axis.z)+deg2rad(phytomer_parameters.leaf.roll.val()))*compound_rotation/std::fabs(compound_rotation);
+
807 }
+
808 phytomer_parameters.leaf.roll.resample();
+
809 context_ptr->rotateObject(objID_leaf, roll_rot, "x" );
+
810
+
811 //pitch rotation
+
812 float pitch_rot = deg2rad(phytomer_parameters.leaf.pitch.val());
+
813 phytomer_parameters.leaf.pitch.resample();
+
814 if( ind_from_tip==0 ){
+
815 pitch_rot += asin_safe(petiole_tip_axis.z);
+
816 }
+
817 context_ptr->rotateObject(objID_leaf, -pitch_rot , "y" );
+
818
+
819 //yaw rotation
+
820 if( ind_from_tip!=0 ){
+
821 float yaw_rot = -deg2rad(phytomer_parameters.leaf.yaw.val())*compound_rotation/fabs(compound_rotation);
+
822 phytomer_parameters.leaf.yaw.resample();
+
823 context_ptr->rotateObject( objID_leaf, yaw_rot, "z" );
+
824 }
+
825
+
826 //rotate to azimuth of petiole
+
827 context_ptr->rotateObject( objID_leaf, -std::atan2(petiole_tip_axis.y, petiole_tip_axis.x)+compound_rotation, "z" );
+
828
+
829
+
830 // -- translation -- //
+
831
+
832 vec3 leaf_base = petiole_vertices.at(petiole).back();
+
833 if( phytomer_parameters.leaf.leaves_per_petiole>1 && phytomer_parameters.leaf.leaflet_offset.val()>0 ){
+
834 if( ind_from_tip != 0 ) {
+
835 float offset = (fabs(ind_from_tip) - 0.5f) * phytomer_parameters.leaf.leaflet_offset.val() * phytomer_parameters.petiole.length.val();
+
836 leaf_base = interpolateTube(petiole_vertices.at(petiole), 1.f - offset / phytomer_parameters.petiole.length.val() );
+
837 }
+
838 }
+
839
+
840 context_ptr->translateObject( objID_leaf, leaf_base );
+
841
+
842 leaf_objIDs.at(petiole).push_back(objID_leaf );
+
843 leaf_bases.at(petiole).push_back(leaf_base );
+
844
+
845 }
+
846 phytomer_parameters.leaf.prototype_scale.resample();
+
847
+
848 if( petiole_axis==make_vec3(0,0,1) ) {
+
849 inflorescence_bending_axis = make_vec3(1, 0, 0);
+
850 }else{
+
851 inflorescence_bending_axis = cross(make_vec3(0, 0, 1), petiole_axis);
+
852 }
+
853
+
854 }
+
855
+
856}
+
857
+
858void Phytomer::addInflorescence(const helios::vec3 &base_position, const AxisRotation &base_rotation, const helios::vec3 &a_inflorescence_bending_axis, FloralBud &fbud) {
+
859
+
860 uint Ndiv_rachis_length = std::max(uint(1), phytomer_parameters.peduncle.length_segments);
+
861 uint Ndiv_rachis_radius = std::max(uint(3), phytomer_parameters.peduncle.radial_subdivisions);
+
862 if( phytomer_parameters.peduncle.length_segments==0 || phytomer_parameters.peduncle.radial_subdivisions<3 ){
+
863 build_context_geometry_peduncle = false;
+
864 }
+
865
+
866 float dr_peduncle = phytomer_parameters.peduncle.length.val() / float(Ndiv_rachis_length);
+
867 phytomer_parameters.peduncle.length.resample();
+
868
+
869 std::vector<vec3> peduncle_vertices(phytomer_parameters.peduncle.length_segments + 1);
+
870 peduncle_vertices.at(0) = base_position;
+
871 std::vector<float> peduncle_radii(phytomer_parameters.peduncle.length_segments + 1);
+
872 peduncle_radii.at(0) = phytomer_parameters.peduncle.radius.val();
+
873 std::vector<RGBcolor> peduncle_colors(phytomer_parameters.peduncle.length_segments + 1);
+
874 peduncle_colors.at(0) = phytomer_parameters.internode.color;
+
875
+
876 vec3 peduncle_axis = getAxisVector(1.f, internode_vertices );
+
877
+
878 //peduncle pitch rotation
+
879 if( phytomer_parameters.peduncle.pitch.val()!=0.f || base_rotation.pitch!=0.f ) {
+
880 peduncle_axis = rotatePointAboutLine(peduncle_axis, nullorigin, inflorescence_bending_axis, deg2rad(phytomer_parameters.peduncle.pitch.val())+base_rotation.pitch );
+
881 phytomer_parameters.peduncle.pitch.resample();
+
882 }
+
883
+
884 //rotate peduncle to azimuth of petiole and apply peduncle base yaw rotation
+
885 vec3 internode_axis = getAxisVector(1.f, internode_vertices );
+
886 vec3 parent_petiole_base_axis = getPetioleAxisVector(0.f, fbud.parent_petiole_index);
+
887 float parent_petiole_azimuth = -std::atan2(parent_petiole_base_axis.y, parent_petiole_base_axis.x);
+
888 float current_peduncle_azimuth = -std::atan2(peduncle_axis.y, peduncle_axis.x);
+
889 peduncle_axis = rotatePointAboutLine( peduncle_axis, nullorigin, internode_axis, (current_peduncle_azimuth-parent_petiole_azimuth) + base_rotation.yaw );
+
890
+
891 float theta_base = fabs(cart2sphere(peduncle_axis).zenith);
+
892
+
893 for(int i=1; i<=phytomer_parameters.peduncle.length_segments; i++ ){
+
894
+
895 if( phytomer_parameters.peduncle.curvature.val()!=0.f ) {
+
896 float theta_curvature = -deg2rad(phytomer_parameters.peduncle.curvature.val() * dr_peduncle);
+
897 phytomer_parameters.peduncle.curvature.resample();
+
898 if (fabs(theta_curvature) * float(i) < M_PI - theta_base) {
+
899 peduncle_axis = rotatePointAboutLine(peduncle_axis, nullorigin, inflorescence_bending_axis, theta_curvature);
+
900 } else {
+
901 peduncle_axis = make_vec3(0, 0, -1);
+
902 }
+
903 }
+
904
+
905 peduncle_vertices.at(i) = peduncle_vertices.at(i - 1) + dr_peduncle * peduncle_axis;
+
906
+
907 peduncle_radii.at(i) = phytomer_parameters.peduncle.radius.val();
+
908 peduncle_colors.at(i) = phytomer_parameters.internode.color;
+
909
+
910 }
+
911 phytomer_parameters.peduncle.radius.resample();
+
912
+
913 if( build_context_geometry_peduncle) {
+
914 peduncle_objIDs.at(fbud.parent_petiole_index).at(fbud.bud_index).push_back(context_ptr->addTubeObject(Ndiv_rachis_radius, peduncle_vertices, peduncle_radii, peduncle_colors));
+
915 }
+
916
+
917 for(int fruit=0; fruit < phytomer_parameters.inflorescence.flowers_per_rachis.val(); fruit++ ){
+
918
+
919 uint objID_fruit;
+
920 helios::vec3 fruit_scale;
+
921
+
922 if(fbud.state == BUD_FRUITING ){
+
923 objID_fruit = phytomer_parameters.inflorescence.fruit_prototype_function(context_ptr,1,fbud.time_counter);
+
924 fruit_scale = phytomer_parameters.inflorescence.fruit_prototype_scale.val()*make_vec3(1,1,1);
+
925 phytomer_parameters.inflorescence.fruit_prototype_scale.resample();
+
926 }else{
+
927 bool flower_is_open;
+
928 if(fbud.state == BUD_FLOWER_CLOSED ) {
+
929 flower_is_open = false;
+
930 }else{
+
931 flower_is_open = true;
+
932 }
+
933 objID_fruit = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr,1,flower_is_open);
+
934 fruit_scale = phytomer_parameters.inflorescence.flower_prototype_scale.val()*make_vec3(1,1,1);
+
935 phytomer_parameters.inflorescence.flower_prototype_scale.resample();
+
936 }
+
937
+
938 float ind_from_tip = fabs(fruit- float(phytomer_parameters.inflorescence.flowers_per_rachis.val() - 1) / 2.f);
+
939
+
940 context_ptr->scaleObject( objID_fruit, fruit_scale );
+
941
+
942 //if we have more than one flower/fruit, we need to adjust the base position of the fruit
+
943 vec3 fruit_base = peduncle_vertices.back();
+
944 float frac = 1;
+
945 if(phytomer_parameters.inflorescence.flowers_per_rachis.val() > 1 && phytomer_parameters.inflorescence.flower_offset.val() > 0 ){
+
946 if( ind_from_tip != 0 ) {
+
947 float offset = 0;
+
948 if(phytomer_parameters.inflorescence.flower_arrangement_pattern == "opposite" ){
+
949 offset = (ind_from_tip - 0.5f) * phytomer_parameters.inflorescence.flower_offset.val() * phytomer_parameters.peduncle.length.val();
+
950 }else if(phytomer_parameters.inflorescence.flower_arrangement_pattern == "alternate" ){
+
951 offset = (ind_from_tip - 0.5f + 0.5f*float(fruit> float(phytomer_parameters.inflorescence.flowers_per_rachis.val() - 1) / 2.f) ) * phytomer_parameters.inflorescence.flower_offset.val() * phytomer_parameters.peduncle.length.val();
+
952 }else{
+
953 helios_runtime_error("ERROR (PlantArchitecture::addInflorescence): Invalid fruit arrangement pattern.");
+
954 }
+
955 if( phytomer_parameters.peduncle.length.val()>0 ){
+
956 frac = 1.f - offset / phytomer_parameters.peduncle.length.val();
+
957 }
+
958 fruit_base = interpolateTube(peduncle_vertices, frac);
+
959 }
+
960 }
+
961
+
962 //if we have more than one flower/fruit, we need to adjust the rotation about the peduncle
+
963 float compound_rotation = 0;
+
964 if(phytomer_parameters.inflorescence.flowers_per_rachis.val() > 1 ) {
+
965 if (phytomer_parameters.inflorescence.flower_offset.val() == 0) { //flowers/fruit are all at the tip, so just equally distribute them about the azimuth
+
966 float dphi = M_PI / (floor(0.5 * float(phytomer_parameters.inflorescence.flowers_per_rachis.val() - 1)) + 1);
+
967 compound_rotation = -float(M_PI) + dphi * (fruit + 0.5f);
+
968 } else {
+
969 if( fruit < float(phytomer_parameters.inflorescence.flowers_per_rachis.val() - 1) / 2.f ) {
+
970 compound_rotation = 0;
+
971 }else {
+
972 compound_rotation = M_PI;
+
973 }
+
974 }
+
975 }
+
976
+
977 peduncle_axis = getAxisVector(frac, peduncle_vertices );
+
978
+
979 vec3 fruit_axis = peduncle_axis;
+
980
+
981 //roll rotation
+
982 if( phytomer_parameters.inflorescence.roll.val()!=0.f ) {
+
983 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.inflorescence.roll.val()), "x" );
+
984 phytomer_parameters.inflorescence.roll.resample();
+
985 }
+
986
+
987 //pitch rotation
+
988 float pitch_inflorescence = -asin_safe(peduncle_axis.z) + deg2rad(phytomer_parameters.inflorescence.pitch.val());
+
989 phytomer_parameters.inflorescence.pitch.resample();
+
990 if(fbud.state == BUD_FRUITING ) { //gravity effect for fruit
+
991 pitch_inflorescence = pitch_inflorescence + phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.val() * (0.5f * M_PI - pitch_inflorescence);
+
992 }
+
993 context_ptr->rotateObject(objID_fruit, pitch_inflorescence, "y");
+
994 fruit_axis = rotatePointAboutLine(fruit_axis, nullorigin, make_vec3(1, 0, 0), pitch_inflorescence);
+
995
+
996 //rotate flower/fruit to azimuth of peduncle
+
997 context_ptr->rotateObject(objID_fruit, -std::atan2(peduncle_axis.y, peduncle_axis.x), "z" );
+
998 fruit_axis = rotatePointAboutLine( fruit_axis, nullorigin, make_vec3(0,0,1), -std::atan2(peduncle_axis.y, peduncle_axis.x) );
+
999
+
1000 context_ptr->translateObject( objID_fruit, fruit_base );
+
1001
+
1002 //rotate flower/fruit about peduncle (roll)
+
1003 if( phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.val()!=0 && fbud.state == BUD_FRUITING ) {
+
1004 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation, fruit_base, make_vec3(0, 0, 1));
+
1005 }else{
+
1006 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation, fruit_base, peduncle_axis);
+
1007 fruit_axis = rotatePointAboutLine(fruit_axis, nullorigin, peduncle_axis, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation);
+
1008 }
+
1009 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.resample();
+
1010
+
1011 inflorescence_bases.at(fbud.parent_petiole_index).at(fbud.bud_index).push_back( fruit_base );
+
1012
+
1013 inflorescence_objIDs.at(fbud.parent_petiole_index).at(fbud.bud_index).push_back( objID_fruit );
+
1014
+
1015 }
+
1016 phytomer_parameters.inflorescence.flowers_per_rachis.resample();
+
1017 phytomer_parameters.peduncle.roll.resample();
+
1018
+
1019 context_ptr->setObjectData( peduncle_objIDs.at(fbud.parent_petiole_index).at(fbud.bud_index), "rank", rank );
+
1020
+
1021 context_ptr->setObjectData( inflorescence_objIDs.at(fbud.parent_petiole_index).at(fbud.bud_index), "rank", rank );
+
1022
+
1023 for( uint objID : peduncle_objIDs.at(fbud.parent_petiole_index).at(fbud.bud_index) ) {
+
1024 context_ptr->setPrimitiveData( context_ptr->getObjectPrimitiveUUIDs(objID), "peduncleID", (int)objID );
+
1025 }
+
1026 for( uint objID : inflorescence_objIDs.at(fbud.parent_petiole_index).at(fbud.bud_index) ) {
+
1027 if( fbud.state == BUD_FLOWER_CLOSED ) {
+
1028 context_ptr->setPrimitiveData(context_ptr->getObjectPrimitiveUUIDs(objID), "closedflowerID", (int) objID);
+
1029 }else if( fbud.state == BUD_FLOWER_OPEN ) {
+
1030 context_ptr->clearPrimitiveData( context_ptr->getObjectPrimitiveUUIDs(objID), "closedflowerID" );
+
1031 context_ptr->setPrimitiveData(context_ptr->getObjectPrimitiveUUIDs(objID), "openflowerID", (int) objID);
+
1032 }else{
+
1033 context_ptr->setPrimitiveData(context_ptr->getObjectPrimitiveUUIDs(objID), "fruitID", (int) objID);
+
1034 }
+
1035 }
+
1036
+
1037}
+
1038
+
1039void Phytomer::setPetioleBase( const helios::vec3 &base_position ){
+
1040
+
1041 vec3 old_base = petiole_vertices.front().front();
+
1042 vec3 shift = base_position - old_base;
+
1043
+
1044 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
+
1045 for (auto &vertex: petiole_vertices.at(petiole) ) {
+
1046 vertex += shift;
+
1047 }
+
1048 }
+
1049
+
1050 if( build_context_geometry_petiole ) {
+
1051 context_ptr->translateObject(flatten(petiole_objIDs), shift);
+
1052 }
+
1053 context_ptr->translateObject( flatten(leaf_objIDs), shift );
+
1054
+
1055 for( int petiole=0; petiole<leaf_bases.size(); petiole++ ) {
+
1056 for (auto &leaf_base: leaf_bases.at(petiole)) {
+
1057 leaf_base += shift;
+
1058 }
+
1059 if( !inflorescence_objIDs.empty() ) {
+
1060 for (int bud = 0; bud < inflorescence_objIDs.at(petiole).size(); bud++) {
+
1061 context_ptr->translateObject(inflorescence_objIDs.at(petiole).at(bud), shift);
+
1062 for (auto &inflorescence_base: inflorescence_bases.at(petiole).at(bud)) {
+
1063 inflorescence_base += shift;
+
1064 }
+
1065 if( build_context_geometry_peduncle ) {
+
1066 context_ptr->translateObject(peduncle_objIDs.at(petiole).at(bud), shift);
+
1067 }
+
1068 }
+
1069 }
+
1070 }
+
1071
+
1072}
+
1073
+
1074void Phytomer::setPhytomerBase( const helios::vec3 &base_position ){
+
1075
+
1076 vec3 old_base = internode_vertices.front();
+
1077 vec3 shift = base_position - old_base;
+
1078
+
1079 for( auto & vertex : internode_vertices){
+
1080 vertex += shift;
+
1081 }
+
1082
+
1083 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
+
1084 for (auto &vertex: petiole_vertices.at(petiole) ) {
+
1085 vertex += shift;
+
1086 }
+
1087 }
+
1088
+
1089 if( build_context_geometry_internode ) {
+
1090 context_ptr->translateObject(internode_objIDs, shift);
+
1091 }
+
1092 if( build_context_geometry_petiole ) {
+
1093 context_ptr->translateObject(flatten(petiole_objIDs), shift);
+
1094 }
+
1095 context_ptr->translateObject( flatten(leaf_objIDs), shift );
+
1096 for( int petiole=0; petiole<leaf_bases.size(); petiole++ ) {
+
1097 for (auto &leaf_base: leaf_bases.at(petiole)) {
+
1098 leaf_base += shift;
+
1099 }
+
1100 if( !inflorescence_objIDs.empty() ) {
+
1101 for (int bud = 0; bud < inflorescence_objIDs.at(petiole).size(); bud++) {
+
1102 context_ptr->translateObject(inflorescence_objIDs.at(petiole).at(bud), shift);
+
1103 for (auto &inflorescence_base: inflorescence_bases.at(petiole).at(bud)) {
+
1104 inflorescence_base += shift;
+
1105 }
+
1106 if( build_context_geometry_peduncle ) {
+
1107 context_ptr->translateObject(peduncle_objIDs.at(petiole).at(bud), shift);
+
1108 }
+
1109 }
+
1110 }
+
1111 }
+
1112
+
1113}
+
1114
+
1115void Phytomer::setInternodeLengthScaleFraction(float internode_scale_factor_fraction ){
+
1116
+
1117 assert(internode_scale_factor_fraction >= 0 && internode_scale_factor_fraction <= 1 );
+
1118
+
1119 if(internode_scale_factor_fraction == current_internode_scale_factor ){
+
1120 return;
+
1121 }
+
1122
+
1123 float delta_scale = internode_scale_factor_fraction / current_internode_scale_factor;
+
1124
+
1125 internode_length = internode_length*delta_scale;
+
1126 current_internode_scale_factor = internode_scale_factor_fraction;
+
1127
+
1128 if( build_context_geometry_internode ) {
+
1129 int node = 0;
+
1130 vec3 last_base = internode_vertices.front();
+
1131 for (uint objID: internode_objIDs) { //should be automatically skipped if internode geometry was not built
+
1132 context_ptr->getConeObjectPointer(objID)->scaleLength(delta_scale);
+
1133 if (node > 0) {
+
1134 vec3 new_base = context_ptr->getConeObjectNode(objID, 0);
+
1135 context_ptr->translateObject(objID, last_base - new_base);
+
1136 }
+
1137 last_base = context_ptr->getConeObjectNode(objID, 1);
+
1138 internode_vertices.at(node + 1) = last_base;
+
1139 node++;
+
1140 }
+
1141 }else{
+
1142 for( int i=1; i<internode_vertices.size(); i++ ) {
+
1143 vec3 axis_vector = internode_vertices.at(i) - internode_vertices.at(i-1);
+
1144 internode_vertices.at(i) = internode_vertices.at(i-1) + delta_scale*axis_vector;
+
1145 }
+
1146 }
+
1147
+
1148 //translate leaf to new internode position
+
1149 setPetioleBase( internode_vertices.back() );
+
1150
+
1151
+
1152}
+
1153
+
1154void Phytomer::setInternodeMaxLength( float internode_length_max ){
+
1155 this->internode_length_max = internode_length_max;
+
1156
+
1157 current_internode_scale_factor = current_internode_scale_factor*this->internode_length_max/internode_length_max;
+
1158
+
1159 if( current_internode_scale_factor>=1.f ){
+
1160 setInternodeLengthScaleFraction(1.f);
+
1161 current_internode_scale_factor = 1.f;
+
1162 }
+
1163}
+
1164
+
1165void Phytomer::scaleInternodeMaxLength( float scale_factor ){
+
1166 this->internode_length_max *= scale_factor;
+
1167
+
1168 current_internode_scale_factor = current_internode_scale_factor/scale_factor;
+
1169
+
1170 if( current_internode_scale_factor>=1.f ){
+
1171 setInternodeLengthScaleFraction(1.f);
+
1172 current_internode_scale_factor = 1.f;
+
1173 }
+
1174}
+
1175
+
1176void Phytomer::setInternodeMaxRadius( float internode_radius_max ){
+
1177
+
1178 this->internode_radius_max = internode_radius_max;
+
1179
+
1180}
+
1181
+
1182void Phytomer::setLeafScaleFraction(float leaf_scale_factor_fraction ){
+
1183
+
1184 assert(leaf_scale_factor_fraction >= 0 && leaf_scale_factor_fraction <= 1 );
+
1185
+
1186 if(leaf_scale_factor_fraction == current_leaf_scale_factor || (leaf_objIDs.empty() && petiole_objIDs.empty()) ){
+
1187 return;
+
1188 }
+
1189
+
1190 float delta_scale = leaf_scale_factor_fraction / current_leaf_scale_factor;
+
1191
+
1192 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
+
1193 petiole_length.at(petiole) *= delta_scale;
+
1194 }
+
1195 current_leaf_scale_factor = leaf_scale_factor_fraction;
+
1196
+
1197 assert(leaf_objIDs.size() == leaf_bases.size());
+
1198
+
1199 //scale the petiole
+
1200 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
+
1201
+
1202 if( !petiole_objIDs.empty() ) {
+
1203 int node = 0;
+
1204 vec3 old_tip = petiole_vertices.at(petiole).back();
+
1205 vec3 last_base = petiole_vertices.at(petiole).front();//looping over petioles
+
1206 for (uint objID: petiole_objIDs.at(petiole)) { //looping over cones/segments within petiole
+
1207 context_ptr->getConeObjectPointer(objID)->scaleLength(delta_scale);
+
1208 context_ptr->getConeObjectPointer(objID)->scaleGirth(delta_scale);
+
1209 petiole_radii.at(petiole).at(node) *= delta_scale;
+
1210 if (node > 0) {
+
1211 vec3 new_base = context_ptr->getConeObjectNode(objID, 0);
+
1212 context_ptr->translateObject(objID, last_base - new_base);
+
1213 } else {
+
1214 petiole_vertices.at(petiole).at(0) = context_ptr->getConeObjectNode(objID, 0);
+
1215 }
+
1216 last_base = context_ptr->getConeObjectNode(objID, 1);
+
1217 petiole_vertices.at(petiole).at(node + 1) = last_base;
+
1218 node++;
+
1219 }
+
1220 }else{
+
1221 for( int i=1; i<petiole_vertices.at(petiole).size(); i++ ) {
+
1222 vec3 axis_vector = petiole_vertices.at(petiole).at(i) - petiole_vertices.at(petiole).at(i-1);
+
1223 petiole_vertices.at(petiole).at(i) = petiole_vertices.at(petiole).at(i-1) + delta_scale*axis_vector;
+
1224 petiole_radii.at(petiole).at(i) *= delta_scale;
+
1225 }
+
1226 }
+
1227
+
1228 //scale and translate leaves
+
1229 assert(leaf_objIDs.at(petiole).size() == leaf_bases.at(petiole).size());
+
1230 for (int leaf = 0; leaf < leaf_objIDs.at(petiole).size(); leaf++) {
+
1231
+
1232 float ind_from_tip = float(leaf) - float(phytomer_parameters.leaf.leaves_per_petiole - 1) / 2.f;
+
1233
+
1234 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), -1 * leaf_bases.at(petiole).at(leaf));
+
1235 context_ptr->scaleObject(leaf_objIDs.at(petiole).at(leaf), delta_scale * make_vec3(1, 1, 1));
+
1236 if (ind_from_tip == 0) {
+
1237 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), petiole_vertices.at(petiole).back());
+
1238 leaf_bases.at(petiole).at(leaf) = petiole_vertices.at(petiole).back();
+
1239 } else {
+
1240 float offset = (fabs(ind_from_tip) - 0.5f) * phytomer_parameters.leaf.leaflet_offset.val() * phytomer_parameters.petiole.length.val();
+
1241 vec3 leaf_base = interpolateTube(petiole_vertices.at(petiole), 1.f - offset / phytomer_parameters.petiole.length.val());
+
1242 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), leaf_base);
+
1243 leaf_bases.at(petiole).at(leaf) = leaf_base;
+
1244 }
+
1245
+
1246 }
+
1247
+
1248 }
+
1249
+
1250}
+
1251
+
1252void Phytomer::setLeafPrototypeScale( float leaf_prototype_scale ){
+
1253
+
1254 current_leaf_scale_factor = current_leaf_scale_factor*phytomer_parameters.leaf.prototype_scale.val()/leaf_prototype_scale;
+
1255
+
1256 if( current_leaf_scale_factor>=1.f ){
+
1257 setLeafScaleFraction(1.f);
+
1258 current_leaf_scale_factor = 1.f;
+
1259 }
+
1260
+
1261}
+
1262void Phytomer::scaleLeafPrototypeScale( float scale_factor ){
+
1263
+
1264 current_leaf_scale_factor = current_leaf_scale_factor/scale_factor;
+
1265
+
1266 if( current_leaf_scale_factor>=1.f ){
+
1267 setLeafScaleFraction(1.f);
+
1268 current_leaf_scale_factor = 1.f;
+
1269 }
+
1270
+
1271}
+
1272
+
1273
+
1274void Phytomer::setInflorescenceScaleFraction(FloralBud &fbud, float inflorescence_scale_factor_fraction) {
+
1275
+
1276 assert(inflorescence_scale_factor_fraction >= 0 && inflorescence_scale_factor_fraction <= 1 );
+
1277
+
1278 if(inflorescence_scale_factor_fraction == fbud.current_fruit_scale_factor ){
+
1279 return;
+
1280 }
+
1281
+
1282 float delta_scale = inflorescence_scale_factor_fraction / fbud.current_fruit_scale_factor;
+
1283
+
1284 fbud.current_fruit_scale_factor = inflorescence_scale_factor_fraction;
+
1285
+
1286 //scale and translate flowers/fruit
+
1287 for (int inflorescence = 0; inflorescence < inflorescence_objIDs.at( fbud.parent_petiole_index ).at( fbud.bud_index ).size(); inflorescence++) {
+
1288
+
1289 uint objID = inflorescence_objIDs.at( fbud.parent_petiole_index ).at( fbud.bud_index ).at(inflorescence);
+
1290
+
1291 context_ptr->translateObject(objID, -1 * inflorescence_bases.at( fbud.parent_petiole_index ).at( fbud.bud_index ).at(inflorescence));
+
1292 context_ptr->scaleObject(objID, delta_scale * make_vec3(1, 1, 1));
+
1293 context_ptr->translateObject(objID, inflorescence_bases.at( fbud.parent_petiole_index ).at( fbud.bud_index ).at(inflorescence));
+
1294
+
1295 }
+
1296
+
1297}
+
1298
+
1299void Phytomer::removeLeaf(){
+
1300
+
1301 context_ptr->deleteObject(flatten(leaf_objIDs));
+
1302 leaf_objIDs.resize(0);
+
1303 leaf_bases.resize(0);
+
1304
+
1305 if( build_context_geometry_petiole ) {
+
1306 context_ptr->deleteObject(flatten(petiole_objIDs));
+
1307 petiole_objIDs.resize(0);
+
1308 }
+
1309
+
1310}
+
1311
+
1312bool Phytomer::hasLeaf() const{
+
1313 return !leaf_objIDs.empty();
+
1314}
+
1315
+
1316bool Phytomer::hasInflorescence() const {
+
1317 return !inflorescence_objIDs.empty();
+
1318}
+
1319
+
1320Shoot::Shoot(uint plant_ID, int shoot_ID, int parent_shoot_ID, uint parent_node, uint parent_petiole_index, uint rank, const helios::vec3 &origin, const AxisRotation &shoot_base_rotation, uint current_node_number,
+
1321 float internode_length_shoot_initial, ShootParameters shoot_params, const std::string &shoot_type_label, PlantArchitecture *plant_architecture_ptr) :
+
1322 plantID(plant_ID), ID(shoot_ID), parent_shoot_ID(parent_shoot_ID), parent_node_index(parent_node), parent_petiole_index(parent_petiole_index), rank(rank), origin(origin), base_rotation(shoot_base_rotation), current_node_number(current_node_number), internode_length_max_shoot_initial(internode_length_shoot_initial), shoot_parameters(std::move(shoot_params)), shoot_type_label(shoot_type_label), plant_architecture_ptr(plant_architecture_ptr) {
+
1323 assimilate_pool = 0;
+
1324 phyllochron_counter = 0;
+
1325 dormant = true;
+
1326 context_ptr = plant_architecture_ptr->context_ptr;
+
1327}
+
1328
+
1329void Shoot::buildShootPhytomers(float internode_radius, float internode_length, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction) {
+
1330
+
1331 for( int i=0; i<current_node_number; i++ ) { //loop over phytomers to build up the shoot
+
1332
+
1333 //Determine position of internode base
+
1334 vec3 internode_base_position;
+
1335 if( i==0 ){ //first phytomer on shoot
+
1336 internode_base_position = origin;
+
1337 }else{ // not the first phytomer on the shoot
+
1338 internode_base_position = phytomers.at(i-1)->internode_vertices.back();
+
1339 }
+
1340
+
1341 //Adding the phytomer(s) to the shoot
+
1342 int pID = addPhytomer(shoot_parameters.phytomer_parameters, internode_base_position, this->base_rotation, internode_radius, internode_length, internode_length_scale_factor_fraction, leaf_scale_factor_fraction);
+
1343
+
1344 }
+
1345
+
1346}
+
1347
+
1348bool Shoot::sampleChildShootType(std::string &child_shoot_type_label) const{
+
1349
+
1350 auto shoot_ptr = this;
+
1351
+
1352 assert( shoot_ptr->shoot_parameters.child_shoot_type_labels.size() == shoot_ptr->shoot_parameters.child_shoot_type_probabilities.size() );
+
1353
+
1354 child_shoot_type_label = "";
+
1355
+
1356 if ( shoot_ptr->shoot_parameters.child_shoot_type_labels.size()==0 ) { //if user doesn't specify child shoot types, generate the same type by default
+
1357 child_shoot_type_label = shoot_ptr->shoot_type_label;
+
1358 }else if( shoot_ptr->shoot_parameters.child_shoot_type_labels.size()==1 ){ //if only one child shoot types was specified, use it
+
1359 child_shoot_type_label = shoot_ptr->shoot_parameters.child_shoot_type_labels.at(0);
+
1360 }else{
+
1361 float randf = context_ptr->randu();
+
1362 int shoot_type_index = -1;
+
1363 float cumulative_probability = 0;
+
1364 for (int s = 0; s < shoot_ptr->shoot_parameters.child_shoot_type_labels.size(); s++) {
+
1365 cumulative_probability += shoot_ptr->shoot_parameters.child_shoot_type_probabilities.at(s);
+
1366 if (randf < cumulative_probability ) {
+
1367 shoot_type_index = s;
+
1368 break;
+
1369 }
+
1370 }
+
1371 if (shoot_type_index < 0) {
+
1372 shoot_type_index = shoot_ptr->shoot_parameters.child_shoot_type_labels.size() - 1;
+
1373 }
+
1374 child_shoot_type_label = shoot_ptr->shoot_type_label;
+
1375 if (shoot_type_index >= 0) {
+
1376 child_shoot_type_label = shoot_ptr->shoot_parameters.child_shoot_type_labels.at(shoot_type_index);
+
1377 }
+
1378 }
+
1379
+
1380 bool bud_break = true;
+
1381 if (context_ptr->randu() > plant_architecture_ptr->shoot_types.at(shoot_ptr->shoot_type_label).vegetative_bud_break_probability.val() ) {
+
1382 bud_break = false;
+
1383 child_shoot_type_label = "";
+
1384 }
+
1385
+
1386
+
1387 return bud_break;
+
1388
+
1389}
+
1390
+
1391uint PlantArchitecture::addBaseStemShoot(uint plantID, uint current_node_number, const AxisRotation &base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction,
+
1392 const std::string &shoot_type_label) {
+
1393
+
1394 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1395 helios_runtime_error("ERROR (PlantArchitecture::addShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1396 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
+
1397 helios_runtime_error("ERROR (PlantArchitecture::addShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
+
1398 }
+
1399
+
1400 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
1401
+
1402 auto shoot_parameters = shoot_types.at(shoot_type_label);
+
1403
+
1404 validateShootTypes(shoot_parameters);
+
1405
+
1406 if(current_node_number > shoot_parameters.max_nodes.val() ){
+
1407 helios_runtime_error("ERROR (PlantArchitecture::addShoot): Cannot add shoot with " + std::to_string(current_node_number) + " nodes since the specified max node number is " + std::to_string(shoot_parameters.max_nodes.val()) + ".");
+
1408 }
+
1409
+
1410 uint shootID = shoot_tree_ptr->size();
+
1411
+
1412 auto* shoot_new = (new Shoot(plantID, shootID, -1, 0, 0, 0, plant_instances.at(plantID).base_position, base_rotation, current_node_number, internode_length_max, shoot_parameters, shoot_type_label, this));
+
1413 shoot_tree_ptr->emplace_back(shoot_new);
+
1414 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction);
+
1415
+
1416 return shootID;
+
1417
+
1418}
+
1419
+
1420uint PlantArchitecture::appendShoot(uint plantID, int parent_shoot_ID, uint current_node_number, const AxisRotation &base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction,
+
1421 float leaf_scale_factor_fraction, const std::string &shoot_type_label) {
+
1422
+
1423 if( plant_instances.find(plantID) == plant_instances.end() ) {
+
1424 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1425 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
+
1426 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
+
1427 }
+
1428
+
1429 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
1430
+
1431 auto shoot_parameters = shoot_types.at(shoot_type_label);
+
1432
+
1433 validateShootTypes(shoot_parameters);
+
1434
+
1435 if( shoot_tree_ptr->empty() ){
+
1436 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Cannot append shoot to empty shoot. You must call addBaseStemShoot() first for each plant.");
+
1437 }else if( parent_shoot_ID >= int(shoot_tree_ptr->size()) ){
+
1438 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Parent with ID of " + std::to_string(parent_shoot_ID) + " does not exist.");
+
1439 }else if(current_node_number > shoot_parameters.max_nodes.val() ){
+
1440 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Cannot add shoot with " + std::to_string(current_node_number) + " nodes since the specified max node number is " + std::to_string(shoot_parameters.max_nodes.val()) + ".");
+
1441 }else if( shoot_tree_ptr->at(parent_shoot_ID)->phytomers.empty() ){
+
1442 std::cout << "WARNING (PlantArchitecture::appendShoot): Shoot does not have any phytomers to append." << std::endl;
+
1443 }
+
1444
+
1445 //stop parent shoot from producing new phytomers at the apex
+
1446 shoot_tree_ptr->at(parent_shoot_ID)->shoot_parameters.max_nodes = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number;
+
1447
+
1448 shoot_tree_ptr->at(parent_shoot_ID)->terminateApicalBud(); //meristem should not keep growing after appending shoot
+
1449
+
1450 int appended_shootID = shoot_tree_ptr->size();
+
1451
+
1452 uint parent_node = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number-1;
+
1453
+
1454 uint rank = shoot_tree_ptr->at(parent_shoot_ID)->rank;
+
1455
+
1456 vec3 base_position = shoot_tree_ptr->at(parent_shoot_ID)->phytomers.back()->internode_vertices.back();
+
1457
+
1458 auto * shoot_new = (new Shoot(plantID, appended_shootID, parent_shoot_ID, parent_node, 0, rank, base_position, base_rotation, current_node_number, internode_length_max, shoot_parameters, shoot_type_label, this));
+
1459 shoot_tree_ptr->emplace_back(shoot_new);
+
1460 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction);
+
1461
+
1462 shoot_tree_ptr->at(parent_shoot_ID)->childIDs[(int)shoot_tree_ptr->at(parent_shoot_ID)->current_node_number] = appended_shootID;
+
1463
+
1464 return appended_shootID;
+
1465
+
1466}
+
1467
+
1468uint PlantArchitecture::addChildShoot(uint plantID, int parent_shoot_ID, uint parent_node_index, uint current_node_number, const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max,
+
1469 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label, uint petiole_index) {
+
1470
+
1471 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1472 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1473 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
+
1474 helios_runtime_error("ERROR (PlantArchitecture::addShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
+
1475 }
+
1476
+
1477 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
1478
+
1479 auto shoot_parameters = shoot_types.at(shoot_type_label);
+
1480
+
1481 validateShootTypes(shoot_parameters);
+
1482
+
1483 if(parent_shoot_ID <= -1 || parent_shoot_ID >= shoot_tree_ptr->size() ){
+
1484 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Parent with ID of " + std::to_string(parent_shoot_ID) + " does not exist.");
+
1485 }else if(shoot_tree_ptr->at(parent_shoot_ID)->phytomers.size() <= parent_node_index ) {
+
1486 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Parent shoot does not have a node " + std::to_string(parent_node_index) + ".");
+
1487 }
+
1488
+
1489 uint parent_rank = (int)shoot_tree_ptr->at(parent_shoot_ID)->rank;
+
1490 int parent_node_count = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number;
+
1491
+
1492 vec3 shoot_base_position;
+
1493 if(parent_shoot_ID > -1 ){
+
1494 auto shoot_phytomers = &shoot_tree_ptr->at(parent_shoot_ID)->phytomers;
+
1495
+
1496 if(parent_node_index >= shoot_phytomers->size() ){
+
1497 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Requested to place child shoot on node " + std::to_string(parent_node_index) + " but parent only has " + std::to_string(shoot_phytomers->size()) + " nodes." );
+
1498 }
+
1499
+
1500 shoot_base_position = shoot_phytomers->at(parent_node_index)->internode_vertices.back();
+
1501
+
1502 //\todo Shift the shoot base position outward by the parent internode radius
+
1503
+
1504 }else{
+
1505 helios_runtime_error("PlantArchitecture::addChildShoot: Should not be here.");
+
1506 }
+
1507
+
1508 int childID = shoot_tree_ptr->size();
+
1509
+
1510 auto* shoot_new = (new Shoot(plantID, childID, parent_shoot_ID, parent_node_index, petiole_index, parent_rank + 1, shoot_base_position, shoot_base_rotation, current_node_number, internode_length_max, shoot_parameters, shoot_type_label, this));
+
1511 shoot_tree_ptr->emplace_back(shoot_new);
+
1512 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction);
+
1513
+
1514 shoot_tree_ptr->at(parent_shoot_ID)->childIDs[(int)parent_node_index] = childID;
+
1515
+
1516 return childID;
+
1517
+
1518}
+
1519
+
1520void PlantArchitecture::validateShootTypes( ShootParameters &shoot_parameters ) const{
+
1521
+
1522 assert( shoot_parameters.child_shoot_type_probabilities.size() == shoot_parameters.child_shoot_type_labels.size() );
+
1523
+
1524 for( int ind = shoot_parameters.child_shoot_type_labels.size()-1; ind>=0; ind-- ){
+
1525 if( shoot_types.find(shoot_parameters.child_shoot_type_labels.at(ind)) == shoot_types.end() ){
+
1526 shoot_parameters.child_shoot_type_labels.erase(shoot_parameters.child_shoot_type_labels.begin()+ind);
+
1527 shoot_parameters.child_shoot_type_probabilities.erase(shoot_parameters.child_shoot_type_probabilities.begin()+ind);
+
1528 }
+
1529 }
+
1530
+
1531}
+
1532
+
1533int PlantArchitecture::addPhytomerToShoot(uint plantID, uint shootID, const PhytomerParameters &phytomer_parameters, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction) {
+
1534
+
1535 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1536 helios_runtime_error("ERROR (PlantArchitecture::addPhytomerToShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1537 }
+
1538
+
1539 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
1540
+
1541 if(shootID >= shoot_tree_ptr->size() ){
+
1542 helios_runtime_error("ERROR (PlantArchitecture::addPhytomerToShoot): Parent with ID of " + std::to_string(shootID) + " does not exist.");
+
1543 }
+
1544
+
1545 auto current_shoot_ptr = plant_instances.at(plantID).shoot_tree.at(shootID);
+
1546
+
1547 //The base position of this phytomer is the last vertex position of the prior phytomer on the shoot
+
1548 vec3 base_position = current_shoot_ptr->phytomers.back()->internode_vertices.back();
+
1549 //The base rotation of this phytomer is the base rotation of the current shoot (the phytomer will be further rotated in the Phytomer constructor)
+
1550 AxisRotation base_rotation = current_shoot_ptr->base_rotation;
+
1551
+
1552 int pID = current_shoot_ptr->addPhytomer(phytomer_parameters, base_position, base_rotation, internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction);
+
1553
+
1554 current_shoot_ptr->current_node_number ++;
+
1555
+
1556 return pID;
+
1557
+
1558}
+
1559
+ +
1561 build_context_geometry_internode = false;
+
1562}
+
1563
+ +
1565 build_context_geometry_petiole = false;
+
1566}
+
1567
+ +
1569 build_context_geometry_peduncle = false;
+
1570}
+
1571
+ +
1573 ground_clipping_height = ground_height;
+
1574}
+
1575
+
1576void PlantArchitecture::incrementPhytomerInternodeGirth(uint plantID, uint shootID, uint node_number, float girth_change){
+
1577
+
1578 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1579 helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1580 }
+
1581
+
1582 auto parent_shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
1583
+
1584 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
1585 helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
+
1586 }else if( node_number>=parent_shoot->current_node_number ){
+
1587 helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Cannot scale internode " + std::to_string(node_number) + " because there are only " + std::to_string(parent_shoot->current_node_number) + " nodes in this shoot.");
+
1588 }
+
1589
+
1590 auto phytomer = parent_shoot->phytomers.at(node_number);
+
1591
+
1592 if( girth_change != 0.f ) {
+
1593
+
1594 int node = 0;
+
1595 for (uint objID: phytomer->internode_objIDs) { //should be automatically skipped if internode geometry was not built
+
1596
+
1597 float radius = context_ptr->getConeObjectNodeRadius(objID, 0);
+
1598
+
1599 if( radius*girth_change > phytomer->internode_radius_max ){
+
1600 girth_change = phytomer->internode_radius_max/radius;
+
1601 radius = phytomer->internode_radius_max;
+
1602 }
+
1603
+
1604 context_ptr->getConeObjectPointer(objID)->scaleGirth(girth_change);
+
1605
+
1606 phytomer->internode_radii.at(node) = context_ptr->getConeObjectNodeRadius(objID, 0);
+
1607
+
1608 node++;
+
1609 }
+
1610
+
1611 }
+
1612
+
1613 // \todo Shift all shoot bases outward to account for the girth scaling
+
1614
+
1615}
+
1616
+
1617void PlantArchitecture::shiftDownstreamShoots(uint plantID, std::vector<std::shared_ptr<Shoot>> &shoot_tree, std::shared_ptr<Shoot> parent_shoot_ptr, const vec3 &base_position ){
+
1618
+
1619 for(int node=0; node < parent_shoot_ptr->phytomers.size(); node++ ){
+
1620
+
1621 if(parent_shoot_ptr->childIDs.find(node) != parent_shoot_ptr->childIDs.end() ){
+
1622 auto child_shoot = shoot_tree.at(parent_shoot_ptr->childIDs.at(node));
+
1623 setShootOrigin(plantID, parent_shoot_ptr->childIDs.at(node), parent_shoot_ptr->phytomers.at(node)->internode_vertices.back());
+
1624 shiftDownstreamShoots(plantID, shoot_tree, child_shoot, parent_shoot_ptr->phytomers.at(node)->internode_vertices.back() );
+
1625 }
+
1626
+
1627 }
+
1628
+
1629}
+
1630
+
1631void PlantArchitecture::setPhytomerInternodeLengthScaleFraction(uint plantID, uint shootID, uint node_number, float internode_scale_factor_fraction) {
+
1632
+
1633 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1634 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerInternodeLengthScaleFraction): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1635 }
+
1636
+
1637 auto current_shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
1638
+
1639 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
1640 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerInternodeLengthScaleFraction): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
+
1641 }else if(node_number >= current_shoot->current_node_number ){
+
1642 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerInternodeLengthScaleFraction): Cannot scale internode " + std::to_string(node_number) + " because there are only " + std::to_string(current_shoot->current_node_number) + " nodes in this shoot.");
+
1643 }
+
1644 if(internode_scale_factor_fraction < 0 || internode_scale_factor_fraction > 1 ){
+
1645 std::cout << "WARNING (PlantArchitecture::setPhytomerInternodeLengthScaleFraction): Internode scaling factor was outside the range of 0 to 1. No scaling was applied." << std::endl;
+
1646 return;
+
1647 }
+
1648
+
1649 current_shoot->phytomers.at(node_number)->setInternodeLengthScaleFraction(internode_scale_factor_fraction);
+
1650
+
1651 for(int node=node_number; node < current_shoot->phytomers.size(); node++ ){
+
1652
+
1653 //shift all downstream phytomers
+
1654 if( node>node_number ) {
+
1655 vec3 upstream_base = current_shoot->phytomers.at(node - 1)->internode_vertices.back();
+
1656 current_shoot->phytomers.at(node)->setPhytomerBase(upstream_base);
+
1657 }
+
1658
+
1659 //shift all downstream shoots
+
1660 if( current_shoot->childIDs.find(node) != current_shoot->childIDs.end() ) {
+
1661 auto child_shoot = plant_instances.at(plantID).shoot_tree.at(current_shoot->childIDs.at(node));
+
1662 setShootOrigin(plantID, current_shoot->childIDs.at(node), current_shoot->phytomers.at(node)->internode_vertices.back());
+
1663 shiftDownstreamShoots(plantID, plant_instances.at(plantID).shoot_tree, child_shoot, current_shoot->phytomers.at(node)->internode_vertices.back());
+
1664 }
+
1665
+
1666 }
+
1667
+
1668 //shift appended shoot (if present)
+
1669 int node = current_shoot->phytomers.size();
+
1670 if( current_shoot->childIDs.find(node) != current_shoot->childIDs.end() ) {
+
1671 auto child_shoot = plant_instances.at(plantID).shoot_tree.at(current_shoot->childIDs.at(node));
+
1672 setShootOrigin(plantID, current_shoot->childIDs.at(node), current_shoot->phytomers.back()->internode_vertices.back());
+
1673 shiftDownstreamShoots(plantID, plant_instances.at(plantID).shoot_tree, child_shoot, current_shoot->phytomers.back()->internode_vertices.back());
+
1674 }
+
1675
+
1676}
+
1677
+
1678void PlantArchitecture::setShootOrigin(uint plantID, uint shootID, const helios::vec3 &origin){
+
1679
+
1680 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1681 helios_runtime_error("ERROR (PlantArchitecture::setShootOrigin): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1682 }else if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
1683 helios_runtime_error("ERROR (PlantArchitecture::setShootOrigin): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
+
1684 }
+
1685
+
1686 auto shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
1687
+
1688 if( shoot->phytomers.empty() ){
+
1689 return;
+
1690 }
+
1691
+
1692 uint node_count = shoot->phytomers.size();
+
1693
+
1694 shoot->phytomers.front()->setPhytomerBase(origin);
+
1695
+
1696 vec3 upstream_base = shoot->phytomers.front()->internode_vertices.front();
+
1697 for( int node=0; node<node_count; node++ ) {
+
1698 shoot->phytomers.at(node)->setPhytomerBase(upstream_base);
+
1699 if( shoot->childIDs.find(node) != shoot->childIDs.end() ){
+
1700 auto child_shoot = plant_instances.at(plantID).shoot_tree.at(shoot->childIDs.at(node));
+
1701 setShootOrigin(plantID, shoot->childIDs.at(node), upstream_base);
+
1702 }
+
1703 upstream_base = shoot->phytomers.at(node)->internode_vertices.back();
+
1704 }
+
1705
+
1706}
+
1707
+
1708void PlantArchitecture::setPhytomerLeafScale(uint plantID, uint shootID, uint node_number, float leaf_scale_factor_fraction) {
+
1709
+
1710 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1711 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerInternodeLengthScaleFraction): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1712 }
+
1713
+
1714 auto parent_shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
1715
+
1716 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
1717 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerLeafScale): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
+
1718 }else if( node_number>=parent_shoot->current_node_number ){
+
1719 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerLeafScale): Cannot scale leaf " + std::to_string(node_number) + " because there are only " + std::to_string(parent_shoot->current_node_number) + " nodes in this shoot.");
+
1720 }
+
1721 if(leaf_scale_factor_fraction < 0 || leaf_scale_factor_fraction > 1 ){
+
1722 std::cout << "WARNING (PlantArchitecture::setPhytomerLeafScale): Leaf scaling factor was outside the range of 0 to 1. No scaling was applied." << std::endl;
+
1723 return;
+
1724 }
+
1725
+
1726 parent_shoot->phytomers.at(node_number)->setLeafScaleFraction(leaf_scale_factor_fraction);
+
1727
+
1728}
+
1729
+
1730void PlantArchitecture::setPlantBasePosition(uint plantID, const helios::vec3 &base_position) {
+
1731
+
1732 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1733 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1734 }
+
1735
+
1736 plant_instances.at(plantID).base_position = base_position;
+
1737
+
1738 //\todo Does not work after shoots have been added to the plant.
+
1739 if( !plant_instances.at(plantID).shoot_tree.empty() ){
+
1740 std::cout << "WARNING (PlantArchitecture::setPlantBasePosition): This function does not work after shoots have been added to the plant." << std::endl;
+
1741 }
+
1742
+
1743}
+
1744
+
1745helios::vec3 PlantArchitecture::getPlantBasePosition(uint plantID) const{
+
1746 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1747 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1748 }else if( plant_instances.at(plantID).shoot_tree.empty() ){
+
1749 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " has no shoots, so could not get a base position.");
+
1750 }
+
1751 return plant_instances.at(plantID).base_position;
+
1752}
+
1753
+
1754void PlantArchitecture::setPlantAge(uint plantID, float a_current_age) {
+
1755 //\todo
+
1756// this->current_age = current_age;
+
1757}
+
1758
+
1759float PlantArchitecture::getPlantAge(uint plantID) const{
+
1760 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1761 helios_runtime_error("ERROR (PlantArchitecture::setPlantAge): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1762 }else if( plant_instances.at(plantID).shoot_tree.empty() ){
+
1763 helios_runtime_error("ERROR (PlantArchitecture::setPlantAge): Plant with ID of " + std::to_string(plantID) + " has no shoots, so could not get a base position.");
+
1764 }
+
1765 return plant_instances.at(plantID).current_age;
+
1766}
+
1767
+
1768void PlantArchitecture::harvestPlant(uint plantID){
+
1769
+
1770 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1771 helios_runtime_error("ERROR (PlantArchitecture::harvestPlant): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1772 }
+
1773
+
1774 for( auto& shoot: plant_instances.at(plantID).shoot_tree ){
+
1775 for( auto& phytomer: shoot->phytomers ){
+
1776
+
1777 phytomer->setFloralBudState( BUD_DEAD );
+
1778
+
1779 }
+
1780 }
+
1781
+
1782}
+
1783
+
1784void PlantArchitecture::removeShootLeaves(uint plantID, uint shootID){
+
1785 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1786 helios_runtime_error("ERROR (PlantArchitecture::removePlantLeaves): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1787 }
+
1788
+
1789 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
1790 helios_runtime_error("ERROR (PlantArchitecture::removeShootLeaves): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
+
1791 }
+
1792
+
1793 auto& shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
1794
+
1795 for( auto& phytomer: shoot->phytomers ){
+
1796 phytomer->removeLeaf();
+
1797 }
+
1798
+
1799}
+
1800
+
1801void PlantArchitecture::removePlantLeaves(uint plantID ){
+
1802 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1803 helios_runtime_error("ERROR (PlantArchitecture::removePlantLeaves): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1804 }
+
1805
+
1806 for( auto& shoot: plant_instances.at(plantID).shoot_tree ){
+
1807 for( auto& phytomer: shoot->phytomers ){
+
1808 phytomer->removeLeaf();
+
1809 }
+
1810 }
+
1811}
+
1812
+
1813void PlantArchitecture::makePlantDormant( uint plantID ){
+
1814 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1815 helios_runtime_error("ERROR (PlantArchitecture::makePlantDormant): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1816 }
+
1817
+
1818 for( auto& shoot: plant_instances.at(plantID).shoot_tree ){
+
1819 shoot->makeDormant();
+
1820 }
+
1821}
+
1822
+
1823void PlantArchitecture::breakPlantDormancy( uint plantID ){
+
1824 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1825 helios_runtime_error("ERROR (PlantArchitecture::breakPlantDormancy): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1826 }
+
1827
+
1828 for( auto& shoot: plant_instances.at(plantID).shoot_tree ){
+
1829 shoot->breakDormancy();
+
1830 }
+
1831}
+
1832
+
1833
+
1834uint PlantArchitecture::getShootNodeCount( uint plantID, uint shootID ) const{
+
1835 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1836 helios_runtime_error("ERROR (PlantArchitecture::getShootNodeCount): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1837 }else if( plant_instances.at(plantID).shoot_tree.size()<=shootID ){
+
1838 helios_runtime_error("ERROR (PlantArchitecture::getShootNodeCount): Shoot ID is out of range.");
+
1839 }
+
1840 return plant_instances.at(plantID).shoot_tree.at(shootID)->current_node_number;
+
1841}
+
1842
+
1843std::vector<uint> PlantArchitecture::getAllPlantObjectIDs(uint plantID) const{
+
1844
+
1845 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1846 helios_runtime_error("ERROR (PlantArchitecture::getAllPlantObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1847 }
+
1848
+
1849 std::vector<uint> objIDs;
+
1850
+
1851 for( const auto& shoot: plant_instances.at(plantID).shoot_tree ){
+
1852 for( const auto& phytomer: shoot->phytomers ){
+
1853 objIDs.insert(objIDs.end(), phytomer->internode_objIDs.begin(), phytomer->internode_objIDs.end() );
+
1854 std::vector<uint> petiole_objIDs_flat = flatten(phytomer->petiole_objIDs);
+
1855 objIDs.insert(objIDs.end(), petiole_objIDs_flat.begin(), petiole_objIDs_flat.end() );
+
1856 std::vector<uint> leaf_objIDs_flat = flatten(phytomer->leaf_objIDs);
+
1857 objIDs.insert(objIDs.end(), leaf_objIDs_flat.begin(), leaf_objIDs_flat.end() );
+
1858 std::vector<uint> inflorescence_objIDs_flat = flatten(phytomer->inflorescence_objIDs);
+
1859 objIDs.insert(objIDs.end(), inflorescence_objIDs_flat.begin(), inflorescence_objIDs_flat.end() );
+
1860 std::vector<uint> rachis_objIDs_flat = flatten(phytomer->peduncle_objIDs);
+
1861 objIDs.insert(objIDs.end(), rachis_objIDs_flat.begin(), rachis_objIDs_flat.end() );
+
1862 }
+
1863 }
+
1864
+
1865 return objIDs;
+
1866
+
1867}
+
1868
+
1869std::vector<uint> PlantArchitecture::getAllPlantUUIDs(uint plantID) const{
+
1870 return context_ptr->getObjectPrimitiveUUIDs(getAllPlantObjectIDs(plantID));
+
1871}
+
1872
+
1873std::vector<uint> PlantArchitecture::getPlantInternodeObjectIDs(uint plantID) const{
+
1874
+
1875 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1876 helios_runtime_error("ERROR (PlantArchitecture::getPlantInternodeObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1877 }
+
1878
+
1879 std::vector<uint> objIDs;
+
1880
+
1881 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
1882
+
1883 for( auto &shoot : shoot_tree ){
+
1884 for( auto &phytomer : shoot->phytomers ){
+
1885 objIDs.insert(objIDs.end(), phytomer->internode_objIDs.begin(), phytomer->internode_objIDs.end() );
+
1886 }
+
1887 }
+
1888
+
1889 return objIDs;
+
1890
+
1891}
+
1892
+
1893std::vector<uint> PlantArchitecture::getPlantPetioleObjectIDs(uint plantID) const{
+
1894 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1895 helios_runtime_error("ERROR (PlantArchitecture::getPlantPetioleObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1896 }
+
1897
+
1898 std::vector<uint> objIDs;
+
1899
+
1900 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
1901
+
1902 for( auto &shoot : shoot_tree ){
+
1903 for( auto &phytomer : shoot->phytomers ){
+
1904 for( auto &petiole : phytomer->petiole_objIDs ){
+
1905 objIDs.insert(objIDs.end(), petiole.begin(), petiole.end() );
+
1906 }
+
1907 }
+
1908 }
+
1909
+
1910 return objIDs;
+
1911
+
1912}
+
1913
+
1914std::vector<uint> PlantArchitecture::getPlantLeafObjectIDs(uint plantID) const{
+
1915 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1916 helios_runtime_error("ERROR (PlantArchitecture::getPlantLeafObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1917 }
+
1918
+
1919 std::vector<uint> objIDs;
+
1920
+
1921 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
1922
+
1923 for( auto &shoot : shoot_tree ){
+
1924 for( auto &phytomer : shoot->phytomers ){
+
1925 for( int petiole=0; petiole<phytomer->leaf_objIDs.size(); petiole++ ) {
+
1926 objIDs.insert(objIDs.end(), phytomer->leaf_objIDs.at(petiole).begin(), phytomer->leaf_objIDs.at(petiole).end());
+
1927 }
+
1928 }
+
1929 }
+
1930
+
1931 return objIDs;
+
1932
+
1933}
+
1934
+
1935std::vector<uint> PlantArchitecture::getPlantPeduncleObjectIDs(uint plantID) const{
+
1936
+
1937 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1938 helios_runtime_error("ERROR (PlantArchitecture::getPlantPeduncleObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1939 }
+
1940
+
1941 std::vector<uint> objIDs;
+
1942
+
1943 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
1944
+
1945 for( auto &shoot : shoot_tree ){
+
1946 for( auto &phytomer : shoot->phytomers ){
+
1947 for( auto &fbud : phytomer->peduncle_objIDs ){
+
1948 for( auto &peduncle : fbud ) {
+
1949 objIDs.insert(objIDs.end(), peduncle.begin(), peduncle.end());
+
1950 }
+
1951 }
+
1952 }
+
1953 }
+
1954
+
1955 return objIDs;
+
1956
+
1957}
+
1958
+
1959std::vector<uint> PlantArchitecture::getPlantFlowerObjectIDs(uint plantID) const{
+
1960
+
1961 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1962 helios_runtime_error("ERROR (PlantArchitecture::getPlantInflorescenceObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1963 }
+
1964
+
1965 std::vector<uint> objIDs;
+
1966
+
1967 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
1968
+
1969 for( auto &shoot : shoot_tree ){
+
1970 for( auto &phytomer : shoot->phytomers ){
+
1971 for( int petiole=0; petiole<phytomer->floral_buds.size(); petiole++ ){
+
1972 for( int bud=0; bud<phytomer->floral_buds.at(petiole).size(); bud++ ){
+
1973 if( phytomer->floral_buds.at(petiole).at(bud).state == BUD_FLOWER_OPEN || phytomer->floral_buds.at(petiole).at(bud).state == BUD_FLOWER_CLOSED ) {
+
1974 objIDs.insert(objIDs.end(), phytomer->inflorescence_objIDs.at(petiole).at(bud).begin(), phytomer->inflorescence_objIDs.at(petiole).at(bud).end());
+
1975 }
+
1976 }
+
1977 }
+
1978 }
+
1979 }
+
1980
+
1981 return objIDs;
+
1982
+
1983
+
1984}
+
1985
+
1986std::vector<uint> PlantArchitecture::getPlantFruitObjectIDs(uint plantID) const{
+
1987
+
1988 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1989 helios_runtime_error("ERROR (PlantArchitecture::getPlantInflorescenceObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1990 }
+
1991
+
1992 std::vector<uint> objIDs;
+
1993
+
1994 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
1995
+
1996 for( auto &shoot : shoot_tree ){
+
1997 for( auto &phytomer : shoot->phytomers ){
+
1998 for( int petiole=0; petiole<phytomer->floral_buds.size(); petiole++ ){
+
1999 for( int bud=0; bud<phytomer->floral_buds.at(petiole).size(); bud++ ){
+
2000 if( phytomer->floral_buds.at(petiole).at(bud).state == BUD_FRUITING ) {
+
2001 objIDs.insert(objIDs.end(), phytomer->inflorescence_objIDs.at(petiole).at(bud).begin(), phytomer->inflorescence_objIDs.at(petiole).at(bud).end());
+
2002 }
+
2003 }
+
2004 }
+
2005 }
+
2006 }
+
2007
+
2008 return objIDs;
+
2009
+
2010
+
2011}
+
2012
+
2013uint PlantArchitecture::addPlantInstance(const helios::vec3 &base_position, float current_age) {
+
2014
+
2015 if( current_age<0 ){
+
2016 helios_runtime_error("ERROR (PlantArchitecture::addPlantInstance): Current age must be greater than or equal to zero.");
+
2017 }
+
2018
+
2019 PlantInstance instance(base_position, current_age);
+
2020
+
2021 plant_instances.emplace(plant_count, instance);
+
2022
+
2023 plant_count++;
+
2024
+
2025 return plant_count-1;
+
2026
+
2027}
+
2028
+
2029uint PlantArchitecture::duplicatePlantInstance(uint plantID, const helios::vec3 &base_position, const AxisRotation &base_rotation, float current_age) {
+
2030
+
2031 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2032 helios_runtime_error("ERROR (PlantArchitecture::duplicatePlantInstance): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2033 }
+
2034
+
2035 auto plant_shoot_tree = &plant_instances.at(plantID).shoot_tree;
+
2036
+
2037 uint plantID_new = addPlantInstance(base_position, current_age);
+
2038
+
2039 if( plant_shoot_tree->empty() ){ //no shoots to add
+
2040 return plantID_new;
+
2041 }
+
2042 if( plant_shoot_tree->front()->phytomers.empty() ){ //no phytomers to add
+
2043 return plantID_new;
+
2044 }
+
2045
+
2046 for( auto shoot: *plant_shoot_tree ) {
+
2047
+
2048 uint shootID_new; //ID of the new shoot; will be set once the shoot is created on the first loop iteration
+
2049 for (int node = 0; node < shoot->current_node_number; node++) {
+
2050
+
2051 auto phytomer = shoot->phytomers.at(node);
+
2052 float internode_radius = phytomer->internode_radius_initial;
+
2053 float internode_length_max = phytomer->internode_length_max;
+
2054 float internode_scale_factor_fraction = phytomer->current_internode_scale_factor;
+
2055 float leaf_scale_factor_fraction = phytomer->current_leaf_scale_factor;
+
2056
+
2057 if (node == 0) {//first phytomer on shoot
+
2058 AxisRotation original_base_rotation = shoot->base_rotation;
+
2059 if(shoot->parent_shoot_ID == -1 ) { //first shoot on plant
+
2060 shootID_new = addBaseStemShoot(plantID_new, 1, original_base_rotation+base_rotation, internode_radius, internode_length_max, internode_scale_factor_fraction, leaf_scale_factor_fraction, shoot->shoot_type_label);
+
2061 }else{ //child shoot
+
2062 uint parent_node = plant_shoot_tree->at(shoot->parent_shoot_ID)->parent_node_index;
+
2063 uint parent_petiole_index = 0;
+
2064 for( auto &petiole : phytomer->vegetative_buds ) {
+
2065 shootID_new = addChildShoot(plantID_new, shoot->parent_shoot_ID, parent_node, 1, original_base_rotation, internode_radius, internode_length_max, internode_scale_factor_fraction, leaf_scale_factor_fraction,
+
2066 shoot->shoot_type_label,parent_petiole_index);
+
2067 parent_petiole_index++;
+
2068 }
+
2069 }
+
2070 } else {
+
2071 //each phytomer needs to be added one-by-one to account for possible internodes/leaves that are not fully elongated
+
2072 addPhytomerToShoot(plantID_new, shootID_new, shoot_types.at(shoot->shoot_type_label).phytomer_parameters, internode_radius, internode_length_max, internode_scale_factor_fraction, leaf_scale_factor_fraction);
+
2073 }
+
2074
+
2075 }
+
2076
+
2077 }
+
2078
+
2079 return plantID_new;
+
2080
+
2081}
+
2082
+
2083void PlantArchitecture::setPlantPhenologicalThresholds(uint plantID, float time_to_dormancy_break, float time_to_flower_initiation, float time_to_flower_opening, float time_to_fruit_set, float time_to_fruit_maturity, float time_to_senescence) {
+
2084
+
2085 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2086 helios_runtime_error("ERROR (PlantArchitecture::setPlantPhenologicalThresholds): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2087 }
+
2088
+
2089 plant_instances.at(plantID).dd_to_dormancy_break = time_to_dormancy_break;
+
2090 plant_instances.at(plantID).dd_to_flower_initiation = time_to_flower_initiation;
+
2091 plant_instances.at(plantID).dd_to_flower_opening = time_to_flower_opening;
+
2092 plant_instances.at(plantID).dd_to_fruit_set = time_to_fruit_set;
+
2093 plant_instances.at(plantID).dd_to_fruit_maturity = time_to_fruit_maturity;
+
2094 plant_instances.at(plantID).dd_to_senescence = time_to_senescence;
+
2095
+
2096}
+
2097
+
2098
+ +
2100
+
2101 for (auto &plant: plant_instances ){
+
2102
+
2103 uint plantID = plant.first;
+
2104 PlantInstance& plant_instance = plant.second;
+
2105
+
2106 auto shoot_tree = &plant_instance.shoot_tree;
+
2107
+
2108 //\todo placeholder
+
2109 incrementAssimilatePool(plantID, -10);
+
2110
+
2111 if( plant_instance.current_age > plant_instance.dd_to_senescence ){
+
2112 for (const auto& shoot : *shoot_tree) {
+
2113 shoot->makeDormant();
+
2114 shoot->assimilate_pool = 100;
+
2115 plant_instance.current_age = 0;
+
2116 }
+
2117 harvestPlant(plantID);
+
2118 std::cout << "Going dormant" << std::endl;
+
2119 continue;
+
2120 }
+
2121
+
2122 //accounting for case of dt>phyllochron
+
2123 float phyllochron_min = shoot_tree->front()->shoot_parameters.phyllochron.val();
+
2124 for ( int i=1; i<shoot_tree->size(); i++ ){
+
2125 if( shoot_tree->at(i)->shoot_parameters.phyllochron.val() < phyllochron_min ){
+
2126 phyllochron_min = shoot_tree->at(i)->shoot_parameters.phyllochron.val();
+
2127 }
+
2128 }
+
2129
+
2130 int Nsteps = std::floor(dt/phyllochron_min);
+
2131 float remainder_time = dt-phyllochron_min*float(Nsteps);
+
2132 if( remainder_time>0.f ){
+
2133 Nsteps++;
+
2134 }
+
2135
+
2136 for( int timestep=0; timestep<Nsteps; timestep++ ) {
+
2137
+
2138 float dt_max = phyllochron_min;
+
2139 if (timestep == Nsteps - 1 && remainder_time != 0.f ) {
+
2140 dt_max = remainder_time;
+
2141 }
+
2142
+
2143 plant_instance.current_age += dt_max;
+
2144
+
2145 size_t shoot_count = shoot_tree->size();
+
2146 for ( int i=0; i<shoot_count; i++ ){
+
2147
+
2148 auto shoot = shoot_tree->at(i);
+
2149
+
2150 // ****** PHENOLOGICAL TRANSITIONS ****** //
+
2151
+
2152 // breaking dormancy
+
2153 bool dormancy_broken_this_timestep = false;
+
2154 if (shoot->dormancy_cycles >= 1 && shoot->dormant && plant_instance.current_age >= plant_instance.dd_to_dormancy_break) {
+
2155 shoot->breakDormancy();
+
2156 dormancy_broken_this_timestep = true;
+
2157 shoot->assimilate_pool = 1e6;
+
2158// std::cout << "Shoot " << shoot->ID << " breaking dormancy" << std::endl;
+
2159 }
+
2160
+
2161 if (shoot->dormant) { //dormant, don't do anything
+
2162 continue;
+
2163 }
+
2164
+
2165 for (auto &phytomer: shoot->phytomers) {
+
2166
+
2167 if (!shoot->dormant) {
+
2168 phytomer->time_since_dormancy += dt_max;
+
2169 }
+
2170
+
2171 if (phytomer->floral_buds.empty()) { //no floral buds - skip this phytomer
+
2172 continue;
+
2173 }
+
2174
+
2175 for (auto &petiole: phytomer->floral_buds) {
+
2176 for (auto &fbud: petiole) {
+
2177
+
2178 if (fbud.state != BUD_DORMANT && fbud.state != BUD_DEAD) {
+
2179 fbud.time_counter += dt_max;
+
2180 }
+
2181
+
2182 // -- Flowering -- //
+
2183 if (shoot->shoot_parameters.phytomer_parameters.inflorescence.flower_prototype_function != nullptr) { //user defined a flower prototype function
+
2184 // -- Flower initiation (closed flowers) -- //
+
2185 if (fbud.state == BUD_ACTIVE && plant_instance.dd_to_flower_initiation >= 0.f) { //bud is active and flower initiation is enabled
+
2186 if ((!shoot->shoot_parameters.flowers_require_dormancy && plant_instance.current_age >= plant_instance.dd_to_flower_initiation) ||
+
2187 (shoot->shoot_parameters.flowers_require_dormancy && phytomer->time_since_dormancy >= plant_instance.dd_to_flower_initiation)) {
+
2188 fbud.time_counter = 0;
+
2189 if (context_ptr->randu() < shoot->shoot_parameters.flower_bud_break_probability.val() ) {
+
2190 phytomer->setFloralBudState(BUD_FLOWER_CLOSED, fbud);
+
2191 } else {
+
2192 phytomer->setFloralBudState(BUD_DEAD, fbud);
+
2193 }
+
2194 if (shoot->shoot_parameters.determinate_shoot_growth) {
+
2195 shoot->terminateApicalBud();
+
2196 shoot->terminateAxillaryVegetativeBuds();
+
2197 }
+
2198 }
+
2199
+
2200 // -- Flower opening -- //
+
2201 } else if ((fbud.state == BUD_FLOWER_CLOSED && plant_instance.dd_to_flower_opening >= 0.f) ||
+
2202 (fbud.state == BUD_ACTIVE && plant_instance.dd_to_flower_initiation < 0.f && plant_instance.dd_to_flower_opening >= 0.f)) {
+
2203 if (fbud.time_counter >= plant_instance.dd_to_flower_opening) {
+
2204 fbud.time_counter = 0;
+
2205 if( fbud.state == BUD_FLOWER_CLOSED ) {
+
2206 phytomer->setFloralBudState(BUD_FLOWER_OPEN, fbud);
+
2207 }else{
+
2208 if (context_ptr->randu() < shoot->shoot_parameters.flower_bud_break_probability.val() ) {
+
2209 phytomer->setFloralBudState(BUD_FLOWER_OPEN, fbud);
+
2210 } else {
+
2211 phytomer->setFloralBudState(BUD_DEAD, fbud);
+
2212 }
+
2213 }
+
2214 if (shoot->shoot_parameters.determinate_shoot_growth) {
+
2215 shoot->terminateApicalBud();
+
2216 shoot->terminateAxillaryVegetativeBuds();
+
2217 }
+
2218 }
+
2219 }
+
2220 }
+
2221
+
2222 // -- Fruit Set -- //
+
2223 // If the flower bud is in a 'flowering' state, the fruit set occurs after a certain amount of time
+
2224 if (shoot->shoot_parameters.phytomer_parameters.inflorescence.fruit_prototype_function != nullptr) {
+
2225 if ((fbud.state == BUD_FLOWER_OPEN && plant_instance.dd_to_fruit_set >= 0.f) || //flower opened and fruit set is enabled
+
2226 (fbud.state == BUD_ACTIVE && plant_instance.dd_to_flower_initiation < 0.f && plant_instance.dd_to_flower_opening < 0.f && plant_instance.dd_to_fruit_set >= 0.f) || //jumped straight to fruit set with no flowering
+
2227 (fbud.state == BUD_FLOWER_CLOSED && plant_instance.dd_to_flower_opening < 0.f && plant_instance.dd_to_fruit_set >= 0.f)) { //jumped from closed flower to fruit set with no flower opening
+
2228 std::cout << "potential for fruit set " << fbud.state << std::endl;
+
2229 if (fbud.time_counter >= plant_instance.dd_to_fruit_set) {
+
2230 fbud.time_counter = 0;
+
2231 if (context_ptr->randu() < shoot->shoot_parameters.fruit_set_probability.val() ) {
+
2232 phytomer->setFloralBudState(BUD_FRUITING, fbud);
+
2233 } else {
+
2234 phytomer->setFloralBudState(BUD_DEAD, fbud);
+
2235 }
+
2236 if (shoot->shoot_parameters.determinate_shoot_growth) {
+
2237 shoot->terminateApicalBud();
+
2238 shoot->terminateAxillaryVegetativeBuds();
+
2239 }
+
2240 }
+
2241 }
+
2242 }
+
2243
+
2244 }
+
2245 }
+
2246
+
2247 }
+
2248
+
2249 int node_index = 0;
+
2250 for (auto &phytomer: shoot->phytomers) {
+
2251
+
2252 // ****** GROWTH/SCALING OF CURRENT PHYTOMERS/FRUIT ****** //
+
2253
+
2254 //scale internode length
+
2255 if (phytomer->current_internode_scale_factor < 1) {
+
2256 float dL_internode = dt_max * shoot->shoot_parameters.elongation_rate.val() * phytomer->internode_length_max;
+
2257 float length_scale = fmin(1.f, (phytomer->internode_length + dL_internode) / phytomer->internode_length_max);
+
2258 setPhytomerInternodeLengthScaleFraction(plantID, shoot->ID, node_index, length_scale);
+
2259 }
+
2260
+
2261 //scale internode girth
+
2262 if( phytomer->internode_radii.front() < phytomer->internode_radius_max ) {
+
2263 float dR = ( 1.f + dt_max * shoot->shoot_parameters.girth_growth_rate.val()/phytomer->internode_radii.front() );
+
2264 incrementPhytomerInternodeGirth(plantID, shoot->ID, node_index, dR);
+
2265 }
+
2266
+
2267 //scale petiole/leaves
+
2268 if (phytomer->hasLeaf() && phytomer->current_leaf_scale_factor <= 1) {
+
2269 float leaf_length = phytomer->current_leaf_scale_factor * phytomer->phytomer_parameters.leaf.prototype_scale.val();
+
2270 float dL_leaf = dt_max * shoot->shoot_parameters.elongation_rate.val() * phytomer->phytomer_parameters.leaf.prototype_scale.val();
+
2271 float scale = fmin(1.f, (leaf_length + dL_leaf) / phytomer->phytomer_parameters.leaf.prototype_scale.val() );
+
2272 phytomer->setLeafScaleFraction(scale);
+
2273 }
+
2274
+
2275 //Fruit Growth
+
2276 for (auto &petiole: phytomer->floral_buds) {
+
2277 for (auto &fbud: petiole) {
+
2278
+
2279 // If the floral bud it in a 'fruiting' state, the fruit grows with time
+
2280 if (fbud.state == BUD_FRUITING && fbud.time_counter > 0) {
+
2281 float scale = fmin(1, fbud.time_counter / plant_instance.dd_to_fruit_maturity);
+
2282 phytomer->setInflorescenceScaleFraction(fbud, scale);
+
2283 }
+
2284 }
+
2285 }
+
2286
+
2287 // ****** NEW CHILD SHOOTS FROM VEGETATIVE BUDS ****** //
+
2288 uint parent_petiole_index = 0;
+
2289 for (auto &petiole: phytomer->vegetative_buds) {
+
2290 for (auto &vbud: petiole) {
+
2291
+
2292 if (vbud.state == BUD_ACTIVE && phytomer->age + dt_max > shoot->shoot_parameters.vegetative_bud_break_time.val()) {
+
2293
+
2294 ShootParameters *new_shoot_parameters = &shoot_types.at(vbud.shoot_type_label);
+
2295 int parent_node_count = shoot->current_node_number;
+
2296
+
2297 float insertion_angle_adjustment = fmin(shoot->shoot_parameters.child_insertion_angle_tip.val() + shoot->shoot_parameters.child_insertion_angle_decay_rate.val() * float(parent_node_count - phytomer->shoot_index.x - 1),90.f);
+
2298 AxisRotation base_rotation = make_AxisRotation(deg2rad(insertion_angle_adjustment), deg2rad(new_shoot_parameters->base_yaw.val()), deg2rad(new_shoot_parameters->base_roll.val()));
+
2299 new_shoot_parameters->base_yaw.resample();
+
2300
+
2301 //scale the shoot internode length based on proximity from the tip
+
2302 float internode_length_max;
+
2303 if (new_shoot_parameters->growth_requires_dormancy) {
+
2304 internode_length_max = fmax(new_shoot_parameters->child_internode_length_max.val() - new_shoot_parameters->child_internode_length_decay_rate.val() * float(parent_node_count - phytomer->shoot_index.x - 1),
+
2305 new_shoot_parameters->child_internode_length_min.val());
+
2306 } else {
+
2307 internode_length_max = new_shoot_parameters->child_internode_length_max.val();
+
2308 }
+
2309
+
2310 float internode_radius = shoot_types.at(vbud.shoot_type_label).internode_radius_initial.val();
+
2311
+
2312// std::cout << "Adding child shoot of type " << vbud.shoot_type_label << std::endl;
+
2313
+
2314 uint childID = addChildShoot(plantID, shoot->ID, node_index, 1, base_rotation, internode_radius, internode_length_max, 0.01, 0.01, vbud.shoot_type_label, parent_petiole_index);
+
2315
+
2316 phytomer->setVegetativeBudState( BUD_DEAD, vbud );
+
2317 vbud.shoot_ID = childID;
+
2318 shoot_tree->at(childID)->dormant = false;
+
2319
+
2320 }
+
2321
+
2322 }
+
2323 parent_petiole_index++;
+
2324 }
+
2325
+
2326 // check for ground collisions
+
2327 if( ground_clipping_height!=-99999 ){
+
2328
+
2329 // internode
+
2330 if ( phytomer->shoot_index.x>0 && detectGroundCollision( phytomer->internode_objIDs ) ) {
+
2331 context_ptr->deleteObject(phytomer->internode_objIDs);
+
2332 phytomer->internode_objIDs.clear();
+
2333 }
+
2334
+
2335 // leaves
+
2336 for( uint petiole=0; petiole<phytomer->leaf_objIDs.size(); petiole++ ) {
+
2337
+
2338 if ( detectGroundCollision(phytomer->leaf_objIDs.at(petiole)) ) {
+
2339 context_ptr->deleteObject(phytomer->leaf_objIDs.at(petiole));
+
2340 phytomer->leaf_objIDs.at(petiole).clear();
+
2341 phytomer->leaf_bases.at(petiole).clear();
+
2342 context_ptr->deleteObject(phytomer->petiole_objIDs.at(petiole));
+
2343 phytomer->petiole_objIDs.at(petiole).clear();
+
2344 }
+
2345
+
2346 }
+
2347
+
2348 //inflorescence
+
2349 for( uint petiole=0; petiole<phytomer->inflorescence_objIDs.size(); petiole++ ){
+
2350 for( uint bud=0; bud<phytomer->inflorescence_objIDs.at(petiole).size(); bud++ ) {
+
2351 for (uint fruit = 0; fruit < phytomer->inflorescence_objIDs.at(petiole).at(bud).size(); fruit++) {
+
2352 if (detectGroundCollision(phytomer->inflorescence_objIDs.at(petiole).at(bud).at(fruit))) {
+
2353 context_ptr->deleteObject(phytomer->inflorescence_objIDs.at(petiole).at(bud).at(fruit));
+
2354 phytomer->inflorescence_objIDs.at(petiole).at(bud).erase(phytomer->inflorescence_objIDs.at(petiole).at(bud).begin() + fruit);
+
2355 }
+
2356 }
+
2357 }
+
2358 }
+
2359
+
2360 }
+
2361
+
2362
+
2363
+
2364 phytomer->age += dt_max;
+
2365
+
2366 if( phytomer->build_context_geometry_internode ) {
+
2367 context_ptr->setObjectData(phytomer->internode_objIDs, "age", phytomer->age);
+
2368 }
+
2369 if( phytomer->build_context_geometry_petiole ) {
+
2370 context_ptr->setObjectData(phytomer->petiole_objIDs, "age", phytomer->age);
+
2371 }
+
2372 context_ptr->setObjectData(phytomer->leaf_objIDs, "age", phytomer->age);
+
2373
+
2374 node_index++;
+
2375 }
+
2376
+
2377 // if shoot has reached max_nodes, stop apical growth
+
2378 if (shoot->current_node_number >= shoot->shoot_parameters.max_nodes.val()) {
+
2379 shoot->terminateApicalBud();
+
2380 }
+
2381
+
2382 // If the apical bud is dead, don't do anything more with the shoot
+
2383 if (!shoot->meristem_is_alive) {
+
2384 continue;
+
2385 }
+
2386
+
2387 // ****** PHYLLOCHRON - NEW PHYTOMERS ****** //
+
2388 shoot->phyllochron_counter += dt_max;
+
2389 if (shoot->phyllochron_counter >= float(shoot->shoot_parameters.leaf_flush_count) * shoot->shoot_parameters.phyllochron.val()) {
+
2390 float internode_radius = shoot->shoot_parameters.internode_radius_initial.val();
+
2391 float internode_length_max = shoot->internode_length_max_shoot_initial;
+
2392 for (int leaf = 0; leaf < shoot->shoot_parameters.leaf_flush_count; leaf++) {
+
2393 addPhytomerToShoot(plantID, shoot->ID, shoot_types.at(shoot->shoot_type_label).phytomer_parameters, internode_radius, internode_length_max, 0.01, 0.01); //\todo These factors should be set to be consistent with the shoot
+
2394 }
+
2395 shoot->shoot_parameters.phyllochron.resample();
+
2396 shoot->phyllochron_counter = 0;
+
2397 }
+
2398
+
2399 }
+
2400
+
2401 }
+
2402
+
2403
+
2404 }
+
2405}
+
2406
+
2407void PlantArchitecture::incrementAssimilatePool( uint plantID, uint shootID, float assimilate_increment_mg_g ){
+
2408
+
2409 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2410 helios_runtime_error("ERROR (PlantArchitecture::incrementAssimilatePool): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2411 }else if( plant_instances.at(plantID).shoot_tree.size()<=shootID ){
+
2412 helios_runtime_error("ERROR (PlantArchitecture::incrementAssimilatePool): Shoot ID is out of range.");
+
2413 }
+
2414
+
2415 plant_instances.at(plantID).shoot_tree.at(shootID)->assimilate_pool += assimilate_increment_mg_g;
+
2416
+
2417}
+
2418
+
2419void PlantArchitecture::incrementAssimilatePool( uint plantID, float assimilate_increment_mg_g ){
+
2420
+
2421 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2422 helios_runtime_error("ERROR (PlantArchitecture::incrementAssimilatePool): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2423 }
+
2424
+
2425 for( auto &shoot: plant_instances.at(plantID).shoot_tree ){
+
2426 shoot->assimilate_pool += assimilate_increment_mg_g;
+
2427 }
+
2428
+
2429}
+
2430
+
2431void PlantArchitecture::accumulateShootPhotosynthesis( float dt ){
+
2432
+
2433 uint A_prim_data_missing = 0;
+
2434
+
2435 for( auto &plant: plant_instances ){
+
2436
+
2437 uint plantID = plant.first;
+
2438 auto shoot_tree = &plant.second.shoot_tree;
+
2439
+
2440 for( auto &shoot: *shoot_tree ){
+
2441
+
2442 float net_photosynthesis = 0;
+
2443
+
2444 for( auto &phytomer: shoot->phytomers ){
+
2445
+
2446 for( auto &leaf_objID: flatten(phytomer->leaf_objIDs) ){
+
2447 for( uint UUID : context_ptr->getObjectPrimitiveUUIDs(leaf_objID) ){
+
2448 if( context_ptr->doesPrimitiveDataExist(UUID, "net_photosynthesis") && context_ptr->getPrimitiveDataType(UUID,"net_photosynthesis")==HELIOS_TYPE_FLOAT ){
+
2449 float A;
+
2450 context_ptr->getPrimitiveData(UUID,"net_photosynthesis",A);
+
2451 net_photosynthesis += A*context_ptr->getPrimitiveArea(UUID)*dt;
+
2452 }else{
+
2453 A_prim_data_missing++;
+
2454 }
+
2455 }
+
2456 }
+
2457
+
2458 }
+
2459
+
2460 shoot->assimilate_pool += net_photosynthesis;
+
2461
+
2462 }
+
2463
+
2464 }
+
2465
+
2466 if( A_prim_data_missing>0 ){
+
2467 std::cout << "WARNING (PlantArchitecture::accumulateShootPhotosynthesis): " << A_prim_data_missing << " leaf primitives were missing net_photosynthesis primitive data. Did you run the photosynthesis model?" << std::endl;
+
2468 }
+
2469
+
2470}
+
2471
+
2472
+
2473std::vector<uint> makeTubeFromCones(uint radial_subdivisions, const std::vector<helios::vec3> &vertices, const std::vector<float> &radii, const std::vector<helios::RGBcolor> &colors, helios::Context *context_ptr) {
+
2474
+
2475 uint Nverts = vertices.size();
+
2476
+
2477 if( radii.size()!=Nverts || colors.size()!=Nverts ){
+
2478 helios_runtime_error("ERROR (makeTubeFromCones): Length of vertex vectors is not consistent.");
+
2479 }
+
2480
+
2481 std::vector<uint> objIDs(Nverts-1);
+
2482
+
2483 for( uint v=0; v<Nverts-1; v++ ){
+
2484
+
2485 objIDs.at(v) = context_ptr->addConeObject(radial_subdivisions, vertices.at(v), vertices.at(v + 1), radii.at(v), radii.at(v + 1), colors.at(v) );
+
2486
+
2487 }
+
2488
+
2489 return objIDs;
+
2490
+
2491}
+
2492
+
2493bool PlantArchitecture::detectGroundCollision(uint objID) {
+
2494 std::vector<uint> objIDs = {objID};
+
2495 return detectGroundCollision(objIDs);
+
2496}
+
2497
+
2498bool PlantArchitecture::detectGroundCollision(const std::vector<uint> &objID) {
+
2499
+
2500 for( uint ID : objID ){
+
2501 const std::vector<uint> &UUIDs = context_ptr->getObjectPrimitiveUUIDs(ID);
+
2502 for( uint UUID : UUIDs ){
+
2503 const std::vector<vec3> &vertices = context_ptr->getPrimitiveVertices(UUID);
+
2504 for( const vec3 &v : vertices ){
+
2505 if( v.z<ground_clipping_height ){
+
2506 return true;
+
2507 }
+
2508 }
+
2509 }
+
2510 }
+
2511 return false;
+
2512
+
2513}
+
helios::vec3 interpolateTube(const std::vector< helios::vec3 > &P, float frac)
Interpolate the position of a point along a tube.
+
float interpolateTube(const std::vector< float > &P, float frac)
Interpolate the radius of a point along a tube.
+ +
std::vector< uint > makeTubeFromCones(uint radial_subdivisions, const std::vector< helios::vec3 > &vertices, const std::vector< float > &radii, const std::vector< helios::RGBcolor > &colors, helios::Context *context_ptr)
Add geometry to the Context consisting of a series of Cone objects to form a tube-like shape.
+ +
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
+
std::vector< uint > getPlantFlowerObjectIDs(uint plantID) const
Get object IDs for all inflorescence objects for a given plant.
+
void enableGroundClipping(float ground_height=0.f)
Enable automatic removal of organs that are below the ground plane.
+
std::vector< uint > getAllPlantUUIDs(uint plantID) const
Get primitive UUIDs for all primitives in a given plant.
+
void setPlantPhenologicalThresholds(uint plantID, float time_to_dormancy_break, float time_to_flower_initiation, float time_to_flower_opening, float time_to_fruit_set, float time_to_fruit_maturity, float time_to_senescence)
Specify the threshold values for plant phenological stages.
+
std::vector< uint > getPlantInternodeObjectIDs(uint plantID) const
Get object IDs for all internode (Tube) objects for a given plant.
+
int addPhytomerToShoot(uint plantID, uint shootID, const PhytomerParameters &phytomer_parameters, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction)
Add a new phytomer at the terminal bud of a shoot.
+
void disablePeduncleContextBuild()
Do not build peduncle primitive geometry in the Context.
+
void defineShootType(const std::string &shoot_type_label, const ShootParameters &shoot_params)
Define a new shoot type based on a set of ShootParameters.
+
uint addBaseStemShoot(uint plantID, uint current_node_number, const AxisRotation &base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label)
Define the stem/trunk shoot (base of plant) to start a new plant. This requires a plant instance has ...
+
std::vector< uint > getPlantFruitObjectIDs(uint plantID) const
Get object IDs for all fruit objects for a given plant.
+
void disablePetioleContextBuild()
Do not build petiole primitive geometry in the Context.
+
PlantArchitecture(helios::Context *context_ptr)
Main architectural model class constructor.
+
uint addChildShoot(uint plantID, int parent_shoot_ID, uint parent_node_index, uint current_node_number, const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label, uint petiole_index=0)
Manually add a child shoot at the axillary bud of a phytomer.
+
uint duplicatePlantInstance(uint plantID, const helios::vec3 &base_position, const AxisRotation &base_rotation, float current_age)
Duplicate an existing plant instance and specify its base position and age.
+
uint appendShoot(uint plantID, int parent_shoot_ID, uint current_node_number, const AxisRotation &base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label)
Manually append a new shoot at the end of an existing shoot. This is used when the characteristics of...
+
std::vector< uint > getAllPlantObjectIDs(uint plantID) const
Get object IDs for all organs objects for a given plant.
+
std::vector< uint > getPlantPetioleObjectIDs(uint plantID) const
Get object IDs for all petiole (Tube) objects for a given plant.
+
void disableInternodeContextBuild()
Do not build internode primitive geometry in the Context.
+
std::vector< uint > getPlantPeduncleObjectIDs(uint plantID) const
Get object IDs for all peduncle (Tube) objects for a given plant.
+
void advanceTime(float dt)
Advance plant growth by a specified time interval.
+
std::vector< uint > getPlantLeafObjectIDs(uint plantID) const
Get object IDs for all leaf objects for a given plant.
+
void scaleLength(float S)
Method to scale the length of the cone.
Definition: Context.cpp:3578
+
void scaleGirth(float S)
Method to scale the girth of the cone.
Definition: Context.cpp:3627
+
Stores the state associated with simulation.
Definition: Context.h:1705
+
float randn()
Draw a random number from a normal distribution with mean = 0, stddev = 1.
Definition: Context.cpp:1147
+
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition: Context.cpp:6464
+
void getPrimitiveData(uint UUID, const char *label, int &data) const
Get data associated with a primitive element.
+
Cone * getConeObjectPointer(uint ObjID) const
Get a pointer to a Cone Compound Object.
Definition: Context.cpp:3492
+
void rotateObject(uint ObjID, float rot, const char *axis)
Rotate a single compound object about the x, y, or z axis.
Definition: Context.cpp:2657
+
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition: Context.cpp:1121
+
void setObjectData(uint objID, const char *label, const int &data)
Add data value (int) associated with a compound object.
+
void translateObject(uint ObjID, const vec3 &shift)
Translate a single compound object.
Definition: Context.cpp:2647
+
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
+
std::vector< uint > getObjectPrimitiveUUIDs(uint ObjID) const
Get primitive UUIDs associated with compound object (single object ID input)
Definition: Context.cpp:2697
+
std::minstd_rand0 * getRandomGenerator()
Get the random number generator engine.
Definition: Context.cpp:49
+
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
+
void deleteObject(uint ObjID)
Delete a single Compound Object from the context.
Definition: Context.cpp:2419
+
void clearPrimitiveData(uint UUID, const char *label)
Clear primitive data for a single primitive based on its UUID.
+
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
+
float getConeObjectNodeRadius(uint &ObjectID, int number) const
get a node radius of a Cone object from the context
Definition: Context.cpp:7601
+
helios::vec3 getConeObjectNode(uint &ObjectID, int number) const
get a node of a Cone object from the context
Definition: Context.cpp:7597
+
std::vector< helios::vec3 > getPrimitiveVertices(uint UUID) const
Method to return the (x,y,z) coordinates of the vertices of a Primitive.
Definition: Context.cpp:6533
+
void scaleObject(uint ObjID, const helios::vec3 &scalefact)
Method to scale a compound object in the x-, y- and z-directions.
Definition: Context.cpp:2687
+
vec3 rotatePointAboutLine(const vec3 &point, const vec3 &line_base, const vec3 &line_direction, float theta)
Rotate a 3D vector about an arbitrary line.
Definition: global.cpp:136
+
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition: global.cpp:29
+
uint addTubeObject(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition: Context.cpp:4083
+
uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone compound object to the Context.
Definition: Context.cpp:4784
+
std::vector< int > flatten(const std::vector< std::vector< int > > &vec)
Function to flatten a 2D int vector into a 1D vector.
Definition: global.cpp:1682
+
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition: global.cpp:581
+
float deg2rad(float deg)
Convert degrees to radians.
Definition: global.cpp:547
+
void resize_vector(std::vector< std::vector< anytype > > &vec, uint Nx, uint Ny)
Resize 2D C++ vector.
Definition: global.cpp:1044
+
float acos_safe(float x)
arccosine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition: global.cpp:233
+
float sum(const std::vector< float > &vect)
Sum of a vector of floats.
Definition: global.cpp:874
+
float asin_safe(float x)
arcsine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition: global.cpp:239
+
int2 make_int2(int X, int Y)
Make an int2 vector from two ints.
+
vec3 make_vec3(float X, float Y, float Z)
Make a vec3 from three floats.
+
vec3 cross(const vec3 &a, const vec3 &b)
Cross product of two vec3 vectors.
+ + + +
PhytomerParameters()
Default constructor - does not set random number generator.
+ + +
bool sampleChildShootType(std::string &child_shoot_type_label) const
Randomly sample the type of a child shoot based on the probabilities defined in the shoot parameters.
+ +
ShootParameters()
Default constructor - does not set random number generator.
+ +
Vector of three elements of type 'float'.
+
float x
First element in vector.
+
float z
Third element in vector.
+
void normalize()
Normalize vector components such that the magnitude is unity.
+
float y
Second element in vector.
+
+ + + + diff --git a/doc/html/_plant_architecture_8h.html b/doc/html/_plant_architecture_8h.html new file mode 100644 index 000000000..aaeb9d584 --- /dev/null +++ b/doc/html/_plant_architecture_8h.html @@ -0,0 +1,286 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+ +
PlantArchitecture.h File Reference
+
+
+
#include "Context.h"
+#include <random>
+#include <utility>
+
+

Go to the source code of this file.

+ + + + + + + + + + + + + + + + + + + + + + + + +

+Data Structures

struct  RandomParameter_float
 
struct  RandomParameter_int
 
struct  AxisRotation
 
struct  VegetativeBud
 
struct  FloralBud
 
struct  PhytomerParameters
 
struct  ShootParameters
 
struct  Phytomer
 
struct  Shoot
 
struct  PlantInstance
 
class  PlantArchitecture
 
+ + + +

+Enumerations

enum  BudState {
+  BUD_DORMANT = 0 +, BUD_ACTIVE = 1 +, BUD_FLOWER_CLOSED = 2 +, BUD_FLOWER_OPEN = 3 +,
+  BUD_FRUITING = 4 +, BUD_DEAD = 5 +
+ }
 
+ + + + + + +

+Functions

AxisRotation make_AxisRotation (float a_pitch, float a_yaw, float a_roll)
 
std::vector< uint > makeTubeFromCones (uint radial_subdivisions, const std::vector< helios::vec3 > &vertices, const std::vector< float > &radii, const std::vector< helios::RGBcolor > &colors, helios::Context *context_ptr)
 Add geometry to the Context consisting of a series of Cone objects to form a tube-like shape.
 
+

Detailed Description

+

Primary header file for plant architecture plug-in.

+

Copyright (C) 2016-2024 Brian Bailey

+

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.

+

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

+ +

Definition in file PlantArchitecture.h.

+

Enumeration Type Documentation

+ +

◆ BudState

+ +
+
+ + + + +
enum BudState
+
+ +

Definition at line 243 of file PlantArchitecture.h.

+ +
+
+

Function Documentation

+ +

◆ make_AxisRotation()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
AxisRotation make_AxisRotation (float a_pitch,
float a_yaw,
float a_roll 
)
+
+inline
+
+ +

Definition at line 231 of file PlantArchitecture.h.

+ +
+
+ +

◆ makeTubeFromCones()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
std::vector< uint > makeTubeFromCones (uint radial_subdivisions,
const std::vector< helios::vec3 > & vertices,
const std::vector< float > & radii,
const std::vector< helios::RGBcolor > & colors,
helios::Contextcontext_ptr 
)
+
+ +

Add geometry to the Context consisting of a series of Cone objects to form a tube-like shape.

+
Parameters
+ + + + + + +
[in]radial_subdivisionsNumber of subdivisions around the circumference of each cone (must be be >= 3).
[in]vertices(x,y,z) Cartesian coordinates of vertices forming the centerline of the tube.
[in]radiiRadius of the tube at each specified vertex.
[in]colorsColor of the tube at each specified vertex.
[in]context_ptrPointer to the Helios context.
+
+
+
Returns
Vector of Object IDs of the cones forming the tube.
+ +
+
+
+ + + + diff --git a/doc/html/_plant_architecture_8h_source.html b/doc/html/_plant_architecture_8h_source.html new file mode 100644 index 000000000..834f3dd00 --- /dev/null +++ b/doc/html/_plant_architecture_8h_source.html @@ -0,0 +1,1182 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
PlantArchitecture.h
+
+
+Go to the documentation of this file.
1
+
16#ifndef PLANT_ARCHITECTURE
+
17#define PLANT_ARCHITECTURE
+
18
+
19#include "Context.h"
+
20#include <random>
+
21#include <utility>
+
22
+
23//forward declarations of classes/structs
+ +
25struct Shoot;
+
26struct Phytomer;
+
27
+ +
29public:
+
30
+
32
+ +
36 constval = 0.f;
+
37 distribution = "constant";
+
38 generator = nullptr;
+
39 sampled = false;
+
40 }
+
41
+
43
+
46 explicit RandomParameter_float( float val ){
+
47 constval = val;
+
48 distribution = "constant";
+
49 generator = nullptr;
+
50 sampled = false;
+
51 }
+
52
+
54
+
57 explicit RandomParameter_float( std::minstd_rand0 *rand_generator ){
+
58 constval = 0.f;
+
59 distribution = "constant";
+
60 generator = rand_generator;
+
61 sampled = false;
+
62 }
+
63
+
64 void initialize( float a_val, std::minstd_rand0 *rand_generator){
+
65 constval = a_val;
+
66 distribution = "constant";
+
67 generator = rand_generator;
+
68 sampled = false;
+
69 }
+
70
+
71 void initialize( std::minstd_rand0 *rand_generator){
+
72 constval = 1.f;
+
73 distribution = "constant";
+
74 generator = rand_generator;
+
75 sampled = false;
+
76 }
+
77
+
78 RandomParameter_float& operator=(float a){
+
79 this->distribution = "constant";
+
80 this->constval = a;
+
81 this->sampled = false;
+
82 return *this;
+
83 }
+
84
+
85 void uniformDistribution( float minval, float maxval ){
+
86 distribution = "uniform";
+
87 distribution_parameters = {minval, maxval};
+
88 sampled = false;
+
89 }
+
90
+
91 void normalDistribution( float mean, float std_dev ){
+
92 distribution = "normal";
+
93 distribution_parameters = {mean, std_dev};
+
94 sampled = false;
+
95 }
+
96
+
97 void weibullDistribution( float shape, float scale ){
+
98 distribution = "weibull";
+
99 distribution_parameters = {shape, scale};
+
100 sampled = false;
+
101 }
+
102
+
103 float val(){
+
104 if( !sampled ){
+
105 constval = resample();
+
106 }
+
107 return constval;
+
108 }
+
109
+
110 float resample(){
+
111 sampled = true;
+
112 if( distribution!="constant" ) {
+
113 if (generator == nullptr) {
+
114 throw (std::runtime_error("ERROR (PlantArchitecture): Random parameter was not properly initialized with random number generator."));
+
115 }
+
116 if (distribution == "uniform") {
+
117 std::uniform_real_distribution<float> unif_distribution;
+
118 constval = distribution_parameters.at(0) + unif_distribution(*generator) * (distribution_parameters.at(1) - distribution_parameters.at(0));
+
119 } else if (distribution == "normal") {
+
120 std::normal_distribution<float> norm_distribution(distribution_parameters.at(0),distribution_parameters.at(1));
+
121 constval = norm_distribution(*generator);
+
122 } else if (distribution == "weibull") {
+
123 std::weibull_distribution<float> wbull_distribution(distribution_parameters.at(0),distribution_parameters.at(1));
+
124 constval = wbull_distribution(*generator);
+
125 }
+
126 }
+
127 return constval;
+
128 }
+
129
+
130 std::string distribution;
+
131 std::vector<float> distribution_parameters;
+
132
+
133private:
+
134 bool sampled;
+
135 float constval;
+
136
+
137
+
138 std::minstd_rand0 *generator;
+
139};
+
140
+ +
142public:
+
143
+
144 explicit RandomParameter_int(){
+
145 constval = 1;
+
146 distribution = "constant";
+
147 generator = nullptr;
+
148 sampled = false;
+
149 }
+
150
+
151 void initialize(int a_val, std::minstd_rand0 *rand_generator){
+
152 constval = a_val;
+
153 distribution = "constant";
+
154 generator = rand_generator;
+
155 sampled = false;
+
156 }
+
157
+
158 void initialize( std::minstd_rand0 *rand_generator){
+
159 constval = 1;
+
160 distribution = "constant";
+
161 generator = rand_generator;
+
162 sampled = false;
+
163 }
+
164
+
165 RandomParameter_int& operator=(int a){
+
166 this->distribution = "constant";
+
167 this->constval = a;
+
168 this->sampled = false;
+
169 return *this;
+
170 }
+
171
+
172 void uniformDistribution( int minval, int maxval ){
+
173 distribution = "uniform";
+
174 distribution_parameters = {minval, maxval};
+
175 sampled = false;
+
176 }
+
177
+
178 int val(){
+
179 if( !sampled ){
+
180 constval = resample();
+
181 }
+
182 return constval;
+
183 }
+
184
+
185 int resample(){
+
186 sampled = true;
+
187 if( distribution!="constant" ) {
+
188 if (generator == nullptr) {
+
189 throw (std::runtime_error("ERROR (PlantArchitecture): Random parameter was not properly initialized with random number generator."));
+
190 }
+
191 if (distribution == "uniform") {
+
192 std::uniform_int_distribution<> unif_distribution(distribution_parameters.at(0),distribution_parameters.at(1));
+
193 constval = unif_distribution(*generator);
+
194 }
+
195 }
+
196 return constval;
+
197 }
+
198
+
199private:
+
200 bool sampled;
+
201 int constval;
+
202 std::string distribution;
+
203 std::vector<int> distribution_parameters;
+
204 std::minstd_rand0 *generator;
+
205};
+
206
+ +
208public:
+
209
+
210 AxisRotation(){
+
211 pitch = 0;
+
212 yaw = 0;
+
213 roll = 0;
+
214 }
+
215
+
216 AxisRotation( float a_pitch, float a_yaw, float a_roll ){
+
217 pitch = a_pitch;
+
218 yaw = a_yaw;
+
219 roll = a_roll;
+
220 }
+
221
+
222 float pitch;
+
223 float yaw;
+
224 float roll;
+
225
+
226 AxisRotation operator+(const AxisRotation& a) const;
+
227 AxisRotation operator-(const AxisRotation& a) const;
+
228
+
229};
+
230
+
231inline AxisRotation make_AxisRotation( float a_pitch, float a_yaw, float a_roll ) {
+
232 return {a_pitch,a_yaw,a_roll};
+
233}
+
234
+
235inline AxisRotation AxisRotation::operator+(const AxisRotation& a) const{
+
236 return {a.pitch+pitch, a.yaw+yaw, a.roll+roll};
+
237}
+
238
+
239inline AxisRotation AxisRotation::operator-(const AxisRotation& a) const{
+
240 return {a.pitch-pitch, a.yaw-yaw, a.roll-roll};
+
241}
+
242
+
243enum BudState{
+
244 BUD_DORMANT = 0,
+
245 BUD_ACTIVE = 1,
+
246 BUD_FLOWER_CLOSED = 2,
+
247 BUD_FLOWER_OPEN = 3,
+
248 BUD_FRUITING = 4,
+
249 BUD_DEAD = 5
+
250};
+
251
+
253
+
261std::vector<uint> makeTubeFromCones(uint radial_subdivisions, const std::vector<helios::vec3> &vertices, const std::vector<float> &radii, const std::vector<helios::RGBcolor> &colors, helios::Context *context_ptr);
+
262
+
263//struct VegetativeBud{
+
264//
+
265// //state of the bud
+
266// const BudState &state;
+
267// //label of the shoot type that will be produced if the bud breaks into a shoot
+
268// std::string shoot_type_label;
+
269// //ID of the shoot that the bud will produce if it breaks into a shoot
+
270// uint shoot_ID = -1;
+
271//
+
272// VegetativeBud() : state(state_private) {
+
273// state_private = BUD_DORMANT;
+
274// }
+
275//
+
276//private:
+
277//
+
278// //state of the bud
+
279// BudState state_private;
+
280//
+
281// friend class Phytomer;
+
282//
+
283//};
+
284
+
285//struct FloralBud{
+
286//
+
287// //state of the bud
+
288// const BudState &state;
+
289// //amount of time since the bud flowered (=0 if it has not yet flowered)
+
290// float time_counter = 0;
+
291// //Index of the petiole within the internode that this floral bud originates from
+
292// uint parent_petiole_index = 0;
+
293// //Index of the bud within the petiole that this floral bud originates from
+
294// uint bud_index = 0;
+
295// //Scaling factor fraction of the fruit (if present), ranging from 0 to 1
+
296// float current_fruit_scale_factor = 1;
+
297//
+
298// FloralBud() : state_private(BUD_DORMANT), state(state_private) {
+
299// time_counter = 0;
+
300// parent_petiole_index = 0;
+
301// bud_index = 0;
+
302// current_fruit_scale_factor = 1;
+
303// }
+
304//
+
305//protected:
+
306//
+
307// BudState state_private;
+
308//
+
309// friend class Phytomer;
+
310//
+
311//};
+
312
+ +
314
+
315 //state of the bud
+
316 BudState state = BUD_DORMANT;
+
317 //label of the shoot type that will be produced if the bud breaks into a shoot
+
318 std::string shoot_type_label;
+
319 //ID of the shoot that the bud will produce if it breaks into a shoot
+
320 uint shoot_ID = -1;
+
321
+
322};
+
323
+ +
325
+
326 //state of the bud
+
327 BudState state = BUD_DORMANT;
+
328 //amount of time since the bud flowered (=0 if it has not yet flowered)
+
329 float time_counter = 0;
+
330 //Index of the petiole within the internode that this floral bud originates from
+
331 uint parent_petiole_index = 0;
+
332 //Index of the bud within the petiole that this floral bud originates from
+
333 uint bud_index = 0;
+
334 //Scaling factor fraction of the fruit (if present), ranging from 0 to 1
+
335 float current_fruit_scale_factor = 1;
+
336
+
337};
+
338
+ +
340private:
+
341
+
342 struct InternodeParameters{
+ +
344 RandomParameter_float phyllotactic_angle;
+
345 RandomParameter_int max_vegetative_buds_per_petiole;
+
346 RandomParameter_int max_floral_buds_per_petiole;
+
347 helios::RGBcolor color;
+
348 uint length_segments;
+
349 uint radial_subdivisions;
+
350
+
351 InternodeParameters& operator=(const InternodeParameters &a){
+
352 this->pitch = a.pitch;
+
353 this->pitch.resample();
+
354 this->phyllotactic_angle = a.phyllotactic_angle;
+
355 this->phyllotactic_angle.resample();
+
356 this->max_vegetative_buds_per_petiole = a.max_vegetative_buds_per_petiole;
+
357 this->max_vegetative_buds_per_petiole.resample();
+
358 this->max_floral_buds_per_petiole = a.max_floral_buds_per_petiole;
+
359 this->max_floral_buds_per_petiole.resample();
+
360 this->color = a.color;
+
361 this->length_segments = a.length_segments;
+
362 this->radial_subdivisions = a.radial_subdivisions;
+
363 return *this;
+
364 }
+
365 };
+
366
+
367 struct PetioleParameters{
+
368 uint petioles_per_internode;
+ + + +
372 RandomParameter_float curvature;
+ +
374 helios::RGBcolor color;
+
375 uint length_segments;
+
376 uint radial_subdivisions;
+
377
+
378 PetioleParameters& operator=(const PetioleParameters &a){
+
379 this->petioles_per_internode = a.petioles_per_internode;
+
380 this->pitch = a.pitch;
+
381 this->pitch.resample();
+
382 this->radius = a.radius;
+
383 this->radius.resample();
+
384 this->length = a.length;
+
385 this->length.resample();
+
386 this->curvature = a.curvature;
+
387 this->curvature.resample();
+
388 this->taper = a.taper;
+
389 this->taper.resample();
+
390 this->color = a.color;
+
391 this->length_segments = a.length_segments;
+
392 this->radial_subdivisions = a.radial_subdivisions;
+
393 return *this;
+
394 }
+
395 };
+
396
+
397 struct LeafParameters{
+
398 uint leaves_per_petiole;
+ + + +
402 RandomParameter_float leaflet_offset;
+
403 RandomParameter_float leaflet_scale;
+
404 RandomParameter_float prototype_scale;
+
405 uint subdivisions;
+
406 uint(*prototype_function)( helios::Context*, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ) = nullptr;
+
407
+
408 LeafParameters& operator=(const LeafParameters &a){
+
409 this->leaves_per_petiole = a.leaves_per_petiole;
+
410 this->pitch = a.pitch;
+
411 this->pitch.resample();
+
412 this->yaw = a.yaw;
+
413 this->yaw.resample();
+
414 this->roll = a.roll;
+
415 this->roll.resample();
+
416 this->leaflet_offset = a.leaflet_offset;
+
417 this->leaflet_offset.resample();
+
418 this->leaflet_scale = a.leaflet_scale;
+
419 this->leaflet_scale.resample();
+
420 this->prototype_scale = a.prototype_scale;
+
421 this->prototype_scale.resample();
+
422 this->subdivisions = a.subdivisions;
+
423 this->prototype_function = a.prototype_function;
+
424 return *this;
+
425 }
+
426 };
+
427
+
428 struct PeduncleParameters {
+ + + + +
433 RandomParameter_float curvature;
+
434 uint length_segments;
+
435 uint radial_subdivisions;
+
436
+
437 PeduncleParameters &operator=(const PeduncleParameters &a) {
+
438 this->length = a.length;
+
439 this->length.resample();
+
440 this->radius = a.radius;
+
441 this->radius.resample();
+
442 this->pitch = a.pitch;
+
443 this->pitch.resample();
+
444 this->roll = a.roll;
+
445 this->roll.resample();
+
446 this->curvature = a.curvature;
+
447 this->curvature.resample();
+
448 this->length_segments = a.length_segments;
+
449 this->radial_subdivisions = a.radial_subdivisions;
+
450 return *this;
+
451 }
+
452 };
+
453
+
454 struct InflorescenceParameters {
+
455 RandomParameter_int flowers_per_rachis;
+
456 RandomParameter_float flower_offset;
+
457 std::string flower_arrangement_pattern;
+ + +
460 RandomParameter_float flower_prototype_scale;
+
461 uint (*flower_prototype_function)(helios::Context *, uint subdivisions, bool flower_is_open) = nullptr;
+
462 RandomParameter_float fruit_prototype_scale;
+
463 uint (*fruit_prototype_function)(helios::Context *, uint subdivisions, float time_since_fruit_set) = nullptr;
+
464 RandomParameter_float fruit_gravity_factor_fraction;
+
465
+
466 InflorescenceParameters &operator=(const InflorescenceParameters &a) {
+
467 this->flowers_per_rachis = a.flowers_per_rachis;
+
468 this->flowers_per_rachis.resample();
+
469 this->flower_offset = a.flower_offset;
+
470 this->flower_offset.resample();
+
471 this->flower_arrangement_pattern = a.flower_arrangement_pattern;
+
472 this->pitch = a.pitch;
+
473 this->pitch.resample();
+
474 this->roll = a.roll;
+
475 this->roll.resample();
+
476 this->flower_prototype_scale = a.flower_prototype_scale;
+
477 this->flower_prototype_scale.resample();
+
478 this->flower_prototype_function = a.flower_prototype_function;
+
479 this->fruit_prototype_scale = a.fruit_prototype_scale;
+
480 this->fruit_prototype_scale.resample();
+
481 this->fruit_prototype_function = a.fruit_prototype_function;
+
482 this->fruit_gravity_factor_fraction = a.fruit_gravity_factor_fraction;
+
483 this->fruit_gravity_factor_fraction.resample();
+
484 return *this;
+
485 }
+
486 };
+
487
+
488public:
+
489
+
490 InternodeParameters internode;
+
491
+
492 PetioleParameters petiole;
+
493
+
494 LeafParameters leaf;
+
495
+
496 PeduncleParameters peduncle;
+
497
+
498 InflorescenceParameters inflorescence;
+
499
+
500 //Custom user-defined function that is called when a phytomer is created
+
508 void (*phytomer_creation_function)(std::shared_ptr<Phytomer> phytomer_ptr, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age) = nullptr;
+
509
+ +
512
+
514 explicit PhytomerParameters( std::minstd_rand0 *generator );
+
515
+
516 friend class PlantArchitecture;
+
517 friend class Phytomer;
+
518 friend class Shoot;
+
519
+
520};
+
521
+ +
523
+ +
526
+
528 explicit ShootParameters( std::minstd_rand0 *generator );
+
529
+
530 PhytomerParameters phytomer_parameters;
+
531
+
532 // ---- Geometric Parameters ---- //
+
533
+
534 RandomParameter_int max_nodes;
+
535
+
536 RandomParameter_float internode_radius_initial;
+
537
+
538 RandomParameter_float child_insertion_angle_tip;
+
539 RandomParameter_float child_insertion_angle_decay_rate;
+
540
+
541 RandomParameter_float child_internode_length_max;
+
542 RandomParameter_float child_internode_length_min;
+
543 RandomParameter_float child_internode_length_decay_rate;
+
544
+
545 RandomParameter_float base_roll;
+
546 RandomParameter_float base_yaw;
+
547
+
548 RandomParameter_float gravitropic_curvature; //degrees/length
+
549
+
550 RandomParameter_float tortuosity; //degrees/length (standard deviation of random curvature perturbation)
+
551
+
552 // ---- Growth Parameters ---- //
+
553
+
554 RandomParameter_float phyllochron; //phytomers/day
+
555 uint leaf_flush_count; //number of leaves in a 'flush' (=1 gives continuous leaf production)
+
556
+
557 RandomParameter_float elongation_rate; //length/day
+
558
+
559 RandomParameter_float girth_growth_rate; //1/day
+
560 RandomParameter_float internode_radius_max; //meters
+
561
+
562 // Probability that bud with this shoot type will break and form a new shoot
+
563 RandomParameter_float vegetative_bud_break_probability;
+
564
+
565 // Probability that a phytomer will flower
+
566 RandomParameter_float flower_bud_break_probability;
+
567
+
568 // Probability that a flower will set fruit
+
569 RandomParameter_float fruit_set_probability;
+
570
+
571 RandomParameter_float vegetative_bud_break_time; //days
+
572
+
573 bool flowers_require_dormancy;
+
574 bool growth_requires_dormancy;
+
575
+
576 bool determinate_shoot_growth; //true=determinate, false=indeterminate
+
577
+
578 // ---- Custom Functions ---- //
+
579
+
580 void defineChildShootTypes( const std::vector<std::string> &child_shoot_type_labels, const std::vector<float> &child_shoot_type_probabilities );
+
581
+
582 ShootParameters& operator=(const ShootParameters &a) {
+
583 this->phytomer_parameters = a.phytomer_parameters;
+
584 this->max_nodes = a.max_nodes;
+
585 max_nodes.resample();
+
586 this->internode_radius_initial = a.internode_radius_initial;
+
587 this->internode_radius_initial.resample();
+
588 this->phyllochron = a.phyllochron;
+
589 this->phyllochron.resample();
+
590 this->leaf_flush_count = a.leaf_flush_count;
+
591 this->elongation_rate = a.elongation_rate;
+
592 this->elongation_rate.resample();
+
593 this->girth_growth_rate = a.girth_growth_rate;
+
594 this->girth_growth_rate.resample();
+
595 this->internode_radius_max = a.internode_radius_max;
+
596 this->internode_radius_max.resample();
+
597 this->vegetative_bud_break_probability = a.vegetative_bud_break_probability;
+
598 this->vegetative_bud_break_probability.resample();
+
599 this->flower_bud_break_probability = a.flower_bud_break_probability;
+
600 this->flower_bud_break_probability.resample();
+
601 this->fruit_set_probability = a.fruit_set_probability;
+
602 this->fruit_set_probability.resample();
+
603 this->gravitropic_curvature = a.gravitropic_curvature;
+
604 this->gravitropic_curvature.resample();
+
605 this->tortuosity = a.tortuosity;
+
606 this->tortuosity.resample();
+
607 this->vegetative_bud_break_probability = a.vegetative_bud_break_probability;
+
608 this->flower_bud_break_probability = a.flower_bud_break_probability;
+
609 this->fruit_set_probability = a.fruit_set_probability;
+
610 this->vegetative_bud_break_time = a.vegetative_bud_break_time;
+
611 this->vegetative_bud_break_time.resample();
+
612 this->child_insertion_angle_tip = a.child_insertion_angle_tip;
+
613 this->child_insertion_angle_tip.resample();
+
614 this->child_insertion_angle_decay_rate = a.child_insertion_angle_decay_rate;
+
615 this->child_insertion_angle_decay_rate.resample();
+
616 this->child_internode_length_max = a.child_internode_length_max;
+
617 this->child_internode_length_max.resample();
+
618 this->child_internode_length_min = a.child_internode_length_min;
+
619 this->child_internode_length_min.resample();
+
620 this->child_internode_length_decay_rate = a.child_internode_length_decay_rate;
+
621 this->child_internode_length_decay_rate.resample();
+
622 this->base_roll = a.base_roll;
+
623 this->base_roll.resample();
+
624 this->base_yaw = a.base_yaw;
+
625 this->base_yaw.resample();
+
626 this->flowers_require_dormancy = a.flowers_require_dormancy;
+
627 this->growth_requires_dormancy = a.growth_requires_dormancy;
+
628 this->child_shoot_type_labels = a.child_shoot_type_labels;
+
629 this->child_shoot_type_probabilities = a.child_shoot_type_probabilities;
+
630 this->determinate_shoot_growth = a.determinate_shoot_growth;
+
631 return *this;
+
632 }
+
633
+
634 friend class PlantArchitecture;
+
635 friend class Shoot;
+
636
+
637protected:
+
638
+
639 std::vector<std::string> child_shoot_type_labels;
+
640 std::vector<float> child_shoot_type_probabilities;
+
641
+
642};
+
643
+
644struct Phytomer {
+
645public:
+
646
+
647 // Constructor
+
648 Phytomer(const PhytomerParameters &params, Shoot *parent_shoot, uint phytomer_index, const helios::vec3 &parent_internode_axis, const helios::vec3 &parent_petiole_axis, helios::vec3 internode_base_origin, const AxisRotation &shoot_base_rotation,
+
649 float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, uint rank, bool build_context_geometry_internode, bool build_context_geometry_petiole,
+
650 bool build_context_geometry_peduncle, helios::Context *context_ptr);
+
651
+
652 // ---- query info about the phytomer ---- //
+
653
+
654 helios::vec3 getInternodeAxisVector( float stem_fraction ) const;
+
655
+
656 helios::vec3 getPetioleAxisVector(float stem_fraction, uint petiole_index) const;
+
657
+
658 helios::vec3 getAxisVector( float stem_fraction, const std::vector<helios::vec3> &axis_vertices ) const;
+
659
+
660 float getInternodeLength() const;
+
661
+
662 float getPetioleLength() const;
+
663
+
664 float getInternodeRadius( float stem_fraction ) const;
+
665
+
666 bool hasLeaf() const;
+
667
+
668 bool hasInflorescence() const;
+
669
+
670 // ---- modify the phytomer ---- //
+
671
+
672 void addInflorescence(const helios::vec3 &base_position, const AxisRotation &base_rotation, const helios::vec3 &a_inflorescence_bending_axis, FloralBud &fbud);
+
673
+
674 void setInternodeLengthScaleFraction(float internode_scale_factor_fraction );
+
675
+
676 void setInternodeMaxLength( float internode_length_max );
+
677
+
678 void scaleInternodeMaxLength( float scale_factor );
+
679
+
680 void setInternodeMaxRadius( float internode_radius_max );
+
681
+
682 void setLeafScaleFraction(float leaf_scale_factor_fraction );
+
683
+
684 void setLeafPrototypeScale( float leaf_prototype_scale );
+
685
+
686 void scaleLeafPrototypeScale( float scale_factor );
+
687
+
688 void setInflorescenceScaleFraction(FloralBud &fbud, float inflorescence_scale_factor_fraction);
+
689
+
690 void setPetioleBase( const helios::vec3 &base_position );
+
691
+
692 void setPhytomerBase( const helios::vec3 &base_position );
+
693
+
694 void setVegetativeBudState( BudState state );
+
695
+
696 void setVegetativeBudState(BudState state, uint petiole_index, uint bud_index);
+
697
+
698 void setVegetativeBudState( BudState state, VegetativeBud &vbud );
+
699
+
700 void setFloralBudState( BudState state );
+
701
+
702 void setFloralBudState(BudState state, uint petiole_index, uint bud_index);
+
703
+
704 void setFloralBudState(BudState state, FloralBud &fbud);
+
705
+
706 void removeLeaf();
+
707
+
708 // ---- phytomer data ---- //
+
709
+
710 std::vector<helios::vec3> internode_vertices; //index is tube segment within internode
+
711 std::vector<std::vector<helios::vec3>> petiole_vertices; //first index is petiole within internode, second index is tube segment within petiole
+
712 std::vector<std::vector<helios::vec3>> leaf_bases; //first index is petiole within internode, second index is leaf within petiole
+
713 std::vector<std::vector<std::vector<helios::vec3>>> inflorescence_bases; //first index is the petiole within internode, second index is the floral bud, third index is flower/fruit within peduncle/rachis
+
714 float internode_length;
+
715
+
716 std::vector<float> internode_radii; //index is segment within internode
+
717 std::vector<std::vector<float>> petiole_radii; //first index is petiole within internode, second index is segment within petiole
+
718 std::vector<float> petiole_length; //index is petiole within internode
+
719
+
720 std::vector<helios::RGBcolor> internode_colors;
+
721 std::vector<helios::RGBcolor> petiole_colors;
+
722
+
723 std::vector<uint> internode_objIDs; //index is segment within internode
+
724 std::vector<std::vector<uint> > petiole_objIDs; //first index is petiole within internode, second index is segment within petiole
+
725 std::vector<std::vector<uint>> leaf_objIDs; //first index is petiole within internode, second index is leaf within petiole
+
726 std::vector<std::vector<std::vector<uint>>> inflorescence_objIDs; //first index is the petiole within internode, second index is the floral bud, third index is flower/fruit within peduncle/rachis
+
727 std::vector<std::vector<std::vector<uint>>> peduncle_objIDs; //first index is the petiole within internode, second index is the floral bud, third index is flower/fruit within peduncle/rachis
+
728
+
729 PhytomerParameters phytomer_parameters;
+
730
+
731 uint rank;
+
732 helios::int2 shoot_index; // .x = index of phytomer along shoot, .y = maximum number of phytomers on parent shoot
+
733
+
734 float age = 0;
+
735 float time_since_dormancy = 0;
+
736
+
737 float current_internode_scale_factor = 1;
+
738 float current_leaf_scale_factor = 1;
+
739
+
740 std::vector<std::vector<VegetativeBud>> vegetative_buds; //first index is petiole within internode, second index is bud within petiole
+
741 std::vector<std::vector<FloralBud>> floral_buds; //first index is petiole within internode, second index is bud within petiole
+
742
+
743 float internode_radius_initial;
+
744 float internode_radius_max;
+
745 float internode_length_max;
+
746
+
747 bool build_context_geometry_internode = true;
+
748 bool build_context_geometry_petiole = true;
+
749 bool build_context_geometry_peduncle = true;
+
750
+
751protected:
+
752
+
753 helios::vec3 inflorescence_bending_axis;
+
754
+
755 helios::Context *context_ptr;
+
756
+
757};
+
758
+
759struct Shoot{
+
760
+
761 Shoot(uint plant_ID, int shoot_ID, int parent_shoot_ID, uint parent_node, uint parent_petiole_index, uint rank, const helios::vec3 &origin, const AxisRotation &shoot_base_rotation, uint current_node_number,
+
762 float internode_length_shoot_initial, ShootParameters shoot_params, const std::string &shoot_type_label, PlantArchitecture *plant_architecture_ptr);
+
763
+
764 void buildShootPhytomers(float internode_radius, float internode_length, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction);
+
765
+
766 int addPhytomer(const PhytomerParameters &params, const helios::vec3 internode_base_position, const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction,
+
767 float leaf_scale_factor_fraction);
+
768
+
770
+
774 bool sampleChildShootType(std::string &child_shoot_type_label) const;
+
775
+
776 void terminateApicalBud();
+
777
+
778 void terminateAxillaryVegetativeBuds();
+
779
+
780 uint current_node_number;
+
781
+
782 helios::vec3 origin;
+
783
+
784 AxisRotation base_rotation;
+
785
+
786 const int ID;
+
787 const int parent_shoot_ID;
+
788 const uint plantID;
+
789 const uint parent_node_index;
+
790 const uint rank;
+
791 const uint parent_petiole_index;
+
792
+
793 float assimilate_pool; // mg SC/g DW
+
794
+
795 void breakDormancy();
+
796 void makeDormant();
+
797
+
798 bool dormant;
+
799 uint dormancy_cycles = 0;
+
800
+
801 bool meristem_is_alive = true;
+
802
+
803 float phyllochron_counter = 0;
+
804
+
805 float curvature_perturbation = 0;
+
806
+
807 const float internode_length_max_shoot_initial;
+
808
+
809 //map of node number to ID of shoot child
+
810 std::map<int,int> childIDs;
+
811
+
812 ShootParameters shoot_parameters;
+
813
+
814 std::string shoot_type_label;
+
815
+
816 std::vector<std::shared_ptr<Phytomer> > phytomers;
+
817
+
818 PlantArchitecture* plant_architecture_ptr;
+
819
+
820 helios::Context *context_ptr;
+
821
+
822};
+
823
+ +
825
+
826 PlantInstance(const helios::vec3 &a_base_position, float a_current_age) : base_position(a_base_position), current_age(a_current_age) {}
+
827 std::vector<std::shared_ptr<Shoot> > shoot_tree;
+
828 helios::vec3 base_position;
+
829 float current_age;
+
830
+
831 //Phenological thresholds
+
832 float dd_to_dormancy_break = 0;
+
833 float dd_to_flower_initiation = 0;
+
834 float dd_to_flower_opening = 0;
+
835 float dd_to_fruit_set = 0;
+
836 float dd_to_fruit_maturity = 0;
+
837 float dd_to_senescence = 0;
+
838
+
839};
+
840
+ +
842public:
+
843
+
845
+
848 explicit PlantArchitecture( helios::Context* context_ptr );
+
849
+
850 // ********* Methods for Building Plants from Existing Library ********* //
+
851
+
853
+
856 void loadPlantModelFromLibrary( const std::string &plant_label );
+
857
+
859
+
864 uint buildPlantInstanceFromLibrary( const helios::vec3 &base_position, float age );
+
865
+
867
+
871 ShootParameters getCurrentShootParameters( const std::string &shoot_type_label );
+
872
+
874
+
877 std::map<std::string, ShootParameters> getCurrentShootParameters( );
+
878
+
880
+
885 void updateCurrentShootParameters( const std::string &shoot_type_label, const ShootParameters &params );
+
886
+
888
+
893 void updateCurrentShootParameters( const std::map<std::string, ShootParameters> &params );
+
894
+
895 // ********* Methods for Building Custom Plant Geometry from Scratch ********* //
+
896
+
898
+
903 uint addPlantInstance(const helios::vec3 &base_position, float current_age);
+
904
+
906
+
912 uint duplicatePlantInstance(uint plantID, const helios::vec3 &base_position, const AxisRotation &base_rotation, float current_age);
+
913
+
915
+
925 void setPlantPhenologicalThresholds(uint plantID, float time_to_dormancy_break, float time_to_flower_initiation, float time_to_flower_opening, float time_to_fruit_set, float time_to_fruit_maturity, float time_to_senescence);
+
926
+
928
+
931 void advanceTime( float dt );
+
932
+
933 void incrementAssimilatePool( uint plantID, uint shootID, float assimilate_increment_mg_g );
+
934
+
935 void incrementAssimilatePool( uint plantID, float assimilate_increment_mg_g );
+
936
+
937 // -- plant building methods -- //
+
938
+
940
+
944 void defineShootType( const std::string &shoot_type_label, const ShootParameters &shoot_params );
+
945
+
947
+
958 uint addBaseStemShoot(uint plantID, uint current_node_number, const AxisRotation &base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction,
+
959 const std::string &shoot_type_label);
+
960
+
962
+
974 uint appendShoot(uint plantID, int parent_shoot_ID, uint current_node_number, const AxisRotation &base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction,
+
975 float leaf_scale_factor_fraction, const std::string &shoot_type_label);
+
976
+
978
+
992 uint addChildShoot(uint plantID, int parent_shoot_ID, uint parent_node_index, uint current_node_number, const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max,
+
993 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label, uint petiole_index = 0 );
+
994
+
996
+
1006 int addPhytomerToShoot(uint plantID, uint shootID, const PhytomerParameters &phytomer_parameters, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction);
+
1007
+ +
1010
+ +
1013
+ +
1016
+
1018
+
1021 void enableGroundClipping( float ground_height = 0.f );
+
1022
+
1023 // -- methods for modifying the current plant state -- //
+
1024
+
1025 void incrementPhytomerInternodeGirth(uint plantID, uint shootID, uint node_number, float girth_change);
+
1026
+
1027 void setPhytomerInternodeLengthScaleFraction(uint plantID, uint shootID, uint node_number, float internode_scale_factor_fraction);
+
1028
+
1029 void setPhytomerLeafScale(uint plantID, uint shootID, uint node_number, float leaf_scale_factor_fraction);
+
1030
+
1031 void setShootOrigin(uint plantID, uint shootID, const helios::vec3 &origin);
+
1032
+
1033 void setPlantBasePosition(uint plantID, const helios::vec3 &base_position);
+
1034
+
1035 void setPlantAge(uint plantID, float current_age);
+
1036
+
1037 void harvestPlant(uint plantID);
+
1038
+
1039 void removeShootLeaves(uint plantID, uint shootID);
+
1040
+
1041 void removePlantLeaves(uint plantID );
+
1042
+
1043 void makePlantDormant( uint plantID );
+
1044
+
1045 void breakPlantDormancy( uint plantID );
+
1046
+
1047 // -- methods for querying information about the plant -- //
+
1048
+
1049 float getPlantAge(uint plantID) const;
+
1050
+
1051 uint getShootNodeCount( uint plantID, uint shootID ) const;
+
1052
+
1053 helios::vec3 getPlantBasePosition(uint plantID) const;
+
1054
+
1056
+
1060 std::vector<uint> getAllPlantObjectIDs(uint plantID) const;
+
1061
+
1063
+
1067 std::vector<uint> getAllPlantUUIDs(uint plantID) const;
+
1068
+
1070
+
1074 std::vector<uint> getPlantInternodeObjectIDs(uint plantID) const;
+
1075
+
1077
+
1081 std::vector<uint> getPlantPetioleObjectIDs(uint plantID) const;
+
1082
+
1084
+
1088 std::vector<uint> getPlantLeafObjectIDs(uint plantID) const;
+
1089
+
1091
+
1095 std::vector<uint> getPlantPeduncleObjectIDs(uint plantID) const;
+
1096
+
1098
+
1102 std::vector<uint> getPlantFlowerObjectIDs(uint plantID) const;
+
1103
+
1105
+
1109 std::vector<uint> getPlantFruitObjectIDs(uint plantID) const;
+
1110
+
1111 std::string getPlantString(uint plantID) const;
+
1112
+
1113 // -- manual plant generation from input string -- //
+
1114
+
1115 uint generatePlantFromString(const std::string &generation_string, const PhytomerParameters &phytomer_parameters);
+
1116
+
1117 uint generatePlantFromString(const std::string &generation_string, const std::map<std::string,PhytomerParameters> &phytomer_parameters);
+
1118
+
1119 friend class Shoot;
+
1120
+
1121protected:
+
1122
+
1123 helios::Context* context_ptr;
+
1124
+
1125 std::minstd_rand0 *generator = nullptr;
+
1126
+
1127 uint plant_count = 0;
+
1128
+
1129 std::string current_plant_model;
+
1130
+
1131 std::map<uint,PlantInstance> plant_instances;
+
1132
+
1133 std::string makeShootString(const std::string &current_string, const std::shared_ptr<Shoot> &shoot, const std::vector<std::shared_ptr<Shoot>> & shoot_tree) const;
+
1134
+
1135 std::map<std::string,ShootParameters> shoot_types;
+
1136
+
1137 bool build_context_geometry_internode = true;
+
1138 bool build_context_geometry_petiole = true;
+
1139 bool build_context_geometry_peduncle = true;
+
1140
+
1141 float ground_clipping_height = -99999;
+
1142
+
1143 void validateShootTypes( ShootParameters &shoot_parameters ) const;
+
1144
+
1145 void accumulateShootPhotosynthesis( float dt );
+
1146
+
1147 void parseStringShoot(const std::string &LString_shoot, uint plantID, int parentID, uint parent_node, const std::map<std::string, PhytomerParameters> &phytomer_parameters, ShootParameters &shoot_parameters);
+
1148
+
1149 void parseShootArgument(const std::string &shoot_argument, const std::map<std::string, PhytomerParameters> &phytomer_parameters, ShootParameters &shoot_parameters, AxisRotation &base_rotation, std::string &phytomer_label);
+
1150
+
1151 void parseInternodeArgument(const std::string &internode_argument, float &internode_radius, float &internode_length, PhytomerParameters &phytomer_parameters);
+
1152
+
1153 void parsePetioleArgument(const std::string& petiole_argument, PhytomerParameters &phytomer_parameters );
+
1154
+
1155 void parseLeafArgument(const std::string& leaf_argument, PhytomerParameters &phytomer_parameters );
+
1156
+
1157 void shiftDownstreamShoots(uint plantID, std::vector<std::shared_ptr<Shoot>> &shoot_tree, std::shared_ptr<Shoot> parent_shoot_ptr, const helios::vec3 &base_position );
+
1158
+
1159 void initializeDefaultShoots( const std::string &plant_label );
+
1160
+
1161 bool detectGroundCollision(uint objID);
+
1162
+
1163 bool detectGroundCollision(const std::vector<uint> &objID);
+
1164
+
1165 // --- Plant Libary --- //
+
1166
+
1167 void initializeAlmondTreeShoots();
+
1168
+
1169 uint buildAlmondTree( const helios::vec3 &base_position, float age );
+
1170
+
1171 void initializeBindweedShoots();
+
1172
+
1173 uint buildBindweedPlant( const helios::vec3 &base_position, float age );
+
1174
+
1175 void initializeBeanShoots();
+
1176
+
1177 uint buildBeanPlant( const helios::vec3 &base_position, float age );
+
1178
+
1179 void initializeCheeseweedShoots();
+
1180
+
1181 uint buildCheeseweedPlant( const helios::vec3 &base_position, float age );
+
1182
+
1183 void initializeCowpeaShoots();
+
1184
+
1185 uint buildCowpeaPlant( const helios::vec3 &base_position, float age );
+
1186
+
1187 void initializePuncturevineShoots();
+
1188
+
1189 uint buildPuncturevinePlant( const helios::vec3 &base_position, float age );
+
1190
+
1191 void initializeRedbudShoots();
+
1192
+
1193 uint buildRedbudPlant( const helios::vec3 &base_position, float age );
+
1194
+
1195 void initializeSoybeanShoots();
+
1196
+
1197 uint buildSoybeanPlant( const helios::vec3 &base_position, float age );
+
1198
+
1199 void initializeSorghumShoots();
+
1200
+
1201 uint buildSorghumPlant( const helios::vec3 &base_position, float age );
+
1202
+
1203 void initializeStrawberryShoots();
+
1204
+
1205 uint buildStrawberryPlant( const helios::vec3 &base_position, float age );
+
1206
+
1207 void initializeSugarbeetShoots();
+
1208
+
1209 uint buildSugarbeetPlant( const helios::vec3 &base_position, float age );
+
1210
+
1211 void initializeTomatoShoots();
+
1212
+
1213 uint buildTomatoPlant( const helios::vec3 &base_position, float age );
+
1214
+
1215};
+
1216
+
1217
+
1218#endif //PLANT_ARCHITECTURE
+ +
std::vector< uint > makeTubeFromCones(uint radial_subdivisions, const std::vector< helios::vec3 > &vertices, const std::vector< float > &radii, const std::vector< helios::RGBcolor > &colors, helios::Context *context_ptr)
Add geometry to the Context consisting of a series of Cone objects to form a tube-like shape.
+ +
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
+
std::map< std::string, ShootParameters > getCurrentShootParameters()
Get the shoot parameters structure for all shoot types in the current plant model.
+
std::vector< uint > getPlantFlowerObjectIDs(uint plantID) const
Get object IDs for all inflorescence objects for a given plant.
+
void updateCurrentShootParameters(const std::string &shoot_type_label, const ShootParameters &params)
Update the parameters of a single shoot type in the current plant model.
+
void enableGroundClipping(float ground_height=0.f)
Enable automatic removal of organs that are below the ground plane.
+
std::vector< uint > getAllPlantUUIDs(uint plantID) const
Get primitive UUIDs for all primitives in a given plant.
+
void setPlantPhenologicalThresholds(uint plantID, float time_to_dormancy_break, float time_to_flower_initiation, float time_to_flower_opening, float time_to_fruit_set, float time_to_fruit_maturity, float time_to_senescence)
Specify the threshold values for plant phenological stages.
+
std::vector< uint > getPlantInternodeObjectIDs(uint plantID) const
Get object IDs for all internode (Tube) objects for a given plant.
+
int addPhytomerToShoot(uint plantID, uint shootID, const PhytomerParameters &phytomer_parameters, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction)
Add a new phytomer at the terminal bud of a shoot.
+
void disablePeduncleContextBuild()
Do not build peduncle primitive geometry in the Context.
+
void defineShootType(const std::string &shoot_type_label, const ShootParameters &shoot_params)
Define a new shoot type based on a set of ShootParameters.
+
uint addBaseStemShoot(uint plantID, uint current_node_number, const AxisRotation &base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label)
Define the stem/trunk shoot (base of plant) to start a new plant. This requires a plant instance has ...
+
std::vector< uint > getPlantFruitObjectIDs(uint plantID) const
Get object IDs for all fruit objects for a given plant.
+
void disablePetioleContextBuild()
Do not build petiole primitive geometry in the Context.
+
uint buildPlantInstanceFromLibrary(const helios::vec3 &base_position, float age)
Build a plant instance based on the model currently loaded from the library.
+
uint addChildShoot(uint plantID, int parent_shoot_ID, uint parent_node_index, uint current_node_number, const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label, uint petiole_index=0)
Manually add a child shoot at the axillary bud of a phytomer.
+
uint duplicatePlantInstance(uint plantID, const helios::vec3 &base_position, const AxisRotation &base_rotation, float current_age)
Duplicate an existing plant instance and specify its base position and age.
+
uint appendShoot(uint plantID, int parent_shoot_ID, uint current_node_number, const AxisRotation &base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label)
Manually append a new shoot at the end of an existing shoot. This is used when the characteristics of...
+
std::vector< uint > getAllPlantObjectIDs(uint plantID) const
Get object IDs for all organs objects for a given plant.
+
void loadPlantModelFromLibrary(const std::string &plant_label)
Load an existing plant model from the library.
+
std::vector< uint > getPlantPetioleObjectIDs(uint plantID) const
Get object IDs for all petiole (Tube) objects for a given plant.
+
void disableInternodeContextBuild()
Do not build internode primitive geometry in the Context.
+
std::vector< uint > getPlantPeduncleObjectIDs(uint plantID) const
Get object IDs for all peduncle (Tube) objects for a given plant.
+
void advanceTime(float dt)
Advance plant growth by a specified time interval.
+
std::vector< uint > getPlantLeafObjectIDs(uint plantID) const
Get object IDs for all leaf objects for a given plant.
+
Stores the state associated with simulation.
Definition: Context.h:1705
+
float mean(const std::vector< float > &vect)
Mean value of a vector of floats.
Definition: global.cpp:889
+ + + + +
PhytomerParameters()
Default constructor - does not set random number generator.
+
void(* phytomer_creation_function)(std::shared_ptr< Phytomer > phytomer_ptr, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age)
+ + +
RandomParameter_float()
Constructor initializing to a constant default value of 0.
+
RandomParameter_float(std::minstd_rand0 *rand_generator)
Constructor initializing the random number generator.
+
RandomParameter_float(float val)
Constructor initializing to a constant value.
+ + +
bool sampleChildShootType(std::string &child_shoot_type_label) const
Randomly sample the type of a child shoot based on the probabilities defined in the shoot parameters.
+ +
ShootParameters()
Default constructor - does not set random number generator.
+ +
R-G-B color vector.
+
Vector of two elements of type 'int'.
+
Vector of three elements of type 'float'.
+
+ + + + diff --git a/doc/html/_plant_architecture_doc.html b/doc/html/_plant_architecture_doc.html new file mode 100644 index 000000000..c47946897 --- /dev/null +++ b/doc/html/_plant_architecture_doc.html @@ -0,0 +1,639 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
+
Plant Architecture Model Plugin Documentation
+
+
+ +

Known Issues

+
    +
  • Growing the plant over time is pretty slow. Nothing has been done yet to optimize efficiency. It may be helpful to lower the subdivision count on leaves and stems/branches.
  • +
+ + + + + + + + + +
DependenciesNone
CMakeLists.txtset( PLUGINS "plantarchitecture" )
Header File#include "PlantArchitecture.h"
ClassPlantArchitecture
+

+Class Constructor

+ + + + + +
Constructors
PlantArchitecture( helios::Context* )
+

+Primitive Data

+

+Default Output Primitive Data

+ + + + + + + + + + + + + + + +
Primitive Data LabelData TypeDescription
plantID intUnique identifier of plant the primitive belongs to (used for image labeling).
leafID intUnique identifier of leaf the primitive belongs to (used for image labeling).
peduncleID intUnique identifier of peduncle the primitive belongs to (used for image labeling). Not defined if there are no peduncles.
closedflowerID intUnique identifier of flower (closed) the primitive belongs to (used for image labeling). Not defined if there are no closed flowers.
openflowerID intUnique identifier of flower (open) the primitive belongs to (used for image labeling). Not defined if there are no open flowers.
fruitID intUnique identifier of fruit the primitive belongs to (used for image labeling). Not defined if there are no fruits.
+

+Default Output Object Data

+ + + + + + + +
Object Data LabelData TypeDescription
rank intRank of shoot object belongs to.
age floatAge of the organ that the object belongs to (e.g., a leaf).
+

+Introduction

+

+The Phytomer: Basic Unit of a plant shoot

+

The phytomer is the basic unit of a shoot, and consists of an internode, one or more petioles, leaves, and inflorescence if present. The internode consists of a tube whose base is connected either to a parent shoot if it is the first phytomer along a shoot, or to the end of another phytomer along the same shoot.

+

A phytomer can have one or more petioles, which are connected at the end of the internode. Each petiole has one or more leaves.

+

At the tip of a growing shoot (i.e., end of the last phytomer on the shoot), there is an apical vegetative bud that can spawn a new phytomer along the same shoot. This is how shoot growth occurs. During a dormant period, one or more apical floral buds can also be created.

+

At the base of the petiole, there may be one or more vegetative buds that can develop into a new shoot, and one or more floral buds that can develop into a fruit. The vegetative and floral buds can break into a new shoot/flower in the same growing season, or may need a winter dormancy period before breaking. It is also possible that a bud never breaks and dies. Once a bud breaks it is considered dead.

+
+ +
+Schematic depiction of a phytomer within a shoot.
+

+Coordinate System

+

The coordinate system of plant organs is defined with respect to it's parent element (i.e., element it originated from), with it's default orientation being aligned with it's parent's axis. It can then be rotated based on angles of 'pitch', 'yaw', and 'roll' (in that order):

+

Pitch: rotation angle formed between the axis of the element and it's parent's axis.

+

Yaw: rotation angle about the parent's axis (except in the case of a leaf, where it is about an axis perpendicular to the leaf midrib).

+

Roll: rotation angle about the element's own axis

+
+ +
+

+Randomization of Parameters

+

Nearly all parameters in the architectural model can either be specified as a constant value, or as a random variable following several pre-defined distributions.

+

Parameters that can be randomized have type of RandomParameter_float or RandomParameter_int depending on the parameter value type. If the parameters are assigned a constant value, they are set the same as a regular float or int. The val() method is used to get the value of the parameter.

+
// Assign a constant value
+ +
param = 5;
+
// Alternative approach
+
RandomParameter_float other_param(5);
+ +

In order to randomize the variable, member methods can be called to set the distribution type and specify the distribution parameters. It is also required to initialize the variable with a random number generator. It is recommended that this be based on the Context's generator to keep everything consistent. Below is an example.

+
Context context;
+
+
RandomParameter_float param(context.getRandomGenerator());
+
param.uniformDistribution(0,7.5);
+
std::cout << "Random value: " << param.val() << std::endl;
+

Available distributions are listed below

+ + + + + + + + + +
Distribution Method Parameters
Uniform uniformDistribution() minimum value, maximum value
Normal normalDistribution() mean, standard deviation
Weibull weibullDistribution() shape parameter, scale parameter
+

+Defining the Phytomer and its Parameters

+

Phytomers are defined by a set of parameters that specify its geometry. These parameters are stored in a data structure called PhytomerParameters. The phytomer parameters are parameters that are constant (aside from randomization), and are usually species-specific.

+

The table below lists the parameters that define the geometry of the phytomer, and their descriptions. There are some parameters that are notably absent, such as the internode length and radius. Since these parameters vary with age and position along the shoot, these are considered to be parameters of the shoot and not the phytomer. Shoot parameters are described below in Defining Shoots and their Parameters.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter Type Units Description
internode
pitch RandomParameter_float degrees Angle of the phytomer internode with respect to the previous phytomer along the shoot. Setting this >0 creates a zig-zag shoot.
phyllotactic_angle RandomParameter_float degrees Angle between the petioles/buds of two successive phytomers along the shoot. See this page for more information on phyllotaxis.
max_vegetative_buds_per_petiole RandomParameter_int - Maximum number of possible vegetative nodes per petiole. Some of these buds may not break depending on the vegetative bud break probability.
max_floral_buds_per_petiole RandomParameter_int - Maximum number of possible floral nodes per petiole. Some of these buds may not break depending on the flower bud break probability.
color helios::RGBcolor - Diffuse color of the internode tube.
length_segments uint - Number of longitudinal segment subdivisions of the internode tube.
radial_subdivisions uint - Number of radial subdivisions segments of the internode tube (e.g., =4 gives a square cross-section; =5 gives a pentagonal cross-section, etc.)
petiole
petioles_per_internode uint - Number of petioles emanating from a single internode (e.g., for an 'opposite' growth pattern, = 2)
pitch RandomParameter_float degrees Angle of the petiole base axis with respect to its parent phytomer axis.
radius RandomParameter_float meters Radius of petiole cross-section. (radius = 0 does not create any petiole)
length RandomParameter_float meters Length of the petiole tube. (length = 0 does not create any petiole)
curvature RandomParameter_float degrees/meter Curvature angle of the petiole per unit length of petiole. If curvature is positive, petiole curves upward toward vertical. If negative, curvature is downward.
taper RandomParameter_float - Ratio between the petiole radius at the tip to the radius at the base (e.g., =1 has no taper, =0 comes to a point at the tip).
color helios::RGBcolor - Diffuse color of the petiole tube.
length_segments uint - Number of longitudinal segment subdivisions of the petiole tube.
radial_subdivisions uint - Number of radial subdivisions segments of the petiole tube (e.g., =4 gives a square cross-section; =5 gives a pentagonal cross-section, etc.)
leaf
leaves_per_petiole uint - Number of leaves on each petiole. >1 creates a compound leaf.
pitch RandomParameter_float degrees Angle of the leaf axis with respect to its parent petiole axis.
yaw RandomParameter_float degrees Rotation angle of the leaf about its base along the plane of its lamina.
roll RandomParameter_float degrees Rotation angle of the leaf about it's own axis (midrib).
leaflet_offset RandomParameter_float - If a compound leaf (leaves_per_petiole>1), this sets the spacing between adjacent leaflets along the petiole as a fraction of the petiole length. Note that the first two leaves from the tip will be offset from the tip by half this value.
leaflet_scale RandomParameter_float - If a compound leaf (leaves_per_petiole>1), this sets the scaling factor of the leaflet moving down the petiole with respect to the previous leaf (<1 scales down, >1 scales up).
prototype_scale RandomParameter_float - Scaling factor applied to the leaf prototype. Usually the prototype has unit length, so this sets the physical length of the leaf.
prototype_function function pointer - Pointer to a function that generates the leaf prototype model. Function takes arguments ( helios::Context*, uint subdivisions, int flag ) and returns an object ID (uint).
peduncle
length RandomParameter_float meters Length of the peduncle (inflorescence supporting structure).
radius RandomParameter_float meters Radius of the peduncle.
pitch RandomParameter_float degrees Angle of the peduncle axis with respect to its parent internode axis.
roll RandomParameter_float degrees Rotation angle of the peduncle about it's own axis.
curvature RandomParameter_float degrees/meter Curvature angle of the peduncle per unit length of peduncle. If curvature is positive, peduncle curves upward toward vertical. If negative, curvature is downward.
length_segments uint - Number of longitudinal segment subdivisions of the inflorescence supporting structure.
radial_subdivisions uint - Number of radial subdivisions segments of the inflorescence supporting structure (e.g., =4 gives a square cross-section; =5 gives a pentagonal cross-section, etc.)
inflorescence
flowers_per_rachis RandomParameter_int - Number of flowers per peduncle (rachis).
flower_offset RandomParameter_float - If peduncle has multiple flowers/fruit (flowers_per_rachis>1), this sets the spacing between adjacent flowers/fruit along the peduncle as a fraction of the peduncle length.
flower_arrangement_pattern std::string - Pattern of flower arrangement on the peduncle (rachis): one of "alternate" or "opposite". Only used if flowers_per_rachis > 1.
pitch RandomParameter_float degrees Angle of the fruit axis with respect to its parent peduncle axis.
roll RandomParameter_float degrees Rotation angle of the fruit about it's own axis (x-axis of fruit prototype).
flower_prototype_scale RandomParameter_float - Scaling factor applied to the flower prototype. Usually the prototype has unit length, so this sets the physical length of the flower.
flower_prototype_function function pointer - Pointer to a function that generates the flower prototype model. Function takes arguments ( helios::Context*, uint subdivisions, bool flower_is_open ) and returns an object ID (uint).
fruit_prototype_scale RandomParameter_float - Scaling factor applied to the fruit prototype. Usually the prototype has unit length, so this sets the physical length of the fruit.
fruit_prototype_function function pointer - Pointer to a function that generates the fruit prototype model. Function takes arguments ( helios::Context*, uint subdivisions, float time_since_fruit_set ) and returns an object ID (uint).
+

The phytomer parameters are stored in a data structure (struct) called PhytomerParameters. This structure has sub-member structs for each of internode, leaf, petiole, and inflorescence, each containing the parameters for that element type as designated in the table above. Below is an example of how to set a few of the parameters:

+
+
phytomer.internode.pitch = 0.1;
+
phytomer.petiole.radius = 0.001;
+
phytomer.petiole.length = 0.05;
+
phytomer.leaf.pitch = 0.1;
+
phytomer.leaf.prototype_scale = 0.1;
+
phytomer.peduncle.length = 0.1;
+ +

The figure below provides some examples of how various shoot growth patterns (e.g., alternate, opposite) can be created by varying the model parameters.

+
+ +
+

+Creating Plant Organ Prototypes

+

The geometry of plant leaves, flowers, and fruit are defined based on ‘prototype’ models that can be specified in a number of ways. Each time one of these organ types is to be generated in the model, a user-defined function is called to add the geometry. The user can write a function to add a Tile object, a mesh of triangles, load a polygon model from file, or any other desired method.

+

The prototype functions must return an object ID ( uint) corresponding to the compound object created in the function. Arguments to the prototype function vary based on organ type:

+

Leaves

uint(*prototype_function)( helios::Context*, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes )
+
Stores the state associated with simulation.
Definition: Context.h:1705
+

Flowers

uint(*prototype_function)( helios::Context*, uint subdivisions, bool flower_is_open )
+

Fruit

uint(*prototype_function)( helios::Context*, uint subdivisions, float time_since_fruit_set )
+

The arguments do not necessarily need to be used inside the prototype function, but are always passed to the function in case they are needed.

+

The size, position, and orientation of the prototype when it is created needs to follow a specific convention.

+
    +
  • Prototype size: The prototype should have a unit length, and the size of the organ is set by scaling the prototype in the prototype function. This is done to allow for consistent scaling of the organ based on the parameters of the phytomer and petiole.
  • +
  • Prototype origin: The base of the organ should be located at the origin (0,0,0). For a leaf, the base is the point at which the leaf meets the petiole. For a flow or fruit, this is the point at which the organ meets its supporting structure (peduncle).
  • +
  • Prototype orientation: The organ should be oriented such that its centerline axis is along the positive x-axis, with the positive z-axis pointing upward from the base of the organ.
  • +
+
+ +
+

A simple leaf prototype function is given below, which simply loads a model from an OBJ file.

+
uint someLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AlmondLeaf.obj", make_vec3(0,0,0), 0, nullrotation, RGB::black, "ZUP", true );
+
return context_ptr->addPolymeshObject( UUIDs );
+
}
+
std::vector< uint > loadOBJ(const char *filename, bool silent=false)
Load geometry contained in a Wavefront OBJ file (.obj). Model will be placed at the origin without an...
+
uint addPolymeshObject(const std::vector< uint > &UUIDs)
Add new Polymesh Compound Object.
Definition: Context.cpp:4756
+

A generic leaf prototype function is given in the file Assets.cpp, which creates a leaf from a mesh of triangles, and has adjustable parameters to add leaf curvature, folding, and waves. The advantage of this approach is that each leaf will have random variation, since the leaf is generated procedurally. The disadvantage is that it may not look as detailed as a leaf created outside Helios (e.g., in Blender) that has detailed sculpting of leaf texture, for example.

+
uint someLeafPrototype( helios::Context* context_ptr, uint subdivisions, int compound_leaf_index, uint shoot_node_index, uint shoot_max_nodes ){
+
+
std::string leaf_texture = "plugins/plantarchitecture/assets/textures/AlmondLeaf.png";
+
+
float leaf_aspect = 0.4; //ratio of leaf width to leaf length
+
+
float midrib_fold = 0.2; //fraction of folding along midrib (=0 leaf is flat, =1 leaf is completely folded in half)
+
+
float x_curvature = -0.1; //curvature factor along x-direction. (+curves upward, -curved downward)
+
float y_curvature = 0.4; //curvature factor along y-direction. (+curves upward, -curved downward)
+
+
float petiole_roll = 0.f; //creates a roll of the leaf near its base to more smoothly meet the petiole
+
+
//parameters for leaf wave/wrinkles
+
float wave_period = 0.1f; //period factor of leaf waves
+
float wave_amplitude = 0.03f; // amplitude of leaf waves
+
+
uint objID = buildGenericLeafPrototype(context_ptr, subdivisions, leaf_texture, leaf_aspect, midrib_fold, x_curvature, y_curvature, petiole_roll, wave_period, wave_amplitude);
+
+
return objID;
+
}
+

+Compound Leaves

+

Compound leaves consist of a single petiole with multiple leaves (leaflets) attached. The number of leaflets is specified by the parameter leaves_per_petiole in the PhytomerParameters structure (if leaves_per_petiole = 1, it is not a compound leaf). The compound leaf is formed by making a copy of the leaf prototype, and scaling, rotating, and translating it based on the position along the petiole. If there is an even number of leaflets, there will be two leaves attached to the tip of the leaf at an angle of 60 degrees from each other, whereas if the number of leaflets is even there will be a single leaf attached to the tip. The size of these tip leaves is set by the parameter leaf_prototype_scale. If the number of leaflets is greater than 2, additional leaflets are added running down the petiole in an opposite pattern. The spacing between adjacent leaflets is specified as a fraction of the petiole length by the parameter leaflet_offset, and the scaling factor of the leaflet moving down the petiole with respect to the previous leaflet is specified by the parameter leaflet_offset. The leaflets along the petiole can either get bigger or smaller than the tip leaf/(leaves) according to the parameter leaflet_scale (<1 gets smaller, >1 gets bigger).

+
+ +
+Schematic illustration of varying compound leaves and their parameters. (a) A compound leaf with 7 leaflets. (b) A compound leaf with an even number of leaflets (6). (c) A compound leaf with a leaflet offset of 0.
+

Alternatively, a compound leaf could be created by adding a single "leaf prototype" that contains all of the leaflets in a single model/mesh and specifying 1 leaf per petiole. However, the drawback of this is that it would not be possible to add random variation to the appearance of the compound leaf (e.g., leaf pitch angle, leaf yaw angle, etc.).

+

+Inflorescence

+

The term 'inflorescence' used to denote the peduncle and flowers together. The peduncle is the supporting structure that connects the internode to the flowers. In this model, we do not distinguish between the peduncle (part between the internode and first flower) and the rachis (part that connects adjacent flowers when there are multiple flowers per inflorescence) - this is all considered the peduncle for simplicity.

+

If flowers_per_rachis is greater than 1, the flowers are arranged along the peduncle in a pattern specified by the parameter flower_arrangement_pattern (the two options are "alternate" and "opposite"). The flower_offset parameter specifies the spacing between adjacent flowers along the peduncle.

+

The sketch below shows an example of one parameter set for the infloresence.

+
+ +
+

+Defining Shoots and their Parameters

+

A shoot is the fundamental topological unit of organization in the plant architectural model, and consists of a series of connected phytomers. Each phytomer contains one or more vegetative buds at the point where the petioles meet the internode, which have the possibility to spawn child shoots.

+

Parameters defining the geometry and growth of the shoot are given in the ShootParameters structure. Each parameter in the ShootParameters structure is summarized in the table below, and described in more detail in the following sections.

+

| Parameter | Type | Default | Units | Description | | ---—| ---— | ---— | ---— | | — Phytomer Parameters — |||| | phytomer_parameters | PhytomerParameters | - | - | Parameters defining the geometry of the phytomers comprising this shoot. | | — Geometric Parameters — ||||| | max_nodes | RandomParameter_int | 10 | - | Maximum number of nodes/phytomers along a shoot. | | internode_radius_initial | RandomParameter_float | 0.001 | meters | Initial radius of the internode when it is created. | | internode_radius_max | RandomParameter_float | unlimited | meters | Maximum internode radius for girth growth. For some species like grasses, girth growth stops at some radius. By default, girth growth will continue indefinitely. | | child_insertion_angle_tip | RandomParameter_float | 20 | degrees | Angle of the child shoot with respect to the parent shoot at the tip of the parent shoot. | | child_insertion_angle_decay_rate | RandomParameter_float | 0 | degrees/node | Rate of increase of the child insertion angle moving down the parent shoot. | | child_internode_length_max | RandomParameter_float | 0.02 | meters | Maximum length (with respect to position along the parent shoot) of the internode of a child shoot. | | child_internode_length_min | RandomParameter_float | 0.002 | meters | Minimum length (with respect to position along the parent shoot) of the internode of a child shoot. | | child_internode_length_decay_rate | RandomParameter_float | 0 | meters/node | Rate of decrease of the internode length moving down the parent shoot. | | base_roll | RandomParameter_float | 0 | degrees | Roll angle of the shoot, which effectively specifies the angle of the first petiole relative to the parent shoot. | | base_yaw | RandomParameter_float | 0 | degrees | Yaw angle of the shoot relative to the parent shoot. | | gravitropic_curvature | RandomParameter_float | 0 | degrees/meter | Curvature angle of the shoot per unit length of shoot. If curvature is positive, shoot curves upward toward vertical. If negative, curvature is downward. | | tortuosity | RandomParameter_float | 0 | - | Factor determining the amount of random "wiggle" in internode growth along the shoot. | | — Growth Parameters — ||||| | phyllochron | RandomParameter_float | 1.0 | days/leaf | Time between the emergence of successive phytomers along the shoot. | | leaf_flush_count | uint | 1 | - | Number of leaves/phytomers to flush at a time. Flushes will occur at an interval of phyllochron*leaf_flush_count. | | elongation_rate | RandomParameter_float | 0.2 | meter/meter/day | Relative rate of elongation of the internode of the shoot. Units are meters of elongation per meter of maximum internode length per day. | | girth_growth_rate | RandomParameter_float | 0.0001 | meter/day | Rate of increase of the internode radius of the shoot. Units are meters of increase in internode radius per day. | | vegetative_bud_break_time | RandomParameter_float | 5 | days | Amount of time after the bud is created or after dormancy is broken for the vegetative bud to break. | | vegetative_bud_break_probability | RandomParameter_float | 0 | - | Probability of a bud breaking dormancy and emerging as a shoot. | | flower_bud_break_probability | RandomParameter_float | 0 | - | Probability of a flower bud emerging as a flower. | | fruit_set_probability | RandomParameter_float | 0 | - | Probability of a flower becoming a fruit. | | growth_requires_dormancy | bool | false | - | Flag indicating whether or not the vegetative buds require a winter dormancy period to break into a shoot. If true, the shoot will emerge in the same growing season as the parent shoot. If false, the shoot will emerge from a bud that requires a winter dormancy period. | | flowers_require_dormancy | bool | false | - | Flag indicating whether or not the flower buds require a winter dormancy period to emerge. If true, the flowers will emerge in the same growing season as the parent shoot. If false, the flowers will emerge from a bud that requires a winter dormancy period. | | determinate_shoot_growth | bool | true | - | Flag indicating whether or not shoot growth is determinate. If true, shoot growth will stop once flowering occurs, and the apical bud will become dormant. If false, the shoot will continue growing after flowering. |

+

+Geometric Parameters of the Shoot

+

+max_nodes

+

max_nodes is the maximum number of phytomers that a single shoot can grow to have. Leaves will continue to emerge from the terminal bud according to the phyllochron until max_nodes is reached.

+

+base_roll

+

base_roll is the roll angle of the first phytomer of the shoot about the shoot axis relative to vertical. If base_roll = 0, the first petiole along the shoot will be vertical (or as vertical as is possible given the shoot direction and the specified angle of the petiole relative to the internode). This parameter is used to set the initial orientation of the shoot. For example, if base_roll = 0, the first phytomer of the shoot will be oriented vertically. If base_roll = 30, the first phytomer of the shoot will be oriented 30 degrees from vertical.

+

+internode_radius_initial

+

Will come back to this later. It is currently used in two places: 1. within addPhytomerToShoot() to set the radius of the internode added to an existing shoot, and 2) within buildShootPhytomers() to either set the radius of the internodes if it is the trunk/base, or the radius is set as a fraction of internode_radius_iniitial.

+

+child_insertion_angle_tip and child_insertion_angle_decay_rate

+

The insertion angle of child shoots is the angle that a child shoot makes with its parent shoot growth axis.

+

The methodology for determining the insertion angle of a child shoot differs depending on whether the shoot emerges from a bud that requires a winter dormancy period (proleptic shoot), or whether the shoot emerges in the same growing season. This behavior is set based on the parameter ShootParameters::growth_requires_dormancy (more information on this parameter below).

+

For buds NOT requiring dormancy (ShootParameters::growth_requires_dormancy = false), the insertion angle of the child shoot is simply given by the parameter child_insertion_angle_tip (degrees). (In this case, the parameter child_insertion_angle_decay_rate is not used.)

+

For buds requiring dormancy (proleptic; ShootParameters::growth_requires_dormancy = true), the insertion angle of the child shoot is the smallest at the tip of the shoot (at the time dormancy is broken) and increases moving down the shoot toward and angle of 90 degrees.

+

As shown in the figure below, the insertion angle at the shoot tip is given by the parameter child_insertion_angle_tip (degrees). The angle increases linearly at a rate of child_insertion_angle_decay_rate (units of degrees per node) until it reaches a maximum insertion angle of 90 degrees. For example, if child_insertion_angle_tip = 20 degrees and child_insertion_angle_decay_rate = 20 degrees/node, the insertion angle at the second node from the tip would be 40 degrees, 60 degrees at the third node, 80 degrees at the fourth node, and 90 degrees at all subsequent nodes, up until reaching the previous year's growth.

+
+ +
+

+child_internode_length_max, child_internode_length_min, and child_internode_length_decay_rate

+

The "potential" or fully elongated internode length is specified for a shoot, and is constant along the length of the shoot. When a phytomer emerges from a bud (either apical or lateral along a parent shoot) it's internode is scaled to some short initial size, and elongates over time according to the elongation rate parameter (see below).

+

Similar to determination of the child insertion angle, the methodology for determination of the fully elongated internode length of a child shoot depends on whether or not the child shoot is emerging from a dormant bud.

+

For buds NOT requiring dormancy (ShootParameters::growth_requires_dormancy = false), the potential length of internodes along a shoot is determined according to the value of the child_internode_length_max parameter.

+

For buds requiring dormancy (proleptic; ShootParameters::growth_requires_dormancy = true), the potential length of a shoot's internodes is maximum at the tip of the shoot (at the time dormancy is broken) and decreases moving down the shoot. The potential length of the internode at the tip of the shoot is given by the parameter child_internode_length_max. The length decreases linearly at a rate of child_internode_length_decay_rate (units of meters per node) until it reaches a minimum length given by the parameter child_internode_length_min. For example, if child_internode_length_max = 0.1 m, child_internode_length_min = 0.01 m, and child_internode_length_decay_rate = 0.03 m/node, the potential length of the internode at the second node from the tip would be 0.07 m, 0.04 m at the third node, 0.01 m at the fourth node, and 0.01 m at all subsequent nodes, up until reaching the previous year's growth.

+
+ +
+

+gravitropic_curvature

+

The tendency of shoots to grow toward vertical is given by the parameter gravitropic_curvature. This parameter is the curvature angle of the shoot per unit length of shoot. If curvature is positive, the shoot curves upward toward vertical. If negative, the shoot curves downward. Once the shoot has reached vertical, it will continue to grow vertically. For example, a shoot that emerges from the bud growing horizontally with gravitropic_curvature = 90 degrees/meter will curve upward such that it will be growing upward after the first meter of growth.

+

+tortuosity

+

Random "wiggle" can be added to shoot growth using the tortuosity parameter. Each time a phytomer is added to the shoot, some constant amount of differential curvature is added according to the parameter gravitropic_curvature. To introduce random variation, an additional amount of noise is added to the curvature based on a Langevin-like equation (Brownian motion):

+

+\[
+    d\theta = \frac{1}{2}\left(C_g-\theta\right)dL + T\xi(dL)
+\] +

+

where $d\theta$ is the change in curvature angle of the current phytomer internode relative to the previous internode, $\theta$ is the integrated curvature angle relative to the base of the shoot, $dL$ is the internode length, $T$ is the tortuosity, and $\xi (dL)$ is a Gaussian process with variance of $dL$.

+

+Growth Parameters of the Shoot

+

+phyllochron

+

The phyllochron parameter is the time between the emergence of successive phytomers from the shoot terminal bud. Note that if the number of nodes/phytomers along the shoot reaches gravitropic_curvature, the terminal bud will die and cease producing new phytomers.

+

+elongation_rate

+

The elongation_rate parameter is the rate of axial elongation of the internode of the shoot. When the phytomer is created the internode is small, and will elongate over time according to elongation_rate until it reaches its potential or maximum internode length as determined by the methodology described above. The elongation rate has units of length added to the internode per day.

+

+girth_growth_rate

+

The girth_growth_rate parameter is the rate of increase of the internode radius, given as a scaling factor applied to the current radius. The girth growth rate value is the scale factor applied to the current radius per day. For example, if girth_growth_rate = 1.01, the radius of the internode will increase by 1% per day.

+

+Loading a Plant from the Existing Library

+

A number of plant models are available in the plant architecture library, which can be created based on default parameters, or parameters modified by the user. Plant models available in the library are given in the table below.

+ + + + + + + + + + + + + + + + + + + + + + + +
Plant Type/Species Variety/Variation Plant type string argument Shoot types Image at time = 0 Image at flowering Image at (reproductive) maturity
Almond Tree (Prunus dulcis) Nonpareil "almond" trunk, scaffold, proleptic, sylleptic
Bindweed (Convolvulus arvensis) generic "bindweed" base, offshoots, children
Cheeseweed (Malva neglecta) generic "cheeseweed" mainstem
Common Bean (Phaseolus vulgaris) upright growth habit (determinate) "bean" unifoliate, trifoliate
Cowpea (Vigna unguiculata) upright growth habit (determinate) "cowpea" unifoliate, trifoliate
Puncturevine (Tribulus terrestris) generic "puncturevine" base, offshoots, children
Sorghum (Sorghum bicolor) grain sorghum "sorghum" mainstem
Soybean (Glycine max) upright growth habit (determinate) "soybean" unifoliate, trifoliate
Sugar Beet (Beta vulgaris) generic "sugarbeet" mainstem
Tomato (Solanum lycopersicum) determinate growth "tomato" mainstem
+

+Loading a Plant with Default Parameters

+

Loading a plant from the library with default parameters is relatively simple, and requires only declaring the PlantArchitecture class, loading the model using the PlantArchitecture::loadPlantModelFromLibrary() method (which takes a string argument for the plant model as listed in the table above), and calling the PlantArchitecture::buildPlantInstanceFromLibrary() method. The method takes two arguments: 1) the Cartesian (x,y,z) position of the plant base, and 2) the age of the plant in days. A code example is given below.

+
+
using namespace helios;
+
+
int main(){
+
+
Context context;
+
+
PlantArchitecture plantarchitecture(&context);
+
+
plantarchitecture.loadPlantModelFromLibrary( "bean" );
+
plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, 0 );
+
+
return 0;
+
}
+ + +

+Modifying Parameters of a Plant from the Library

+

Building a plant from the library with modified parameters is similar to above, except that the parameters are modified before calling the PlantArchitecture::buildPlantInstanceFromLibrary() method. After calling PlantArchitecture::loadPlantModelFromLibrary(), the parameters can be queried (at the shoot level), modified, and then set.

+

Parameters are queried based on shoot type (the names of which are given in the table above). The user can either query the ShootParameters structure for a single shoot type based on its label, or for all shoot types in the particular model.

+

Below is an example of modifying the parameters of a single shoot type:

+
plantarchitecture.loadPlantModelFromLibrary( "almond" );
+
+
ShootParameters shoot_parameters = plantarchitecture.getCurrentShootParameters( "trunk" );
+
shoot_parameters.internode_radius_initial = 0.2;
+
shoot_parameters.phytomer_parameters.internode.pitch = 10;
+
+
plantarchitecture.updateCurrentShootParameters( "trunk", shoot_parameters );
+
plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, 0 );
+ +

Below is an example of modifying the parameters for all shoot types:

+
plantarchitecture.loadPlantModelFromLibrary( "almond" );
+
+
std::map<std::string,ShootParameters> shoot_parameters = plantarchitecture.getCurrentShootParameters( "trunk" );
+
for( auto params : shoot_parameters ){
+
std::string shoot_type = params.first;
+
ShootParameters P = params.second;
+
P.internode_radius_initial = 0.2;
+
P.phytomer_parameters.internode.pitch = 10;
+
plantarchitecture.updateCurrentShootParameters( shoot_type, P );
+
}
+
plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, 0 );
+

+Modifying Phenological Threshold Parameters

+

Thresholds determining phenological transitions are set using the PlantArchitecture::setPlantPhenologicalThresholds() method. The thresholds are in arbitrary time units, which should be consistent with the timestep units and units of other parameters. The table below describes each of the phenological parameters. Setting any parameter to a negative value will skip that phenological stage.

+ + + + + + + + + + + + + + + +
Phenological Threshold Description
time_to_dormancy_break Time required to break dormancy starting from the time of entering dormancy (or since the start of the simulation if starting dormant).
time_to_flower_initiation Time from emergence/dormancy required to reach flower creation (closed flowers).
time_to_flower_opening Time from flower initiation required to reach flower opening (open flowers). (If flower initiation was skipped, time is relative to emergence/dormancy).
time_to_fruit_set Time from flower opening required to reach fruit set. (If flower opening or initiation was skipped, time is relative to previous phenological stage).
time_to_fruit_maturity Time from fruit set required to reach maturity. (If fruit set was skipped, time is relative to previous phenological stage).
time_to_senescence Time from emergence/dormancy required to reach senescence. At senescence, leaves and fruit will be removed, and the plant will become dormant.
+
PlantArchitecture plantarchitecture(&context);
+
+
plantarchitecture.loadPlantModelFromLibrary( "bean" );
+
uint plantID = plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, 0 );
+
+
plantarchitecture.setPlantPhenologicalThresholds( plantID, 0, 20, 10, 10, 5, 70 );
+

+Growing the Model over Time

+

The model can be grown over time by calling the PlantArchitecture::advanceTime() method, where the argument to this method is the timestep to advance in days. The timestep value can be larger than the phyllochron, such that multiple phytomers and shoots can be produced in a single call to PlantArchitecture::advanceTime().

+
plantarchitecture.advanceTime( 1 );
+

+Retrieving Information from the Model

+

+Getting Object IDs and Primitive UUIDs of Model Geometry

+

The Object IDs and Primitive UUIDs of an entire plant, or organ groups in the plant, can be retrieved using several methods available in the PlantArchitecture class. These are listed in the table below.

+ + + + + + + + + + + + + + + + + + + + + + + +
MethodDescription
Object IDs
PlantArchitecture::getAllPlantObjectIDs()Returns a vector of Object IDs for all objects the entire plant.
PlantArchitecture::getPlantInternodeObjectIDs()Returns a vector of Object IDs for all internode objects.
PlantArchitecture::getPlantPetioleObjectIDs()Returns a vector of Object IDs for all petiole objects (Tube objects).
PlantArchitecture::getPlantLeafObjectIDs()Returns a vector of Object IDs for all leaf objects.
PlantArchitecture::getPlantPeduncleObjectIDs()Returns a vector of Object IDs for all peduncle objects (Tube objects).
PlantArchitecture::getPlantFlowerObjectIDs()Returns a vector of Object IDs for all flower objects.
PlantArchitecture::getPlantFruitObjectIDs()Returns a vector of Object IDs for all fruit objects.
Primitive UUIDs
PlantArchitecture::getAllPlantUUIDs()Returns a vector of UUIDs for all primitives the entire plant.
+

Note that individual methods to get UUIDs for all organ types are not provided. Instead, the user can query the Object IDs for each organ type and then get the corresponding UUIDs using the Context method helios::Context::getObjectPrimitiveUUIDs().

+

+Getting Primitive UUIDs for Organ Sub-Components

+

In some cases, it may be useful to get the UUIDs of sub-components that make up organ prototypes. For example, this is necessary in order to change the color or radiative properties of leaf veins or flower petals.

+

If such granularity is present in the organ prototype models, these sub-components are separated based on primitive data labels assigned to them.

+ + + + + + + + + + + + + + + + + + + + + + + +
Organ Primitive Data Label Primitive Data Value String Description
Leaves
Leaf/lamina "object_label" "leaf" The main lamina of the leaf.
veins "object_label" "veins" The major veins of the leaf.
petiolule "object_label" "petiolule" The petiolule (i.e., petiole-like structure connecting a leaflet to the petiole in a compound leaf).
Flowers
Petals "object_label" "petals" The petals of the flower.
Sepals "object_label" "sepals" The sepals (i.e., green part at base) of the flower.
Fruit
Fruit "object_label" "fruit" The main body of the fruit.
Sepals "object_label" "sepals" The sepals (i.e., green part at base) of the fruit.
+

The UUIDs for a given sub-organ group can be retrieved by calling the Context method helios::Context::filterPrimitivesByData(). Below is an example for getting the leaf vein UUIDs.

+
std::vector<uint> plant_UUIDs = plantarchitecture.getAllPlantUUIDs( plantID );
+
std::vector<uint> leaf_vein_UUIDs = context.filterPrimitivesByData( plant_UUIDs, "object_label", "veins" );
+
std::vector< uint > filterPrimitivesByData(const std::vector< uint > &UUIDs, const std::string &primitive_data_label, float filter_value, const std::string &comparator)
Filter a set of primitives based on their primitive data and a condition and float value.
+

For custom user-defined organ prototypes, users should follow the convention of grouping the above sub-components into separate object groups with the labels given in the table above.

+
+
+ + + + diff --git a/doc/html/_plant_library_8cpp.html b/doc/html/_plant_library_8cpp.html new file mode 100644 index 000000000..cc492adf0 --- /dev/null +++ b/doc/html/_plant_library_8cpp.html @@ -0,0 +1,111 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
PlantLibrary.cpp File Reference
+
+
+
#include "Assets.h"
+
+

Go to the source code of this file.

+

Detailed Description

+

Contains routines for loading and building plant models from a library of predefined plant types.

+

Copyright (C) 2016-2024 Brian Bailey

+

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.

+

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

+ +

Definition in file PlantLibrary.cpp.

+
+ + + + diff --git a/doc/html/_plant_library_8cpp_source.html b/doc/html/_plant_library_8cpp_source.html new file mode 100644 index 000000000..b9f405bc9 --- /dev/null +++ b/doc/html/_plant_library_8cpp_source.html @@ -0,0 +1,1627 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
PlantLibrary.cpp
+
+
+Go to the documentation of this file.
1
+
16#include "Assets.h"
+
17
+
18using namespace helios;
+
19
+
20void PlantArchitecture::loadPlantModelFromLibrary( const std::string &plant_label ){
+
21
+
22 current_plant_model = plant_label;
+
23 initializeDefaultShoots(plant_label);
+
24
+
25}
+
26
+
27uint PlantArchitecture::buildPlantInstanceFromLibrary( const helios::vec3 &base_position, float age ){
+
28
+
29 if( current_plant_model.empty() ){
+
30 helios_runtime_error("ERROR (PlantArchitecture::buildPlantInstanceFromLibrary): current plant model has not been initialized from library. You must call loadPlantModelFromLibrary() first.");
+
31 }
+
32
+
33 uint plantID = 0;
+
34 if( current_plant_model == "almond" ) {
+
35 plantID = buildAlmondTree(base_position, age);
+
36 }else if( current_plant_model == "bindweed" ) {
+
37 plantID = buildBindweedPlant(base_position, age);
+
38 }else if( current_plant_model == "bean" ) {
+
39 plantID = buildBeanPlant(base_position, age);
+
40 }else if( current_plant_model == "cheeseweed" ) {
+
41 plantID = buildCheeseweedPlant(base_position, age);
+
42 }else if( current_plant_model == "cowpea" ) {
+
43 plantID = buildCowpeaPlant(base_position, age);
+
44 }else if( current_plant_model == "puncturevine" ) {
+
45 plantID = buildPuncturevinePlant(base_position, age);
+
46 }else if( current_plant_model == "redbud" ) {
+
47 plantID = buildRedbudPlant(base_position, age);
+
48 }else if( current_plant_model == "sorghum" ) {
+
49 plantID = buildSorghumPlant(base_position, age);
+
50 }else if( current_plant_model == "soybean" ) {
+
51 plantID = buildSoybeanPlant(base_position, age);
+
52 }else if( current_plant_model == "strawberry" ) {
+
53 plantID = buildStrawberryPlant(base_position, age);
+
54 }else if( current_plant_model == "sugarbeet" ) {
+
55 plantID = buildSugarbeetPlant(base_position, age);
+
56 }else if( current_plant_model == "tomato" ) {
+
57 plantID = buildTomatoPlant(base_position, age);
+
58 }else{
+
59 assert(true); //shouldn't be here
+
60 }
+
61
+
62 return plantID;
+
63
+
64}
+
65
+ +
67
+
68 if( shoot_types.find(shoot_type_label) == shoot_types.end() ){
+
69 helios_runtime_error("ERROR (PlantArchitecture::getCurrentShootParameters): shoot type label of " + shoot_type_label + " does not exist in the current shoot parameters.");
+
70 }
+
71
+
72 return shoot_types.at(shoot_type_label);
+
73}
+
74
+
75std::map<std::string, ShootParameters> PlantArchitecture::getCurrentShootParameters(){
+
76 if( shoot_types.empty() ){
+
77 std::cerr << "WARNING (PlantArchitecture::getCurrentShootParameters): No plant models have been loaded. You need to first load a plant model from the library (see loadPlantModelFromLibrary()) or manually add shoot parameters (see updateCurrentShootParameters())." << std::endl;
+
78 }
+
79 return shoot_types;
+
80}
+
81
+
82void PlantArchitecture::updateCurrentShootParameters( const std::string &shoot_type_label, const ShootParameters &params ){
+
83 shoot_types[shoot_type_label] = params;
+
84}
+
85
+
86void PlantArchitecture::updateCurrentShootParameters( const std::map<std::string, ShootParameters> &params ){
+
87 shoot_types = params;
+
88}
+
89
+
90void PlantArchitecture::initializeDefaultShoots( const std::string &plant_label ){
+
91
+
92 if( plant_label == "almond" ) {
+
93 initializeAlmondTreeShoots();
+
94 }else if( plant_label == "bindweed" ) {
+
95 initializeBindweedShoots();
+
96 }else if( plant_label == "bean" ) {
+
97 initializeBeanShoots();
+
98 }else if( plant_label == "cheeseweed" ) {
+
99 initializeCheeseweedShoots();
+
100 }else if( plant_label == "cowpea" ) {
+
101 initializeCowpeaShoots();
+
102 }else if( plant_label == "puncturevine" ) {
+
103 initializePuncturevineShoots();
+
104 }else if( plant_label == "sorghum" ) {
+
105 initializeSorghumShoots();
+
106 }else if( plant_label == "soybean" ) {
+
107 initializeSoybeanShoots();
+
108 }else if( plant_label == "strawberry" ) {
+
109 initializeStrawberryShoots();
+
110 }else if( plant_label == "sugarbeet" ) {
+
111 initializeSugarbeetShoots();
+
112 }else if( plant_label == "tomato" ) {
+
113 initializeTomatoShoots();
+
114 }else{
+
115 helios_runtime_error("ERROR (PlantArchitecture::loadPlantModelFromLibrary): plant label of " + plant_label + " does not exist in the library.");
+
116 }
+
117
+
118}
+
119
+
120void PlantArchitecture::initializeAlmondTreeShoots(){
+
121
+
122 // ---- Phytomer Parameters ---- //
+
123
+
124 PhytomerParameters phytomer_parameters_almond(context_ptr->getRandomGenerator());
+
125
+
126 phytomer_parameters_almond.internode.pitch = 0;
+
127 phytomer_parameters_almond.internode.phyllotactic_angle.uniformDistribution( 130, 145 );
+
128 phytomer_parameters_almond.internode.length_segments = 1;
+
129 phytomer_parameters_almond.internode.color = make_RGBcolor(0.6,0.45,0.15);
+
130 phytomer_parameters_almond.internode.max_floral_buds_per_petiole = 3;
+
131
+
132 phytomer_parameters_almond.petiole.petioles_per_internode = 1;
+
133 phytomer_parameters_almond.petiole.pitch = -50;
+
134 phytomer_parameters_almond.petiole.taper = 0.1;
+
135 phytomer_parameters_almond.petiole.curvature = 0;
+
136 phytomer_parameters_almond.petiole.length = 0.02;
+
137 phytomer_parameters_almond.petiole.radius = 0.001;
+
138 phytomer_parameters_almond.petiole.length_segments = 1;
+
139
+
140 phytomer_parameters_almond.leaf.leaves_per_petiole = 1;
+
141 phytomer_parameters_almond.leaf.prototype_function = AlmondLeafPrototype;
+
142 phytomer_parameters_almond.leaf.prototype_scale = 0.08;
+
143
+
144 phytomer_parameters_almond.peduncle.length = 0.005;
+
145 phytomer_parameters_almond.peduncle.radius = 0.0005;
+
146 phytomer_parameters_almond.peduncle.pitch = 90;
+
147 phytomer_parameters_almond.peduncle.roll = 90;
+
148 phytomer_parameters_almond.peduncle.curvature = -300;
+
149 phytomer_parameters_almond.peduncle.length_segments = 10;
+
150 phytomer_parameters_almond.peduncle.length_segments = 1;
+
151
+
152 phytomer_parameters_almond.inflorescence.flowers_per_rachis = 1;
+
153 phytomer_parameters_almond.inflorescence.pitch = 0;
+
154 phytomer_parameters_almond.inflorescence.roll = 0;
+
155 phytomer_parameters_almond.inflorescence.flower_prototype_scale = 0.03;
+
156 phytomer_parameters_almond.inflorescence.flower_prototype_function = AlmondFlowerPrototype;
+
157 phytomer_parameters_almond.inflorescence.fruit_prototype_scale = 0.025;
+
158 phytomer_parameters_almond.inflorescence.fruit_prototype_function = AlmondFruitPrototype;
+
159
+
160 // ---- Shoot Parameters ---- //
+
161
+
162 // Trunk
+
163 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
+
164 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_almond;
+
165 shoot_parameters_trunk.max_nodes = 20;
+
166 shoot_parameters_trunk.girth_growth_rate = 0.00025;
+
167 shoot_parameters_trunk.internode_radius_initial = 0.005;
+
168 shoot_parameters_trunk.vegetative_bud_break_probability = 1;
+
169 shoot_parameters_trunk.vegetative_bud_break_time = 0;
+
170 shoot_parameters_trunk.tortuosity = 1000;
+
171 shoot_parameters_trunk.defineChildShootTypes({"scaffold"},{1});
+
172 shoot_parameters_trunk.phyllochron = 100;
+
173
+
174 // Proleptic shoots
+
175 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
+
176 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_almond;
+
177 shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = AlmondPhytomerCreationFunction;
+
178 shoot_parameters_proleptic.max_nodes = 36;
+
179 shoot_parameters_proleptic.phyllochron.uniformDistribution(1,1.1);
+
180 shoot_parameters_proleptic.elongation_rate = 0.25;
+
181 shoot_parameters_proleptic.girth_growth_rate = 0.00025;
+
182 shoot_parameters_proleptic.vegetative_bud_break_probability = 0.75;
+
183 shoot_parameters_proleptic.vegetative_bud_break_time = 0;
+
184 shoot_parameters_proleptic.gravitropic_curvature.uniformDistribution(180,210);
+
185 shoot_parameters_proleptic.tortuosity = 60;
+
186 shoot_parameters_proleptic.internode_radius_initial = 0.001;
+
187 shoot_parameters_proleptic.child_insertion_angle_tip.uniformDistribution( 35, 45);
+
188 shoot_parameters_proleptic.child_insertion_angle_decay_rate = 10;
+
189 shoot_parameters_proleptic.child_internode_length_max = 0.03;
+
190 shoot_parameters_proleptic.child_internode_length_min = 0.0005;
+
191 shoot_parameters_proleptic.child_internode_length_decay_rate = 0.0025;
+
192 shoot_parameters_proleptic.fruit_set_probability = 0.5;
+
193 shoot_parameters_proleptic.flower_bud_break_probability = 0.75;
+
194 shoot_parameters_proleptic.flowers_require_dormancy = true;
+
195 shoot_parameters_proleptic.growth_requires_dormancy = true;
+
196 shoot_parameters_proleptic.determinate_shoot_growth = false;
+
197 shoot_parameters_proleptic.defineChildShootTypes({"sylleptic","proleptic"},{0.2,0.8});
+
198
+
199 // Sylleptic shoots
+
200 ShootParameters shoot_parameters_sylleptic = shoot_parameters_proleptic;
+
201 shoot_parameters_sylleptic.phytomer_parameters.leaf.prototype_scale = 0.12;
+
202 shoot_parameters_sylleptic.phytomer_parameters.leaf.pitch.uniformDistribution(-45, -20);
+
203 shoot_parameters_proleptic.phyllochron = 1.5;
+
204 shoot_parameters_sylleptic.vegetative_bud_break_probability = 1;
+
205 shoot_parameters_sylleptic.gravitropic_curvature.uniformDistribution(250,300);
+
206 shoot_parameters_sylleptic.child_internode_length_max = 0.05;
+
207 shoot_parameters_sylleptic.flowers_require_dormancy = true;
+
208 shoot_parameters_sylleptic.growth_requires_dormancy = true; //seems to not be working when false
+
209 shoot_parameters_sylleptic.defineChildShootTypes({"sylleptic"},{1.0});
+
210
+
211 // Main scaffolds
+
212 ShootParameters shoot_parameters_scaffold = shoot_parameters_proleptic;
+
213 shoot_parameters_scaffold.gravitropic_curvature.uniformDistribution(40,50);
+
214 shoot_parameters_scaffold.phyllochron = 1;
+
215 shoot_parameters_scaffold.child_internode_length_max = 0.03;
+
216 shoot_parameters_scaffold.tortuosity = 15;
+
217 shoot_parameters_scaffold.defineChildShootTypes({"proleptic"},{1.0});
+
218
+
219 defineShootType("trunk", shoot_parameters_trunk);
+
220 defineShootType("scaffold", shoot_parameters_scaffold);
+
221 defineShootType("proleptic", shoot_parameters_proleptic);
+
222 defineShootType("sylleptic", shoot_parameters_sylleptic);
+
223
+
224}
+
225
+
226uint PlantArchitecture::buildAlmondTree(const helios::vec3 &base_position, float age) {
+
227
+
228 if( shoot_types.empty() ){
+
229 //automatically initialize almond tree shoots
+
230 initializeAlmondTreeShoots();
+
231 }
+
232
+
233 uint plantID = addPlantInstance(base_position, age);
+
234
+
235 uint uID_trunk = addBaseStemShoot(plantID, 8, make_AxisRotation(context_ptr->randu(0.f, 0.025f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), 0.f * M_PI), 0.025, 0.1, 1.f, 1.f, "trunk");
+
236
+
237 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
+
238
+
239 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
+
240 for( const auto & phytomer : phytomers ){
+
241 phytomer->removeLeaf();
+
242 phytomer->setVegetativeBudState(BUD_DEAD);
+
243 phytomer->setFloralBudState(BUD_DEAD);
+
244 }
+
245
+
246 uint Nscaffolds = context_ptr->randu(4,5);
+
247
+
248 for( int i=0; i<Nscaffolds; i++ ) {
+
249 uint uID_shoot = appendShoot(plantID, uID_trunk, context_ptr->randu(10, 12), make_AxisRotation(context_ptr->randu(deg2rad(45), deg2rad(55)), (float(i) + context_ptr->randu(-0.1f, 0.1f)) / float(Nscaffolds) * 2 * M_PI, 0), 0.0075, 0.03, 1.f, 1.f, "scaffold");
+
250
+
251 plant_instances.at(plantID).shoot_tree.at(uID_shoot)->breakDormancy();
+
252
+
253 uint blind_nodes = context_ptr->randu(5,8);
+
254 for( int b=0; b<blind_nodes; b++){
+
255 if( b<plant_instances.at(plantID).shoot_tree.at(uID_shoot)->phytomers.size() ) {
+
256 plant_instances.at(plantID).shoot_tree.at(uID_shoot)->phytomers.at(b)->removeLeaf();
+
257 plant_instances.at(plantID).shoot_tree.at(uID_shoot)->phytomers.at(b)->setFloralBudState(BUD_DEAD);
+
258 plant_instances.at(plantID).shoot_tree.at(uID_shoot)->phytomers.at(b)->setVegetativeBudState(BUD_DEAD);
+
259 }
+
260 }
+
261
+
262 }
+
263
+
264 setPlantPhenologicalThresholds(plantID, 0, 1, 1, 3, 7, 12);
+
265
+
266 return plantID;
+
267
+
268}
+
269
+
270void PlantArchitecture::initializeBindweedShoots() {
+
271
+
272 // ---- Phytomer Parameters ---- //
+
273
+
274 PhytomerParameters phytomer_parameters_bindweed(context_ptr->getRandomGenerator());
+
275
+
276 phytomer_parameters_bindweed.internode.pitch.uniformDistribution(0,15);
+
277 phytomer_parameters_bindweed.internode.phyllotactic_angle = 180.f;
+
278 phytomer_parameters_bindweed.internode.color = make_RGBcolor(0.64, 0.71, 0.53);
+
279 phytomer_parameters_bindweed.internode.length_segments = 1;
+
280
+
281 phytomer_parameters_bindweed.petiole.petioles_per_internode = 1;
+
282 phytomer_parameters_bindweed.petiole.pitch.uniformDistribution(80, 100);
+
283 phytomer_parameters_bindweed.petiole.radius = 0.001;
+
284 phytomer_parameters_bindweed.petiole.length = 0.005;
+
285 phytomer_parameters_bindweed.petiole.taper = 0;
+
286 phytomer_parameters_bindweed.petiole.curvature = 0;
+
287 phytomer_parameters_bindweed.petiole.color = phytomer_parameters_bindweed.internode.color;
+
288 phytomer_parameters_bindweed.petiole.length_segments = 1;
+
289
+
290 phytomer_parameters_bindweed.leaf.leaves_per_petiole = 1;
+
291 phytomer_parameters_bindweed.leaf.pitch.uniformDistribution(5, 30);
+
292 phytomer_parameters_bindweed.leaf.yaw = 0;
+
293 phytomer_parameters_bindweed.leaf.roll = 90;
+
294 phytomer_parameters_bindweed.leaf.prototype_function = BindweedLeafPrototype;
+
295 phytomer_parameters_bindweed.leaf.prototype_scale = 0.04;
+
296
+
297 phytomer_parameters_bindweed.peduncle.length = 0.001;
+
298 phytomer_parameters_bindweed.inflorescence.flowers_per_rachis = 1;
+
299 phytomer_parameters_bindweed.inflorescence.pitch = -90.f;
+
300 phytomer_parameters_bindweed.inflorescence.flower_prototype_function = BindweedFlowerPrototype;
+
301 phytomer_parameters_bindweed.inflorescence.flower_prototype_scale = 0.03;
+
302
+
303 // ---- Shoot Parameters ---- //
+
304
+
305 ShootParameters shoot_parameters_primary(context_ptr->getRandomGenerator());
+
306 shoot_parameters_primary.phytomer_parameters = phytomer_parameters_bindweed;
+
307 shoot_parameters_primary.vegetative_bud_break_probability = 0.25;
+
308 shoot_parameters_primary.vegetative_bud_break_time = 1;
+
309 shoot_parameters_primary.base_roll = 90;
+
310 shoot_parameters_primary.internode_radius_initial = 0.001;
+
311 shoot_parameters_primary.phyllochron = 1;
+
312 shoot_parameters_primary.elongation_rate = 0.25;
+
313 shoot_parameters_primary.girth_growth_rate = 0.;
+
314 shoot_parameters_primary.child_internode_length_max = 0.03;
+
315 shoot_parameters_primary.child_internode_length_decay_rate = 0;
+
316 shoot_parameters_primary.child_insertion_angle_tip.uniformDistribution(50, 80);
+
317 shoot_parameters_primary.flowers_require_dormancy = false;
+
318 shoot_parameters_primary.growth_requires_dormancy = false;
+
319 shoot_parameters_primary.flower_bud_break_probability = 0.2;
+
320 shoot_parameters_primary.determinate_shoot_growth = false;
+
321 shoot_parameters_primary.max_nodes = 15;
+
322 shoot_parameters_primary.gravitropic_curvature = 20;
+
323 shoot_parameters_primary.tortuosity = 0;
+
324 shoot_parameters_primary.defineChildShootTypes({"secondary_bindweed"}, {1.f});
+
325
+
326 ShootParameters shoot_parameters_base = shoot_parameters_primary;
+
327 shoot_parameters_base.phytomer_parameters = phytomer_parameters_bindweed;
+
328 shoot_parameters_base.phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(137.5-10,137.5+10);
+
329 shoot_parameters_base.phytomer_parameters.petiole.petioles_per_internode = 0;
+
330 shoot_parameters_base.phytomer_parameters.internode.pitch = 0;
+
331 shoot_parameters_base.phytomer_parameters.petiole.pitch = 0;
+
332 shoot_parameters_base.vegetative_bud_break_probability = 1.0;
+
333 shoot_parameters_base.vegetative_bud_break_time = 1;
+
334 shoot_parameters_base.internode_radius_initial = 0.01;
+
335 shoot_parameters_base.phyllochron = 1;
+
336 shoot_parameters_base.elongation_rate = 0.25;
+
337 shoot_parameters_base.girth_growth_rate = 0.;
+
338 shoot_parameters_base.gravitropic_curvature = 0;
+
339 shoot_parameters_base.child_internode_length_max = 0.01;
+
340 shoot_parameters_base.child_internode_length_decay_rate = 0;
+
341 shoot_parameters_base.child_insertion_angle_tip = 90;
+
342 shoot_parameters_base.child_insertion_angle_decay_rate = 0;
+
343 shoot_parameters_base.internode_radius_initial = 0.001;
+
344 shoot_parameters_base.flowers_require_dormancy = false;
+
345 shoot_parameters_base.growth_requires_dormancy = false;
+
346 shoot_parameters_base.flower_bud_break_probability = 0.0;
+
347 shoot_parameters_base.max_nodes.uniformDistribution(3,5);
+
348 shoot_parameters_base.defineChildShootTypes({"primary_bindweed"},{1.f});
+
349
+
350 ShootParameters shoot_parameters_children = shoot_parameters_primary;
+
351 shoot_parameters_children.base_roll = 0;
+
352
+
353 defineShootType("base_bindweed", shoot_parameters_base);
+
354 defineShootType("primary_bindweed", shoot_parameters_primary);
+
355 defineShootType("secondary_bindweed", shoot_parameters_children);
+
356
+
357}
+
358
+
359uint PlantArchitecture::buildBindweedPlant(const helios::vec3 &base_position, float age) {
+
360
+
361 if (shoot_types.empty()) {
+
362 //automatically initialize bindweed plant shoots
+
363 initializeBindweedShoots();
+
364 }
+
365
+
366 uint plantID = addPlantInstance(base_position, age);
+
367
+
368 uint uID_stem = addBaseStemShoot(plantID, 3, make_AxisRotation(0, 0.f, 0.f), 0.001, 0.001, 1, 1, "base_bindweed");
+
369
+
370 breakPlantDormancy(plantID);
+
371
+
372 setPlantPhenologicalThresholds(plantID, 0, -1, 7, 1000, 5, 100);
+
373
+
374 return plantID;
+
375
+
376}
+
377
+
378void PlantArchitecture::initializeBeanShoots() {
+
379
+
380 PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
+
381
+
382 phytomer_parameters_trifoliate.internode.pitch = 20;
+
383 phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
+
384 phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
+
385 phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
+
386 phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.61, 0.68, 0.42);
+
387 phytomer_parameters_trifoliate.internode.length_segments = 5;
+
388
+
389 phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
+
390 phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(45,70);
+
391 phytomer_parameters_trifoliate.petiole.radius = 0.0015;
+
392 phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.06,0.08);
+
393 phytomer_parameters_trifoliate.petiole.taper = 0.25;
+
394 phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-250,450);
+
395 phytomer_parameters_trifoliate.petiole.color = phytomer_parameters_trifoliate.internode.color;
+
396 phytomer_parameters_trifoliate.petiole.length_segments = 5;
+
397 phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
+
398
+
399 phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
+
400 phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(0, 10);
+
401 phytomer_parameters_trifoliate.leaf.yaw = 10;
+
402 phytomer_parameters_trifoliate.leaf.roll = -15;
+
403 phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.5;
+
404 phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
+
405 phytomer_parameters_trifoliate.leaf.prototype_function = BeanLeafPrototype_trifoliate;
+
406 phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.06,0.08);
+
407 phytomer_parameters_trifoliate.leaf.subdivisions = 6;
+
408
+
409 phytomer_parameters_trifoliate.peduncle.length = 0.02;
+
410 phytomer_parameters_trifoliate.peduncle.radius = 0.0005;
+
411 phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 40);
+
412 phytomer_parameters_trifoliate.peduncle.roll = 90;
+
413 phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(-500, 500);
+
414 phytomer_parameters_trifoliate.peduncle.length_segments = 1;
+
415 phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
+
416
+
417 phytomer_parameters_trifoliate.inflorescence.flowers_per_rachis.uniformDistribution(1, 4);
+
418 phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.2;
+
419 phytomer_parameters_trifoliate.inflorescence.flower_arrangement_pattern = "opposite";
+
420 phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
+
421 phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
+
422 phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.0075;
+
423 phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = BeanFlowerPrototype;
+
424 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.04,0.05);
+
425 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = BeanFruitPrototype;
+
426 phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.8,1.0);
+
427
+
428 PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
+
429 phytomer_parameters_unifoliate.internode.pitch = 0;
+
430 phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 0;
+
431 phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
+
432 phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
+
433 phytomer_parameters_unifoliate.petiole.length = 0.005;
+
434 phytomer_parameters_unifoliate.petiole.radius = 0.0005;
+
435 phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(60,80);
+
436 phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
+
437 phytomer_parameters_unifoliate.leaf.prototype_scale = 0.01;
+
438 phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
+
439 phytomer_parameters_unifoliate.leaf.prototype_function = BeanLeafPrototype_unifoliate;
+
440
+
441 // ---- Shoot Parameters ---- //
+
442
+
443 ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
+
444 shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
+
445 shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = BeanPhytomerCreationFunction;
+
446
+
447 shoot_parameters_trifoliate.max_nodes = 20;
+
448 shoot_parameters_trifoliate.internode_radius_initial = 0.0005;
+
449 shoot_parameters_trifoliate.internode_radius_max = 0.002;
+
450 shoot_parameters_trifoliate.child_insertion_angle_tip.uniformDistribution(40,60);
+
451// shoot_parameters_trifoliate.child_insertion_angle_decay_rate = 0; (default)
+
452 shoot_parameters_trifoliate.child_internode_length_max = 0.015;
+
453// shoot_parameters_trifoliate.child_internode_length_min = 0.0; (default)
+
454// shoot_parameters_trifoliate.child_internode_length_decay_rate = 0; (default)
+
455 shoot_parameters_trifoliate.base_roll = 90;
+
456 shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
+
457 shoot_parameters_trifoliate.gravitropic_curvature = 300;
+
458
+
459 shoot_parameters_trifoliate.phyllochron = 1;
+
460// shoot_parameters_trifoliate.leaf_flush_count = 1; (default)
+
461 shoot_parameters_trifoliate.elongation_rate = 0.15;
+
462 shoot_parameters_trifoliate.girth_growth_rate = 0.0001;
+
463 shoot_parameters_trifoliate.vegetative_bud_break_time = 3;
+
464 shoot_parameters_trifoliate.vegetative_bud_break_probability = 0.25;
+
465 shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.8,1.0);
+
466 shoot_parameters_trifoliate.fruit_set_probability = 0.4;
+
467// shoot_parameters_trifoliate.flowers_require_dormancy = false; (default)
+
468// shoot_parameters_trifoliate.growth_requires_dormancy = false; (default)
+
469// shoot_parameters_trifoliate.determinate_shoot_growth = true; (default)
+
470
+
471 shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
+
472
+
473
+
474 ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
+
475 shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
+
476 shoot_parameters_unifoliate.max_nodes = 1;
+
477 shoot_parameters_unifoliate.vegetative_bud_break_probability = 0;
+
478 shoot_parameters_unifoliate.flower_bud_break_probability = 0;
+
479 shoot_parameters_unifoliate.child_insertion_angle_tip = 0;
+
480 shoot_parameters_unifoliate.child_insertion_angle_decay_rate = 0;
+
481 shoot_parameters_unifoliate.vegetative_bud_break_time = 1;
+
482 shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
+
483
+
484 defineShootType("unifoliate",shoot_parameters_unifoliate);
+
485 defineShootType("trifoliate",shoot_parameters_trifoliate);
+
486
+
487
+
488}
+
489
+
490uint PlantArchitecture::buildBeanPlant(const helios::vec3 &base_position, float age) {
+
491
+
492 if (shoot_types.empty()) {
+
493 //automatically initialize bean plant shoots
+
494 initializeBeanShoots();
+
495 }
+
496
+
497 uint plantID = addPlantInstance(base_position, age);
+
498
+
499 AxisRotation base_rotation = make_AxisRotation(context_ptr->randu(0.f, 0.05f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
+
500 uint uID_unifoliate = addBaseStemShoot(plantID, 1, base_rotation, 0.00025, 0.005, 0.01, 0.01, "unifoliate");
+
501
+
502 appendShoot(plantID, uID_unifoliate, 1, make_AxisRotation(0, 0, 0.5f*M_PI), shoot_types.at("trifoliate").internode_radius_initial.val(), shoot_types.at("trifoliate").child_internode_length_max.val(), 0.1, 0.1, "trifoliate");
+
503
+
504 breakPlantDormancy(plantID);
+
505
+
506 setPlantPhenologicalThresholds(plantID, 0, 15, 3, 3, 5, 100);
+
507
+
508 return plantID;
+
509
+
510}
+
511
+
512void PlantArchitecture::initializeCheeseweedShoots() {
+
513
+
514 // ---- Phytomer Parameters ---- //
+
515
+
516 PhytomerParameters phytomer_parameters_cheeseweed(context_ptr->getRandomGenerator());
+
517
+
518 phytomer_parameters_cheeseweed.internode.pitch = 0;
+
519 phytomer_parameters_cheeseweed.internode.phyllotactic_angle.uniformDistribution( 127.5f, 147.5);
+
520 phytomer_parameters_cheeseweed.internode.color = make_RGBcolor(0.60, 0.65, 0.40);
+
521 phytomer_parameters_cheeseweed.internode.length_segments = 1;
+
522
+
523 phytomer_parameters_cheeseweed.petiole.petioles_per_internode = 1;
+
524 phytomer_parameters_cheeseweed.petiole.pitch.uniformDistribution(45, 75);
+
525 phytomer_parameters_cheeseweed.petiole.radius = 0.00075;
+
526 phytomer_parameters_cheeseweed.petiole.length.uniformDistribution(0.02,0.06);
+
527 phytomer_parameters_cheeseweed.petiole.taper = 0;
+
528 phytomer_parameters_cheeseweed.petiole.curvature = -300;
+
529 phytomer_parameters_cheeseweed.petiole.length_segments = 5;
+
530 phytomer_parameters_cheeseweed.petiole.color = phytomer_parameters_cheeseweed.internode.color;
+
531
+
532 phytomer_parameters_cheeseweed.leaf.leaves_per_petiole = 1;
+
533 phytomer_parameters_cheeseweed.leaf.pitch.uniformDistribution(-30, 0);
+
534 phytomer_parameters_cheeseweed.leaf.yaw = 0;
+
535 phytomer_parameters_cheeseweed.leaf.roll = 0;
+
536 phytomer_parameters_cheeseweed.leaf.prototype_function = CheeseweedLeafPrototype;
+
537 phytomer_parameters_cheeseweed.leaf.prototype_scale = 0.035;
+
538
+
539 // ---- Shoot Parameters ---- //
+
540
+
541 ShootParameters shoot_parameters_base(context_ptr->getRandomGenerator());
+
542 shoot_parameters_base.phytomer_parameters = phytomer_parameters_cheeseweed;
+
543 shoot_parameters_base.vegetative_bud_break_probability = 0.2;
+
544 shoot_parameters_base.vegetative_bud_break_time = 3;
+
545 shoot_parameters_base.internode_radius_initial = 0.0005;
+
546 shoot_parameters_base.internode_radius_max = 0.001;
+
547 shoot_parameters_base.phyllochron = 1;
+
548 shoot_parameters_base.elongation_rate = 0.2;
+
549 shoot_parameters_base.girth_growth_rate = 0.0002;
+
550 shoot_parameters_base.gravitropic_curvature = 0;
+
551 shoot_parameters_base.child_internode_length_max = 0.0015;
+
552 shoot_parameters_base.child_internode_length_decay_rate = 0;
+
553 shoot_parameters_base.flowers_require_dormancy = false;
+
554 shoot_parameters_base.growth_requires_dormancy = false;
+
555 shoot_parameters_base.flower_bud_break_probability = 0.;
+
556 shoot_parameters_base.max_nodes = 8;
+
557
+
558 defineShootType("base", shoot_parameters_base);
+
559
+
560}
+
561
+
562uint PlantArchitecture::buildCheeseweedPlant(const helios::vec3 &base_position, float age) {
+
563
+
564 if (shoot_types.empty()) {
+
565 //automatically initialize cheeseweed plant shoots
+
566 initializeCheeseweedShoots();
+
567 }
+
568
+
569 uint plantID = addPlantInstance(base_position, age);
+
570
+
571 uint uID_stem = addBaseStemShoot(plantID, 1, make_AxisRotation(0, 0.f, 0.f), 0.0001, 0.0025, 0.1, 0.1, "base");
+
572
+
573 breakPlantDormancy(plantID);
+
574
+
575 setPlantPhenologicalThresholds(plantID, 0, 1000, 3, 1000, 5, 100);
+
576
+
577 return plantID;
+
578
+
579}
+
580
+
581void PlantArchitecture::initializeCowpeaShoots() {
+
582
+
583 // ---- Phytomer Parameters ---- //
+
584
+
585// PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
+
586//
+
587// phytomer_parameters_trifoliate.internode.pitch = 20;
+
588// phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
+
589// phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
+
590// phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
+
591// phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.61, 0.68, 0.42);
+
592// phytomer_parameters_trifoliate.internode.length_segments = 5;
+
593//
+
594// phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
+
595// phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(45,60);
+
596// phytomer_parameters_trifoliate.petiole.radius = 0.002;
+
597// phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.1,0.12);
+
598// phytomer_parameters_trifoliate.petiole.taper = 0.25;
+
599// phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-200,-50);
+
600// phytomer_parameters_trifoliate.petiole.color = phytomer_parameters_trifoliate.internode.color;
+
601// phytomer_parameters_trifoliate.petiole.length_segments = 5;
+
602// phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
+
603//
+
604// phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
+
605// phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(0, 10);
+
606// phytomer_parameters_trifoliate.leaf.yaw = 0;
+
607// phytomer_parameters_trifoliate.leaf.roll.normalDistribution(0, 10);
+
608// phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.25;
+
609// phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
+
610// phytomer_parameters_trifoliate.leaf.prototype_function = CowpeaLeafPrototype_trifoliate;
+
611// phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.09,0.1);
+
612//
+
613// phytomer_parameters_trifoliate.peduncle.length = 0.17;
+
614// phytomer_parameters_trifoliate.peduncle.radius = 0.0015;
+
615// phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 30);
+
616// phytomer_parameters_trifoliate.peduncle.roll = 90;
+
617// phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(50, 250);
+
618// phytomer_parameters_trifoliate.peduncle.length_segments = 6;
+
619// phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
+
620//
+
621// phytomer_parameters_trifoliate.inflorescence.flowers_per_rachis.uniformDistribution(2, 3);
+
622// phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.;
+
623// phytomer_parameters_trifoliate.inflorescence.flower_arrangement_pattern = "opposite";
+
624// phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
+
625// phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
+
626// phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.02;
+
627// phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = CowpeaFlowerPrototype;
+
628// phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.02,0.025);
+
629// phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = CowpeaFruitPrototype;
+
630// phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.,0.5);
+
631//
+
632// PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
+
633// phytomer_parameters_unifoliate.internode.pitch = 0;
+
634// phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 0;
+
635// phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
+
636// phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
+
637// phytomer_parameters_unifoliate.petiole.length = 0.0075;
+
638// phytomer_parameters_unifoliate.petiole.radius = 0.001;
+
639// phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(60,80);
+
640// phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
+
641// phytomer_parameters_unifoliate.leaf.prototype_scale = 0.02;
+
642// phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
+
643// phytomer_parameters_unifoliate.leaf.prototype_function = CowpeaLeafPrototype_unifoliate;
+
644//
+
645// // ---- Shoot Parameters ---- //
+
646//
+
647// ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
+
648// shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
+
649// shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = CowpeaPhytomerCreationFunction;
+
650// shoot_parameters_trifoliate.internode_radius_initial = 0.001;
+
651// shoot_parameters_trifoliate.phyllochron = 1;
+
652// shoot_parameters_trifoliate.base_roll = 90;
+
653// shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
+
654// shoot_parameters_trifoliate.elongation_rate = 0.2;
+
655// shoot_parameters_trifoliate.girth_growth_rate = 0.1;
+
656// shoot_parameters_trifoliate.gravitropic_curvature = 100;
+
657// shoot_parameters_trifoliate.vegetative_bud_break_time = 3;
+
658// shoot_parameters_trifoliate.child_internode_length_max = 0.04;
+
659// shoot_parameters_trifoliate.child_internode_length_decay_rate = 0;
+
660// shoot_parameters_trifoliate.child_internode_length_min = 0.0;
+
661// shoot_parameters_trifoliate.internode_radius_max = 0.002;
+
662// shoot_parameters_trifoliate.child_insertion_angle_tip.uniformDistribution(40,60);
+
663// shoot_parameters_trifoliate.child_insertion_angle_decay_rate = 0;
+
664// shoot_parameters_trifoliate.flowers_require_dormancy = false;
+
665// shoot_parameters_trifoliate.growth_requires_dormancy = false;
+
666// shoot_parameters_trifoliate.vegetative_bud_break_probability = 0.5;
+
667// shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.05,0.15);
+
668// shoot_parameters_trifoliate.fruit_set_probability = 0.5;
+
669// shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
+
670// shoot_parameters_trifoliate.max_nodes = 20;
+
671//
+
672// ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
+
673// shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
+
674// shoot_parameters_unifoliate.max_nodes = 1;
+
675// shoot_parameters_unifoliate.vegetative_bud_break_probability = 0;
+
676// shoot_parameters_unifoliate.flower_bud_break_probability = 0;
+
677// shoot_parameters_unifoliate.child_insertion_angle_tip = 0;
+
678// shoot_parameters_unifoliate.child_insertion_angle_decay_rate = 0;
+
679// shoot_parameters_unifoliate.vegetative_bud_break_time = 1;
+
680// shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
+
681//
+
682// defineShootType("unifoliate",shoot_parameters_unifoliate);
+
683// defineShootType("trifoliate",shoot_parameters_trifoliate);
+
684
+
685
+
686 PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
+
687
+
688 phytomer_parameters_trifoliate.internode.pitch = 20;
+
689 phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
+
690 phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
+
691 phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
+
692 phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.61, 0.68, 0.42);
+
693 phytomer_parameters_trifoliate.internode.length_segments = 5;
+
694
+
695 phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
+
696 phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(45,60);
+
697 phytomer_parameters_trifoliate.petiole.radius = 0.0015;
+
698 phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.08,0.1);
+
699 phytomer_parameters_trifoliate.petiole.taper = 0.25;
+
700 phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-200,-50);
+
701 phytomer_parameters_trifoliate.petiole.color = phytomer_parameters_trifoliate.internode.color;
+
702 phytomer_parameters_trifoliate.petiole.length_segments = 5;
+
703 phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
+
704
+
705 phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
+
706 phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(0, 10);
+
707 phytomer_parameters_trifoliate.leaf.yaw = 10;
+
708 phytomer_parameters_trifoliate.leaf.roll = -15;
+
709 phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.5;
+
710 phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
+
711 phytomer_parameters_trifoliate.leaf.prototype_function = CowpeaLeafPrototype_trifoliate;
+
712 phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.09,0.1);
+
713 phytomer_parameters_trifoliate.leaf.subdivisions = 6;
+
714
+
715 phytomer_parameters_trifoliate.peduncle.length = 0.17;
+
716 phytomer_parameters_trifoliate.peduncle.radius = 0.0015;
+
717 phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 30);
+
718 phytomer_parameters_trifoliate.peduncle.roll = 90;
+
719 phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(50, 250);
+
720 phytomer_parameters_trifoliate.peduncle.length_segments = 6;
+
721 phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
+
722
+
723 phytomer_parameters_trifoliate.inflorescence.flowers_per_rachis.uniformDistribution(1, 3);
+
724 phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.;
+
725 phytomer_parameters_trifoliate.inflorescence.flower_arrangement_pattern = "opposite";
+
726 phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
+
727 phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
+
728 phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.02;
+
729 phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = CowpeaFlowerPrototype;
+
730 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.02,0.025);
+
731 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = CowpeaFruitPrototype;
+
732 phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.,0.5);
+
733
+
734 PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
+
735 phytomer_parameters_unifoliate.internode.pitch = 0;
+
736 phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 0;
+
737 phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
+
738 phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
+
739 phytomer_parameters_unifoliate.petiole.length = 0.005;
+
740 phytomer_parameters_unifoliate.petiole.radius = 0.0005;
+
741 phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(60,80);
+
742 phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
+
743 phytomer_parameters_unifoliate.leaf.prototype_scale = 0.01;
+
744 phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
+
745 phytomer_parameters_unifoliate.leaf.prototype_function = CowpeaLeafPrototype_unifoliate;
+
746
+
747 // ---- Shoot Parameters ---- //
+
748
+
749 ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
+
750 shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
+
751 shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = CowpeaPhytomerCreationFunction;
+
752
+
753 shoot_parameters_trifoliate.max_nodes = 20;
+
754 shoot_parameters_trifoliate.internode_radius_initial = 0.001;
+
755 shoot_parameters_trifoliate.internode_radius_max = 0.002;
+
756 shoot_parameters_trifoliate.child_insertion_angle_tip.uniformDistribution(40,70);
+
757// shoot_parameters_trifoliate.child_insertion_angle_decay_rate = 0; (default)
+
758 shoot_parameters_trifoliate.child_internode_length_max = 0.03;
+
759// shoot_parameters_trifoliate.child_internode_length_min = 0.0; (default)
+
760// shoot_parameters_trifoliate.child_internode_length_decay_rate = 0; (default)
+
761 shoot_parameters_trifoliate.base_roll = 90;
+
762 shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
+
763 shoot_parameters_trifoliate.gravitropic_curvature = 200;
+
764
+
765 shoot_parameters_trifoliate.phyllochron = 1;
+
766// shoot_parameters_trifoliate.leaf_flush_count = 1; (default)
+
767 shoot_parameters_trifoliate.elongation_rate = 0.15;
+
768 shoot_parameters_trifoliate.girth_growth_rate = 0.0001;
+
769 shoot_parameters_trifoliate.vegetative_bud_break_time = 3;
+
770 shoot_parameters_trifoliate.vegetative_bud_break_probability = 0.5;
+
771 shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.1,0.2);
+
772 shoot_parameters_trifoliate.fruit_set_probability = 0.5;
+
773// shoot_parameters_trifoliate.flowers_require_dormancy = false; (default)
+
774// shoot_parameters_trifoliate.growth_requires_dormancy = false; (default)
+
775// shoot_parameters_trifoliate.determinate_shoot_growth = true; (default)
+
776
+
777 shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
+
778
+
779
+
780 ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
+
781 shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
+
782 shoot_parameters_unifoliate.max_nodes = 1;
+
783 shoot_parameters_unifoliate.vegetative_bud_break_probability = 0;
+
784 shoot_parameters_unifoliate.flower_bud_break_probability = 0;
+
785 shoot_parameters_unifoliate.child_insertion_angle_tip = 0;
+
786 shoot_parameters_unifoliate.child_insertion_angle_decay_rate = 0;
+
787 shoot_parameters_unifoliate.vegetative_bud_break_time = 1;
+
788 shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
+
789
+
790 defineShootType("unifoliate",shoot_parameters_unifoliate);
+
791 defineShootType("trifoliate",shoot_parameters_trifoliate);
+
792
+
793}
+
794
+
795uint PlantArchitecture::buildCowpeaPlant(const helios::vec3 &base_position, float age) {
+
796
+
797 if (shoot_types.empty()) {
+
798 //automatically initialize cowpea plant shoots
+
799 initializeCowpeaShoots();
+
800 }
+
801
+
802// uint plantID = addPlantInstance(base_position, age);
+
803//
+
804// AxisRotation base_rotation = make_AxisRotation(context_ptr->randu(0.f, 0.05f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
+
805// uint uID_unifoliate = addBaseStemShoot(plantID, 1, base_rotation, 0.0005, 0.02, 0.1, 0.1, "unifoliate");
+
806//
+
807// appendShoot(plantID, uID_unifoliate, 1, make_AxisRotation(0, 0, 0.5f*M_PI), shoot_types.at("trifoliate").internode_radius_initial.val(), shoot_types.at("trifoliate").child_internode_length_max.val(), 0.1, 0.1, "trifoliate");
+
808//
+
809// breakPlantDormancy(plantID);
+
810//
+
811// setPlantPhenologicalThresholds(plantID, 0, 16, 1, 1, 1, 100);
+
812
+
813 uint plantID = addPlantInstance(base_position, age);
+
814
+
815 AxisRotation base_rotation = make_AxisRotation(context_ptr->randu(0.f, 0.05f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
+
816 uint uID_unifoliate = addBaseStemShoot(plantID, 1, base_rotation, 0.0005, 0.02, 0.01, 0.01, "unifoliate");
+
817
+
818 appendShoot(plantID, uID_unifoliate, 1, make_AxisRotation(0, 0, 0.5f*M_PI), shoot_types.at("trifoliate").internode_radius_initial.val(), shoot_types.at("trifoliate").child_internode_length_max.val(), 0.1, 0.1, "trifoliate");
+
819
+
820 breakPlantDormancy(plantID);
+
821
+
822 setPlantPhenologicalThresholds(plantID, 0, 16, 3, 3, 5, 100);
+
823
+
824 return plantID;
+
825
+
826}
+
827
+
828void PlantArchitecture::initializePuncturevineShoots() {
+
829
+
830 // ---- Phytomer Parameters ---- //
+
831
+
832 PhytomerParameters phytomer_parameters_puncturevine(context_ptr->getRandomGenerator());
+
833
+
834 phytomer_parameters_puncturevine.internode.pitch.uniformDistribution(0,15);
+
835 phytomer_parameters_puncturevine.internode.phyllotactic_angle = 180.f;
+
836 phytomer_parameters_puncturevine.internode.color = make_RGBcolor(0.55, 0.52, 0.39);
+
837 phytomer_parameters_puncturevine.internode.length_segments = 1;
+
838
+
839 phytomer_parameters_puncturevine.petiole.petioles_per_internode = 1;
+
840 phytomer_parameters_puncturevine.petiole.pitch.uniformDistribution(80, 100);
+
841 phytomer_parameters_puncturevine.petiole.radius = 0.0003;
+
842 phytomer_parameters_puncturevine.petiole.length = 0.025;
+
843 phytomer_parameters_puncturevine.petiole.taper = 0;
+
844 phytomer_parameters_puncturevine.petiole.curvature = 0;
+
845 phytomer_parameters_puncturevine.petiole.color = phytomer_parameters_puncturevine.internode.color;
+
846 phytomer_parameters_puncturevine.petiole.length_segments = 1;
+
847
+
848 phytomer_parameters_puncturevine.leaf.leaves_per_petiole = 11;
+
849 phytomer_parameters_puncturevine.leaf.pitch.uniformDistribution(-10,10);
+
850 phytomer_parameters_puncturevine.leaf.yaw = 30;
+
851 phytomer_parameters_puncturevine.leaf.roll.uniformDistribution(-5,5);
+
852 phytomer_parameters_puncturevine.leaf.prototype_function = PuncturevineLeafPrototype;
+
853 phytomer_parameters_puncturevine.leaf.prototype_scale = 0.008;
+
854 phytomer_parameters_puncturevine.leaf.leaflet_offset = 0.15;
+
855 phytomer_parameters_puncturevine.leaf.leaflet_scale = 1;
+
856 phytomer_parameters_puncturevine.leaf.subdivisions = 4;
+
857
+
858 phytomer_parameters_puncturevine.peduncle.length = 0.001;
+
859 phytomer_parameters_puncturevine.inflorescence.flowers_per_rachis = 1;
+
860 phytomer_parameters_puncturevine.inflorescence.pitch = -90.f;
+
861 phytomer_parameters_puncturevine.inflorescence.flower_prototype_function = PuncturevineFlowerPrototype;
+
862 phytomer_parameters_puncturevine.inflorescence.flower_prototype_scale = 0.006;
+
863
+
864 // ---- Shoot Parameters ---- //
+
865
+
866 ShootParameters shoot_parameters_primary(context_ptr->getRandomGenerator());
+
867 shoot_parameters_primary.phytomer_parameters = phytomer_parameters_puncturevine;
+
868 shoot_parameters_primary.vegetative_bud_break_probability = 0.3;
+
869 shoot_parameters_primary.vegetative_bud_break_time = 3;
+
870 shoot_parameters_primary.base_roll = 90;
+
871 shoot_parameters_primary.internode_radius_initial = 0.001;
+
872 shoot_parameters_primary.phyllochron = 1;
+
873 shoot_parameters_primary.elongation_rate = 0.2;
+
874 shoot_parameters_primary.girth_growth_rate = 0.;
+
875 shoot_parameters_primary.child_internode_length_max = 0.02;
+
876 shoot_parameters_primary.child_internode_length_decay_rate = 0;
+
877 shoot_parameters_primary.child_insertion_angle_tip.uniformDistribution(50, 80);
+
878 shoot_parameters_primary.flowers_require_dormancy = false;
+
879 shoot_parameters_primary.growth_requires_dormancy = false;
+
880 shoot_parameters_primary.flower_bud_break_probability = 0.2;
+
881 shoot_parameters_primary.determinate_shoot_growth = false;
+
882 shoot_parameters_primary.max_nodes = 15;
+
883 shoot_parameters_primary.gravitropic_curvature = 20;
+
884 shoot_parameters_primary.tortuosity = 0;
+
885 shoot_parameters_primary.defineChildShootTypes({"secondary_puncturevine"}, {1.f});
+
886
+
887 ShootParameters shoot_parameters_base = shoot_parameters_primary;
+
888 shoot_parameters_base.phytomer_parameters = phytomer_parameters_puncturevine;
+
889 shoot_parameters_base.phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(137.5-10,137.5+10);
+
890 shoot_parameters_base.phytomer_parameters.petiole.petioles_per_internode = 0;
+
891 shoot_parameters_base.phytomer_parameters.internode.pitch = 0;
+
892 shoot_parameters_base.phytomer_parameters.petiole.pitch = 0;
+
893 shoot_parameters_base.vegetative_bud_break_probability = 1;
+
894 shoot_parameters_base.vegetative_bud_break_time = 1;
+
895 shoot_parameters_base.internode_radius_initial = 0.001;
+
896 shoot_parameters_base.phyllochron = 1;
+
897 shoot_parameters_base.elongation_rate = 0.25;
+
898 shoot_parameters_base.girth_growth_rate = 0.;
+
899 shoot_parameters_base.gravitropic_curvature = 0;
+
900 shoot_parameters_base.child_internode_length_max = 0.01;
+
901 shoot_parameters_base.child_internode_length_decay_rate = 0;
+
902 shoot_parameters_base.child_insertion_angle_tip = 90;
+
903 shoot_parameters_base.child_insertion_angle_decay_rate = 0;
+
904 shoot_parameters_base.internode_radius_initial = 0.0005;
+
905 shoot_parameters_base.flowers_require_dormancy = false;
+
906 shoot_parameters_base.growth_requires_dormancy = false;
+
907 shoot_parameters_base.flower_bud_break_probability = 0.0;
+
908 shoot_parameters_base.max_nodes.uniformDistribution(3,5);
+
909 shoot_parameters_base.defineChildShootTypes({"primary_puncturevine"},{1.f});
+
910
+
911 ShootParameters shoot_parameters_children = shoot_parameters_primary;
+
912 shoot_parameters_children.base_roll = 0;
+
913
+
914 defineShootType("base_puncturevine", shoot_parameters_base);
+
915 defineShootType("primary_puncturevine", shoot_parameters_primary);
+
916 defineShootType("secondary_puncturevine", shoot_parameters_children);
+
917
+
918}
+
919
+
920uint PlantArchitecture::buildPuncturevinePlant(const helios::vec3 &base_position, float age) {
+
921
+
922 if (shoot_types.empty()) {
+
923 //automatically initialize puncturevine plant shoots
+
924 initializePuncturevineShoots();
+
925 }
+
926
+
927 uint plantID = addPlantInstance(base_position, age);
+
928
+
929 uint uID_stem = addBaseStemShoot(plantID, 3, make_AxisRotation(0, 0.f, 0.f), 0.001, 0.001, 1, 1, "base_puncturevine");
+
930
+
931 breakPlantDormancy(plantID);
+
932
+
933 setPlantPhenologicalThresholds(plantID, 0, -1, 7, 1000, 5, 100);
+
934
+
935 return plantID;
+
936
+
937}
+
938
+
939void PlantArchitecture::initializeRedbudShoots() {
+
940
+
941 // ---- Phytomer Parameters ---- //
+
942
+
943 PhytomerParameters phytomer_parameters_redbud(context_ptr->getRandomGenerator());
+
944
+
945 phytomer_parameters_redbud.internode.pitch = 15;
+
946 phytomer_parameters_redbud.internode.phyllotactic_angle = 180.f;
+
947 phytomer_parameters_redbud.internode.color = make_RGBcolor(0.55, 0.52, 0.39);
+
948 phytomer_parameters_redbud.internode.length_segments = 1;
+
949
+
950 phytomer_parameters_redbud.petiole.petioles_per_internode = 1;
+
951 phytomer_parameters_redbud.petiole.pitch.uniformDistribution(80, 100);
+
952 phytomer_parameters_redbud.petiole.radius = 0.0003;
+
953 phytomer_parameters_redbud.petiole.length = 0.025;
+
954 phytomer_parameters_redbud.petiole.taper = 0;
+
955 phytomer_parameters_redbud.petiole.curvature = 0;
+
956 phytomer_parameters_redbud.petiole.length_segments = 1;
+
957
+
958 phytomer_parameters_redbud.leaf.leaves_per_petiole = 11;
+
959 phytomer_parameters_redbud.leaf.pitch.uniformDistribution(-10, 10);
+
960 phytomer_parameters_redbud.leaf.yaw = 30;
+
961 phytomer_parameters_redbud.leaf.roll.uniformDistribution(-5, 5);
+
962 phytomer_parameters_redbud.leaf.prototype_function = RedbudLeafPrototype;
+
963 phytomer_parameters_redbud.leaf.prototype_scale = 0.008;
+
964 phytomer_parameters_redbud.leaf.leaflet_offset = 0.15;
+
965 phytomer_parameters_redbud.leaf.leaflet_scale = 1;
+
966 phytomer_parameters_redbud.leaf.subdivisions = 4;
+
967
+
968 phytomer_parameters_redbud.peduncle.length = 0.001;
+
969 phytomer_parameters_redbud.inflorescence.flowers_per_rachis = 1;
+
970 phytomer_parameters_redbud.inflorescence.pitch = -90.f;
+
971 phytomer_parameters_redbud.inflorescence.flower_prototype_function = RedbudFlowerPrototype;
+
972 phytomer_parameters_redbud.inflorescence.flower_prototype_scale = 0.006;
+
973
+
974 phytomer_parameters_redbud.phytomer_creation_function = RedbudPhytomerCreationFunction;
+
975
+
976 // ---- Shoot Parameters ---- //
+
977
+
978 ShootParameters shoot_parameters_base(context_ptr->getRandomGenerator());
+
979 shoot_parameters_base.phytomer_parameters = phytomer_parameters_redbud;
+
980 shoot_parameters_base.phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(137.5-10,137.5+10);
+
981 shoot_parameters_base.phytomer_parameters.petiole.petioles_per_internode = 0;
+
982 shoot_parameters_base.phytomer_parameters.internode.pitch = 0;
+
983 shoot_parameters_base.phytomer_parameters.petiole.pitch = 0;
+
984 shoot_parameters_base.vegetative_bud_break_probability = 1.0;
+
985 shoot_parameters_base.vegetative_bud_break_time = 1;
+
986 shoot_parameters_base.internode_radius_initial = 0.001;
+
987 shoot_parameters_base.phyllochron = 1;
+
988 shoot_parameters_base.elongation_rate = 0.25;
+
989 shoot_parameters_base.girth_growth_rate = 0.;
+
990 shoot_parameters_base.gravitropic_curvature = 0;
+
991 shoot_parameters_base.child_internode_length_max = 0.01;
+
992 shoot_parameters_base.child_internode_length_decay_rate = 0;
+
993 shoot_parameters_base.child_insertion_angle_tip = 90;
+
994 shoot_parameters_base.child_insertion_angle_decay_rate = 0;
+
995 shoot_parameters_base.internode_radius_initial = 0.0005;
+
996 shoot_parameters_base.flowers_require_dormancy = false;
+
997 shoot_parameters_base.growth_requires_dormancy = false;
+
998 shoot_parameters_base.flower_bud_break_probability = 0.0;
+
999 shoot_parameters_base.max_nodes.uniformDistribution(3,5);
+
1000// shoot_parameters_base.defineChildShootTypes({"proleptic_redbud"},{1.f});
+
1001
+
1002 defineShootType("trunk_redbud", shoot_parameters_base);
+
1003
+
1004}
+
1005
+
1006uint PlantArchitecture::buildRedbudPlant(const helios::vec3 &base_position, float age) {
+
1007
+
1008 if (shoot_types.empty()) {
+
1009 //automatically initialize redbud plant shoots
+
1010 initializeRedbudShoots();
+
1011 }
+
1012
+
1013 uint plantID = addPlantInstance(base_position, age);
+
1014
+
1015 uint uID_stem = addBaseStemShoot(plantID, 3, make_AxisRotation(0, 0.f, 0.f), 0.001, 0.001, 1, 1, "base_puncturevine");
+
1016
+
1017 breakPlantDormancy(plantID);
+
1018
+
1019 setPlantPhenologicalThresholds(plantID, 0, -1, 3, 1000, 5, 100);
+
1020
+
1021 return plantID;
+
1022
+
1023}
+
1024
+
1025void PlantArchitecture::initializeSorghumShoots() {
+
1026
+
1027 // ---- Phytomer Parameters ---- //
+
1028
+
1029 PhytomerParameters phytomer_parameters_sorghum(context_ptr->getRandomGenerator());
+
1030
+
1031 phytomer_parameters_sorghum.internode.pitch = 0.;
+
1032 phytomer_parameters_sorghum.internode.phyllotactic_angle = 180;
+
1033 phytomer_parameters_sorghum.internode.color = make_RGBcolor(0.45,0.55,0.42);
+
1034 phytomer_parameters_sorghum.internode.length_segments = 2;
+
1035
+
1036 phytomer_parameters_sorghum.petiole.petioles_per_internode = 1;
+
1037 phytomer_parameters_sorghum.petiole.pitch = 0.1;
+
1038 phytomer_parameters_sorghum.petiole.radius = 0.0;
+
1039 phytomer_parameters_sorghum.petiole.length = 0.01;
+
1040 phytomer_parameters_sorghum.petiole.taper = 0;
+
1041 phytomer_parameters_sorghum.petiole.curvature = 0;
+
1042 phytomer_parameters_sorghum.petiole.length_segments = 1;
+
1043
+
1044 phytomer_parameters_sorghum.leaf.leaves_per_petiole = 1;
+
1045 phytomer_parameters_sorghum.leaf.pitch.uniformDistribution(-40,-20);
+
1046 phytomer_parameters_sorghum.leaf.yaw = 0;
+
1047 phytomer_parameters_sorghum.leaf.roll = 0;
+
1048 phytomer_parameters_sorghum.leaf.prototype_function = SorghumLeafPrototype;
+
1049 phytomer_parameters_sorghum.leaf.prototype_scale = 0.3;
+
1050 phytomer_parameters_sorghum.leaf.subdivisions = 50;
+
1051
+
1052 phytomer_parameters_sorghum.peduncle.length = 0.001;
+
1053
+
1054 phytomer_parameters_sorghum.inflorescence.flowers_per_rachis = 1;
+
1055 phytomer_parameters_sorghum.inflorescence.pitch = 0;
+
1056 phytomer_parameters_sorghum.inflorescence.roll = 0;
+
1057 phytomer_parameters_sorghum.inflorescence.fruit_prototype_scale = 0.3;
+
1058 phytomer_parameters_sorghum.inflorescence.fruit_prototype_function = SorghumPaniclePrototype;
+
1059
+
1060 phytomer_parameters_sorghum.phytomer_creation_function = SorghumPhytomerCreationFunction;
+
1061
+
1062 // ---- Shoot Parameters ---- //
+
1063
+
1064 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
+
1065 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_sorghum;
+
1066 shoot_parameters_mainstem.vegetative_bud_break_probability = 0;
+
1067 shoot_parameters_mainstem.internode_radius_initial = 0.001;
+
1068 shoot_parameters_mainstem.phyllochron = 1;
+
1069 shoot_parameters_mainstem.elongation_rate = 0.25;
+
1070 shoot_parameters_mainstem.girth_growth_rate = 0.00075;
+
1071 shoot_parameters_mainstem.internode_radius_max = 0.007;
+
1072 shoot_parameters_mainstem.gravitropic_curvature = 10;
+
1073 shoot_parameters_mainstem.child_internode_length_max = 0.075;
+
1074 shoot_parameters_mainstem.child_internode_length_decay_rate = 0;
+
1075 shoot_parameters_mainstem.flowers_require_dormancy = false;
+
1076 shoot_parameters_mainstem.growth_requires_dormancy = false;
+
1077 shoot_parameters_mainstem.determinate_shoot_growth = false;
+
1078 shoot_parameters_mainstem.flower_bud_break_probability = 1.0;
+
1079 shoot_parameters_mainstem.fruit_set_probability = 1.0;
+
1080 shoot_parameters_mainstem.defineChildShootTypes({"mainstem"},{1.0});
+
1081 shoot_parameters_mainstem.max_nodes = 8;
+
1082
+
1083 defineShootType("mainstem",shoot_parameters_mainstem);
+
1084
+
1085}
+
1086
+
1087uint PlantArchitecture::buildSorghumPlant(const helios::vec3 &base_position, float age) {
+
1088
+
1089 if (shoot_types.empty()) {
+
1090 //automatically initialize sorghum plant shoots
+
1091 initializeSorghumShoots();
+
1092 }
+
1093
+
1094 uint plantID = addPlantInstance(base_position, age);
+
1095
+
1096 uint uID_stem = addBaseStemShoot(plantID, 1, make_AxisRotation(context_ptr->randu(0.f, 0.01f * M_PI), 0.f*context_ptr->randu(0.f, 2.f * M_PI), 0.25f * M_PI), 0.001, 0.03, 0.01, 0.01, "mainstem");
+
1097
+
1098 breakPlantDormancy(plantID);
+
1099
+
1100 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 2, 5, 100);
+
1101
+
1102 return plantID;
+
1103
+
1104}
+
1105
+
1106void PlantArchitecture::initializeSoybeanShoots() {
+
1107
+
1108 PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
+
1109
+
1110 phytomer_parameters_trifoliate.internode.pitch = 20;
+
1111 phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
+
1112 phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
+
1113 phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
+
1114 phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.61, 0.68, 0.42);
+
1115 phytomer_parameters_trifoliate.internode.length_segments = 5;
+
1116
+
1117 phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
+
1118 phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(45,70);
+
1119 phytomer_parameters_trifoliate.petiole.radius = 0.0015;
+
1120 phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.06,0.08);
+
1121 phytomer_parameters_trifoliate.petiole.taper = 0.25;
+
1122 phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-250,450);
+
1123 phytomer_parameters_trifoliate.petiole.color = phytomer_parameters_trifoliate.internode.color;
+
1124 phytomer_parameters_trifoliate.petiole.length_segments = 5;
+
1125 phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
+
1126
+
1127 phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
+
1128 phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(-10, 10);
+
1129 phytomer_parameters_trifoliate.leaf.yaw = 10;
+
1130 phytomer_parameters_trifoliate.leaf.roll = -15;
+
1131 phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.5;
+
1132 phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
+
1133 phytomer_parameters_trifoliate.leaf.prototype_function = SoybeanLeafPrototype_trifoliate;
+
1134 phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.06,0.08);
+
1135 phytomer_parameters_trifoliate.leaf.subdivisions = 6;
+
1136
+
1137 phytomer_parameters_trifoliate.peduncle.length = 0.005;
+
1138 phytomer_parameters_trifoliate.peduncle.radius = 0.0005;
+
1139 phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 40);
+
1140 phytomer_parameters_trifoliate.peduncle.roll = 90;
+
1141 phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(-500, 500);
+
1142 phytomer_parameters_trifoliate.peduncle.length_segments = 1;
+
1143 phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
+
1144
+
1145 phytomer_parameters_trifoliate.inflorescence.flowers_per_rachis.uniformDistribution(1, 4);
+
1146 phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.2;
+
1147 phytomer_parameters_trifoliate.inflorescence.flower_arrangement_pattern = "opposite";
+
1148 phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
+
1149 phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
+
1150 phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.0075;
+
1151 phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = SoybeanFlowerPrototype;
+
1152 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.04,0.05);
+
1153 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = SoybeanFruitPrototype;
+
1154 phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.8,1.0);
+
1155
+
1156 PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
+
1157 phytomer_parameters_unifoliate.internode.pitch = 0;
+
1158 phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 0;
+
1159 phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
+
1160 phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
+
1161 phytomer_parameters_unifoliate.petiole.length = 0.005;
+
1162 phytomer_parameters_unifoliate.petiole.radius = 0.0005;
+
1163 phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(60,80);
+
1164 phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
+
1165 phytomer_parameters_unifoliate.leaf.prototype_scale = 0.01;
+
1166 phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
+
1167 phytomer_parameters_unifoliate.leaf.prototype_function = SoybeanLeafPrototype_unifoliate;
+
1168
+
1169 // ---- Shoot Parameters ---- //
+
1170
+
1171 ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
+
1172 shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
+
1173 shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = SoybeanPhytomerCreationFunction;
+
1174
+
1175 shoot_parameters_trifoliate.max_nodes = 20;
+
1176 shoot_parameters_trifoliate.internode_radius_initial = 0.0005;
+
1177 shoot_parameters_trifoliate.internode_radius_max = 0.002;
+
1178 shoot_parameters_trifoliate.child_insertion_angle_tip.uniformDistribution(40,60);
+
1179// shoot_parameters_trifoliate.child_insertion_angle_decay_rate = 0; (default)
+
1180 shoot_parameters_trifoliate.child_internode_length_max = 0.01;
+
1181// shoot_parameters_trifoliate.child_internode_length_min = 0.0; (default)
+
1182// shoot_parameters_trifoliate.child_internode_length_decay_rate = 0; (default)
+
1183 shoot_parameters_trifoliate.base_roll = 90;
+
1184 shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
+
1185 shoot_parameters_trifoliate.gravitropic_curvature = 300;
+
1186
+
1187 shoot_parameters_trifoliate.phyllochron = 1;
+
1188// shoot_parameters_trifoliate.leaf_flush_count = 1; (default)
+
1189 shoot_parameters_trifoliate.elongation_rate = 0.15;
+
1190 shoot_parameters_trifoliate.girth_growth_rate = 0.0001;
+
1191 shoot_parameters_trifoliate.vegetative_bud_break_time = 3;
+
1192 shoot_parameters_trifoliate.vegetative_bud_break_probability = 0.35;
+
1193 shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.8,1.0);
+
1194 shoot_parameters_trifoliate.fruit_set_probability = 0.4;
+
1195// shoot_parameters_trifoliate.flowers_require_dormancy = false; (default)
+
1196// shoot_parameters_trifoliate.growth_requires_dormancy = false; (default)
+
1197// shoot_parameters_trifoliate.determinate_shoot_growth = true; (default)
+
1198
+
1199 shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
+
1200
+
1201
+
1202 ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
+
1203 shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
+
1204 shoot_parameters_unifoliate.max_nodes = 1;
+
1205 shoot_parameters_unifoliate.vegetative_bud_break_probability = 0;
+
1206 shoot_parameters_unifoliate.flower_bud_break_probability = 0;
+
1207 shoot_parameters_unifoliate.child_insertion_angle_tip = 0;
+
1208 shoot_parameters_unifoliate.child_insertion_angle_decay_rate = 0;
+
1209 shoot_parameters_unifoliate.vegetative_bud_break_time = 1;
+
1210 shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
+
1211
+
1212 defineShootType("unifoliate",shoot_parameters_unifoliate);
+
1213 defineShootType("trifoliate",shoot_parameters_trifoliate);
+
1214
+
1215
+
1216}
+
1217
+
1218uint PlantArchitecture::buildSoybeanPlant(const helios::vec3 &base_position, float age) {
+
1219
+
1220 if (shoot_types.empty()) {
+
1221 //automatically initialize bean plant shoots
+
1222 initializeSoybeanShoots();
+
1223 }
+
1224
+
1225 uint plantID = addPlantInstance(base_position, age);
+
1226
+
1227 AxisRotation base_rotation = make_AxisRotation(context_ptr->randu(0.f, 0.05f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
+
1228 uint uID_unifoliate = addBaseStemShoot(plantID, 1, base_rotation, 0.0002, 0.01, 0.5, 0.5, "unifoliate");
+
1229
+
1230 appendShoot(plantID, uID_unifoliate, 1, make_AxisRotation(0, 0, 0.5f*M_PI), shoot_types.at("trifoliate").internode_radius_initial.val(), shoot_types.at("trifoliate").child_internode_length_max.val(), 1, 1, "trifoliate");
+
1231
+
1232 breakPlantDormancy(plantID);
+
1233
+
1234 setPlantPhenologicalThresholds(plantID, 0, 15, 3, 3, 5, 100);
+
1235
+
1236 return plantID;
+
1237
+
1238}
+
1239
+
1240void PlantArchitecture::initializeStrawberryShoots() {
+
1241
+
1242 // ---- Phytomer Parameters ---- //
+
1243
+
1244 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
+
1245
+
1246 phytomer_parameters.internode.pitch = 10;
+
1247 phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(80,100);
+
1248 phytomer_parameters.internode.color = make_RGBcolor(0.38, 0.48, 0.1);
+
1249 phytomer_parameters.internode.length_segments = 1;
+
1250
+
1251 phytomer_parameters.petiole.petioles_per_internode = 1;
+
1252 phytomer_parameters.petiole.pitch.uniformDistribution(10,45);
+
1253 phytomer_parameters.petiole.radius = 0.002;
+
1254 phytomer_parameters.petiole.length = 0.2;
+
1255 phytomer_parameters.petiole.taper = 0.5;
+
1256 phytomer_parameters.petiole.curvature.uniformDistribution(-200,100);
+
1257 phytomer_parameters.petiole.color = make_RGBcolor(0.60, 0.69, 0.2);
+
1258 phytomer_parameters.petiole.length_segments = 5;
+
1259
+
1260 phytomer_parameters.leaf.leaves_per_petiole = 3;
+
1261 phytomer_parameters.leaf.pitch.uniformDistribution(-30,-15);
+
1262 phytomer_parameters.leaf.yaw = 20;
+
1263 phytomer_parameters.leaf.roll = -30;
+
1264 phytomer_parameters.leaf.leaflet_offset = 0.01;
+
1265 phytomer_parameters.leaf.leaflet_scale = 1.0;
+
1266 phytomer_parameters.leaf.prototype_function = StrawberryLeafPrototype;
+
1267 phytomer_parameters.leaf.prototype_scale = 0.1;
+
1268 phytomer_parameters.leaf.subdivisions = 6;
+
1269
+
1270 phytomer_parameters.peduncle.length = 0.15;
+
1271 phytomer_parameters.peduncle.radius = 0.0005;
+
1272 phytomer_parameters.peduncle.pitch = 35;
+
1273 phytomer_parameters.peduncle.roll = 0;
+
1274 phytomer_parameters.peduncle.curvature = -200;
+
1275 phytomer_parameters.peduncle.length_segments = 5;
+
1276 phytomer_parameters.peduncle.radial_subdivisions = 6;
+
1277
+
1278 phytomer_parameters.inflorescence.flowers_per_rachis.uniformDistribution(1,3);
+
1279 phytomer_parameters.inflorescence.flower_offset = 0.2;
+
1280 phytomer_parameters.inflorescence.flower_arrangement_pattern = "alternate";
+
1281 phytomer_parameters.inflorescence.pitch = 70;
+
1282 phytomer_parameters.inflorescence.roll = 90;
+
1283 phytomer_parameters.inflorescence.flower_prototype_scale = 0.02;
+
1284 phytomer_parameters.inflorescence.flower_prototype_function = StrawberryFlowerPrototype;
+
1285 phytomer_parameters.inflorescence.fruit_prototype_scale = 0.04;
+
1286 phytomer_parameters.inflorescence.fruit_prototype_function = StrawberryFruitPrototype;
+
1287 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction = 0.65;
+
1288
+
1289 // ---- Shoot Parameters ---- //
+
1290
+
1291 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
+
1292 shoot_parameters.phytomer_parameters = phytomer_parameters;
+
1293 shoot_parameters.phytomer_parameters.phytomer_creation_function = TomatoPhytomerCreationFunction;
+
1294
+
1295 shoot_parameters.max_nodes = 15;
+
1296 shoot_parameters.internode_radius_initial = 0.0005;
+
1297 shoot_parameters.internode_radius_max = 0.004;
+
1298 shoot_parameters.child_insertion_angle_tip = 40;
+
1299 shoot_parameters.child_insertion_angle_decay_rate = 0;
+
1300 shoot_parameters.child_internode_length_max = 0.005;
+
1301 shoot_parameters.child_internode_length_decay_rate = 0;
+
1302 shoot_parameters.child_internode_length_min = 0.0;
+
1303 shoot_parameters.base_roll = 90;
+
1304 shoot_parameters.base_yaw.uniformDistribution(-20,20);
+
1305 shoot_parameters.gravitropic_curvature.uniformDistribution(-20,0);
+
1306 shoot_parameters.tortuosity = 0;
+
1307
+
1308 shoot_parameters.phyllochron = 1;
+
1309 shoot_parameters.leaf_flush_count = 1;
+
1310 shoot_parameters.elongation_rate = 0.1;
+
1311 shoot_parameters.girth_growth_rate = 0.00015;
+
1312 shoot_parameters.vegetative_bud_break_time = 3;
+
1313 shoot_parameters.vegetative_bud_break_probability = 0.25;
+
1314 shoot_parameters.flower_bud_break_probability = 1;
+
1315 shoot_parameters.fruit_set_probability = 0.5;
+
1316 shoot_parameters.flowers_require_dormancy = false;
+
1317 shoot_parameters.growth_requires_dormancy = false;
+
1318 shoot_parameters.determinate_shoot_growth = true;
+
1319
+
1320 shoot_parameters.defineChildShootTypes({"mainstem"},{1.0});
+
1321
+
1322 defineShootType("mainstem",shoot_parameters);
+
1323
+
1324}
+
1325
+
1326uint PlantArchitecture::buildStrawberryPlant(const helios::vec3 &base_position, float age) {
+
1327
+
1328 if (shoot_types.empty()) {
+
1329 //automatically initialize strawberry plant shoots
+
1330 initializeStrawberryShoots();
+
1331 }
+
1332
+
1333 uint plantID = addPlantInstance(base_position, age);
+
1334
+
1335 AxisRotation base_rotation = make_AxisRotation(0, context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
+
1336 uint uID_stem = addBaseStemShoot(plantID, 1, base_rotation, 0.0005, 0.003, 0.01, 0.01, "mainstem");
+
1337
+
1338 breakPlantDormancy(plantID);
+
1339
+
1340 setPlantPhenologicalThresholds(plantID, 0, -1, 14, 3, 3, 100);
+
1341
+
1342 return plantID;
+
1343
+
1344}
+
1345
+
1346void PlantArchitecture::initializeSugarbeetShoots() {
+
1347
+
1348 // ---- Phytomer Parameters ---- //
+
1349
+
1350 PhytomerParameters phytomer_parameters_sugarbeet(context_ptr->getRandomGenerator());
+
1351
+
1352 phytomer_parameters_sugarbeet.internode.pitch = 0;
+
1353 phytomer_parameters_sugarbeet.internode.phyllotactic_angle = 137.5;
+
1354 phytomer_parameters_sugarbeet.internode.color = make_RGBcolor(0.44,0.58,0.19);
+
1355 phytomer_parameters_sugarbeet.internode.length_segments = 2;
+
1356
+
1357 phytomer_parameters_sugarbeet.petiole.petioles_per_internode = 1;
+
1358 phytomer_parameters_sugarbeet.petiole.pitch.uniformDistribution(0,40);
+
1359 phytomer_parameters_sugarbeet.petiole.radius = 0.0025;
+
1360 phytomer_parameters_sugarbeet.petiole.length.uniformDistribution(0.07,0.1);
+
1361 phytomer_parameters_sugarbeet.petiole.taper = 0.6;
+
1362 phytomer_parameters_sugarbeet.petiole.curvature.uniformDistribution(-300,100);
+
1363 phytomer_parameters_sugarbeet.petiole.color = phytomer_parameters_sugarbeet.internode.color;
+
1364 phytomer_parameters_sugarbeet.petiole.length_segments = 8;
+
1365
+
1366 phytomer_parameters_sugarbeet.leaf.leaves_per_petiole = 1;
+
1367 phytomer_parameters_sugarbeet.leaf.pitch.uniformDistribution(-10,0);
+
1368 phytomer_parameters_sugarbeet.leaf.yaw.uniformDistribution(-5,5);
+
1369 phytomer_parameters_sugarbeet.leaf.roll.uniformDistribution(-15,15);
+
1370 phytomer_parameters_sugarbeet.leaf.prototype_function = SugarbeetLeafPrototype;
+
1371 phytomer_parameters_sugarbeet.leaf.prototype_scale.uniformDistribution(0.08,0.12);
+
1372 phytomer_parameters_sugarbeet.leaf.subdivisions = 40;
+
1373
+
1374 // ---- Shoot Parameters ---- //
+
1375
+
1376 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
+
1377 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_sugarbeet;
+
1378 shoot_parameters_mainstem.vegetative_bud_break_probability = 0;
+
1379 shoot_parameters_mainstem.internode_radius_initial = 0.001;
+
1380 shoot_parameters_mainstem.phyllochron = 1;
+
1381 shoot_parameters_mainstem.elongation_rate = 0.25;
+
1382 shoot_parameters_mainstem.girth_growth_rate = 0;
+
1383 shoot_parameters_mainstem.gravitropic_curvature = 10;
+
1384 shoot_parameters_mainstem.child_internode_length_max = 0.0001;
+
1385 shoot_parameters_mainstem.child_internode_length_decay_rate = 0;
+
1386 shoot_parameters_mainstem.flowers_require_dormancy = false;
+
1387 shoot_parameters_mainstem.growth_requires_dormancy = false;
+
1388 shoot_parameters_mainstem.flower_bud_break_probability = 0.0;
+
1389 shoot_parameters_mainstem.max_nodes = 30;
+
1390
+
1391 defineShootType("mainstem",shoot_parameters_mainstem);
+
1392
+
1393
+
1394}
+
1395
+
1396uint PlantArchitecture::buildSugarbeetPlant(const helios::vec3 &base_position, float age) {
+
1397
+
1398 if (shoot_types.empty()) {
+
1399 //automatically initialize sugarbeet plant shoots
+
1400 initializeSugarbeetShoots();
+
1401 }
+
1402
+
1403 uint plantID = addPlantInstance(base_position, age);
+
1404
+
1405 uint uID_stem = addBaseStemShoot(plantID, 1, make_AxisRotation(context_ptr->randu(0.f, 0.01f * M_PI), 0.f*context_ptr->randu(0.f, 2.f * M_PI), 0.25f * M_PI), 0.001, 0.0001, 0.01, 1, "mainstem");
+
1406
+
1407 breakPlantDormancy(plantID);
+
1408
+
1409 setPlantPhenologicalThresholds(plantID, 0, 1000, 10, 60, 5, 100);
+
1410
+ +
1412
+
1413 return plantID;
+
1414
+
1415}
+
1416
+
1417void PlantArchitecture::initializeTomatoShoots() {
+
1418
+
1419 // ---- Phytomer Parameters ---- //
+
1420
+
1421 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
+
1422
+
1423 phytomer_parameters.internode.pitch = 10;
+
1424 phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(145, 215);
+
1425 phytomer_parameters.internode.color = make_RGBcolor(0.38, 0.48, 0.1);
+
1426 phytomer_parameters.internode.length_segments = 1;
+
1427
+
1428 phytomer_parameters.petiole.petioles_per_internode = 1;
+
1429 phytomer_parameters.petiole.pitch.uniformDistribution(35,50);
+
1430 phytomer_parameters.petiole.radius = 0.001;
+
1431 phytomer_parameters.petiole.length = 0.15;
+
1432 phytomer_parameters.petiole.taper = 0.15;
+
1433 phytomer_parameters.petiole.curvature.uniformDistribution(-300,-150);
+
1434 phytomer_parameters.petiole.color = phytomer_parameters.internode.color;
+
1435 phytomer_parameters.petiole.length_segments = 5;
+
1436
+
1437 phytomer_parameters.leaf.leaves_per_petiole = 7;
+
1438 phytomer_parameters.leaf.pitch.uniformDistribution(-30,5);
+
1439 phytomer_parameters.leaf.yaw = 0;
+
1440 phytomer_parameters.leaf.roll.normalDistribution(0, 10);
+
1441 phytomer_parameters.leaf.leaflet_offset = 0.15;
+
1442 phytomer_parameters.leaf.leaflet_scale = 0.75;
+
1443 phytomer_parameters.leaf.prototype_function = TomatoLeafPrototype;
+
1444 phytomer_parameters.leaf.prototype_scale = 0.1;
+
1445 phytomer_parameters.leaf.subdivisions = 6;
+
1446
+
1447 phytomer_parameters.peduncle.length = 0.08;
+
1448 phytomer_parameters.peduncle.radius = 0.00075;
+
1449 phytomer_parameters.peduncle.pitch = 25;
+
1450 phytomer_parameters.peduncle.roll = 0;
+
1451 phytomer_parameters.peduncle.curvature = -200;
+
1452 phytomer_parameters.peduncle.length_segments = 5;
+
1453 phytomer_parameters.peduncle.radial_subdivisions = 8;
+
1454
+
1455 phytomer_parameters.inflorescence.flowers_per_rachis = 8;
+
1456 phytomer_parameters.inflorescence.flower_offset = 0.15;
+
1457 phytomer_parameters.inflorescence.flower_arrangement_pattern = "opposite";
+
1458 phytomer_parameters.inflorescence.pitch = 90;
+
1459 phytomer_parameters.inflorescence.roll.uniformDistribution(-30,30);
+
1460 phytomer_parameters.inflorescence.flower_prototype_scale = 0.015;
+
1461 phytomer_parameters.inflorescence.flower_prototype_function = TomatoFlowerPrototype;
+
1462 phytomer_parameters.inflorescence.fruit_prototype_scale = 0.02;
+
1463 phytomer_parameters.inflorescence.fruit_prototype_function = TomatoFruitPrototype;
+
1464 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction = 0.5;
+
1465
+
1466 // ---- Shoot Parameters ---- //
+
1467
+
1468 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
+
1469 shoot_parameters.phytomer_parameters = phytomer_parameters;
+
1470 shoot_parameters.phytomer_parameters.phytomer_creation_function = TomatoPhytomerCreationFunction;
+
1471
+
1472 shoot_parameters.max_nodes = 25;
+
1473 shoot_parameters.internode_radius_initial = 0.0005;
+
1474 shoot_parameters.internode_radius_max = 0.0045;
+
1475 shoot_parameters.child_insertion_angle_tip = 30;
+
1476 shoot_parameters.child_insertion_angle_decay_rate = 0;
+
1477 shoot_parameters.child_internode_length_max = 0.03;
+
1478 shoot_parameters.child_internode_length_min = 0.0;
+
1479 shoot_parameters.child_internode_length_decay_rate = 0;
+
1480 shoot_parameters.base_roll = 90;
+
1481 shoot_parameters.base_yaw.uniformDistribution(-20,20);
+
1482 shoot_parameters.gravitropic_curvature = -20;
+
1483 shoot_parameters.tortuosity = 0;
+
1484
+
1485 shoot_parameters.phyllochron = 1;
+
1486 shoot_parameters.leaf_flush_count = 1;
+
1487 shoot_parameters.elongation_rate = 0.1;
+
1488 shoot_parameters.girth_growth_rate = 0.0002;
+
1489 shoot_parameters.vegetative_bud_break_time = 3;
+
1490 shoot_parameters.vegetative_bud_break_probability = 0.75;
+
1491 shoot_parameters.flower_bud_break_probability = 1;
+
1492 shoot_parameters.fruit_set_probability = 0.5;
+
1493 shoot_parameters.flowers_require_dormancy = false;
+
1494 shoot_parameters.growth_requires_dormancy = false;
+
1495 shoot_parameters.determinate_shoot_growth = true;
+
1496
+
1497 shoot_parameters.defineChildShootTypes({"mainstem"},{1.0});
+
1498
+
1499 defineShootType("mainstem",shoot_parameters);
+
1500
+
1501}
+
1502
+
1503uint PlantArchitecture::buildTomatoPlant(const helios::vec3 &base_position, float age) {
+
1504
+
1505 if (shoot_types.empty()) {
+
1506 //automatically initialize tomato plant shoots
+
1507 initializeTomatoShoots();
+
1508 }
+
1509
+
1510 uint plantID = addPlantInstance(base_position, age);
+
1511
+
1512 AxisRotation base_rotation = make_AxisRotation(0, context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
+
1513 uint uID_stem = addBaseStemShoot(plantID, 1, base_rotation, 0.0005, 0.04, 0.01, 0.01, "mainstem");
+
1514
+
1515 breakPlantDormancy(plantID);
+
1516
+
1517 setPlantPhenologicalThresholds(plantID, 0, -1, 10, 2, 2, 100);
+
1518
+
1519 return plantID;
+
1520
+
1521}
+
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
+
std::map< std::string, ShootParameters > getCurrentShootParameters()
Get the shoot parameters structure for all shoot types in the current plant model.
+
void updateCurrentShootParameters(const std::string &shoot_type_label, const ShootParameters &params)
Update the parameters of a single shoot type in the current plant model.
+
void setPlantPhenologicalThresholds(uint plantID, float time_to_dormancy_break, float time_to_flower_initiation, float time_to_flower_opening, float time_to_fruit_set, float time_to_fruit_maturity, float time_to_senescence)
Specify the threshold values for plant phenological stages.
+
void defineShootType(const std::string &shoot_type_label, const ShootParameters &shoot_params)
Define a new shoot type based on a set of ShootParameters.
+
uint addBaseStemShoot(uint plantID, uint current_node_number, const AxisRotation &base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label)
Define the stem/trunk shoot (base of plant) to start a new plant. This requires a plant instance has ...
+
uint buildPlantInstanceFromLibrary(const helios::vec3 &base_position, float age)
Build a plant instance based on the model currently loaded from the library.
+
uint appendShoot(uint plantID, int parent_shoot_ID, uint current_node_number, const AxisRotation &base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label)
Manually append a new shoot at the end of an existing shoot. This is used when the characteristics of...
+
void loadPlantModelFromLibrary(const std::string &plant_label)
Load an existing plant model from the library.
+
void disableInternodeContextBuild()
Do not build internode primitive geometry in the Context.
+
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition: Context.cpp:1121
+
std::minstd_rand0 * getRandomGenerator()
Get the random number generator engine.
Definition: Context.cpp:49
+
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition: global.cpp:29
+
float deg2rad(float deg)
Convert degrees to radians.
Definition: global.cpp:547
+
RGBcolor make_RGBcolor(float r, float g, float b)
Make an RGBcolor vector.
+ + + +
Vector of three elements of type 'float'.
+
+ + + + diff --git a/doc/html/_plug_ins.html b/doc/html/_plug_ins.html index c01c30b9f..eba0af1e2 100644 --- a/doc/html/_plug_ins.html +++ b/doc/html/_plug_ins.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
+ +
PlantArchitecture Class Reference
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 PlantArchitecture (helios::Context *context_ptr)
 Main architectural model class constructor.
 
void loadPlantModelFromLibrary (const std::string &plant_label)
 Load an existing plant model from the library.
 
uint buildPlantInstanceFromLibrary (const helios::vec3 &base_position, float age)
 Build a plant instance based on the model currently loaded from the library.
 
ShootParameters getCurrentShootParameters (const std::string &shoot_type_label)
 Get the shoot parameters structure for a specific shoot type in the current plant model.
 
std::map< std::string, ShootParametersgetCurrentShootParameters ()
 Get the shoot parameters structure for all shoot types in the current plant model.
 
void updateCurrentShootParameters (const std::string &shoot_type_label, const ShootParameters &params)
 Update the parameters of a single shoot type in the current plant model.
 
void updateCurrentShootParameters (const std::map< std::string, ShootParameters > &params)
 Update the parameters of all shoot types in the current plant model.
 
uint addPlantInstance (const helios::vec3 &base_position, float current_age)
 Create an instance of a plant.
 
uint duplicatePlantInstance (uint plantID, const helios::vec3 &base_position, const AxisRotation &base_rotation, float current_age)
 Duplicate an existing plant instance and specify its base position and age.
 
void setPlantPhenologicalThresholds (uint plantID, float time_to_dormancy_break, float time_to_flower_initiation, float time_to_flower_opening, float time_to_fruit_set, float time_to_fruit_maturity, float time_to_senescence)
 Specify the threshold values for plant phenological stages.
 
void advanceTime (float dt)
 Advance plant growth by a specified time interval.
 
void incrementAssimilatePool (uint plantID, uint shootID, float assimilate_increment_mg_g)
 
void incrementAssimilatePool (uint plantID, float assimilate_increment_mg_g)
 
void defineShootType (const std::string &shoot_type_label, const ShootParameters &shoot_params)
 Define a new shoot type based on a set of ShootParameters.
 
uint addBaseStemShoot (uint plantID, uint current_node_number, const AxisRotation &base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label)
 Define the stem/trunk shoot (base of plant) to start a new plant. This requires a plant instance has already been created using the addPlantInstance() method.
 
uint appendShoot (uint plantID, int parent_shoot_ID, uint current_node_number, const AxisRotation &base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label)
 Manually append a new shoot at the end of an existing shoot. This is used when the characteristics of a shoot change along its length (e.g., from a unifoliate to trifoliate leaf).
 
uint addChildShoot (uint plantID, int parent_shoot_ID, uint parent_node_index, uint current_node_number, const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const std::string &shoot_type_label, uint petiole_index=0)
 Manually add a child shoot at the axillary bud of a phytomer.
 
int addPhytomerToShoot (uint plantID, uint shootID, const PhytomerParameters &phytomer_parameters, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction)
 Add a new phytomer at the terminal bud of a shoot.
 
void disableInternodeContextBuild ()
 Do not build internode primitive geometry in the Context.
 
void disablePetioleContextBuild ()
 Do not build petiole primitive geometry in the Context.
 
void disablePeduncleContextBuild ()
 Do not build peduncle primitive geometry in the Context.
 
void enableGroundClipping (float ground_height=0.f)
 Enable automatic removal of organs that are below the ground plane.
 
void incrementPhytomerInternodeGirth (uint plantID, uint shootID, uint node_number, float girth_change)
 
void setPhytomerInternodeLengthScaleFraction (uint plantID, uint shootID, uint node_number, float internode_scale_factor_fraction)
 
void setPhytomerLeafScale (uint plantID, uint shootID, uint node_number, float leaf_scale_factor_fraction)
 
void setShootOrigin (uint plantID, uint shootID, const helios::vec3 &origin)
 
void setPlantBasePosition (uint plantID, const helios::vec3 &base_position)
 
void setPlantAge (uint plantID, float current_age)
 
void harvestPlant (uint plantID)
 
void removeShootLeaves (uint plantID, uint shootID)
 
void removePlantLeaves (uint plantID)
 
void makePlantDormant (uint plantID)
 
void breakPlantDormancy (uint plantID)
 
float getPlantAge (uint plantID) const
 
uint getShootNodeCount (uint plantID, uint shootID) const
 
helios::vec3 getPlantBasePosition (uint plantID) const
 
std::vector< uint > getAllPlantObjectIDs (uint plantID) const
 Get object IDs for all organs objects for a given plant.
 
std::vector< uint > getAllPlantUUIDs (uint plantID) const
 Get primitive UUIDs for all primitives in a given plant.
 
std::vector< uint > getPlantInternodeObjectIDs (uint plantID) const
 Get object IDs for all internode (Tube) objects for a given plant.
 
std::vector< uint > getPlantPetioleObjectIDs (uint plantID) const
 Get object IDs for all petiole (Tube) objects for a given plant.
 
std::vector< uint > getPlantLeafObjectIDs (uint plantID) const
 Get object IDs for all leaf objects for a given plant.
 
std::vector< uint > getPlantPeduncleObjectIDs (uint plantID) const
 Get object IDs for all peduncle (Tube) objects for a given plant.
 
std::vector< uint > getPlantFlowerObjectIDs (uint plantID) const
 Get object IDs for all inflorescence objects for a given plant.
 
std::vector< uint > getPlantFruitObjectIDs (uint plantID) const
 Get object IDs for all fruit objects for a given plant.
 
std::string getPlantString (uint plantID) const
 
uint generatePlantFromString (const std::string &generation_string, const PhytomerParameters &phytomer_parameters)
 
uint generatePlantFromString (const std::string &generation_string, const std::map< std::string, PhytomerParameters > &phytomer_parameters)
 
+ + + +

+Friends

class Shoot
 
+

Detailed Description

+
+

Definition at line 841 of file PlantArchitecture.h.

+

Constructor & Destructor Documentation

+ +

◆ PlantArchitecture()

+ +
+
+ + + + + +
+ + + + + + + + +
PlantArchitecture::PlantArchitecture (helios::Contextcontext_ptr)
+
+explicit
+
+ +

Main architectural model class constructor.

+
Parameters
+ + +
[in]context_ptrPointer to the Helios context.
+
+
+ +

Definition at line 87 of file PlantArchitecture.cpp.

+ +
+
+

Member Function Documentation

+ +

◆ addBaseStemShoot()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
uint PlantArchitecture::addBaseStemShoot (uint plantID,
uint current_node_number,
const AxisRotationbase_rotation,
float internode_radius,
float internode_length_max,
float internode_length_scale_factor_fraction,
float leaf_scale_factor_fraction,
const std::string & shoot_type_label 
)
+
+ +

Define the stem/trunk shoot (base of plant) to start a new plant. This requires a plant instance has already been created using the addPlantInstance() method.

+
Parameters
+ + + + + + + + + +
[in]plantIDID of the plant instance.
[in]current_node_numberNumber of nodes of the stem shoot.
[in]base_rotationAxisRotation object (pitch, yaw, roll) specifying the orientation of the base of the shoot.
[in]internode_radiusRadius of the internodes along the shoot.
[in]internode_length_maxMaximum length (i.e., fully elongated) of the internodes along the shoot.
[in]internode_length_scale_factor_fractionScaling factor of the maximum internode length to determine the actual initial internode length at the time of creation (=1 applies no scaling).
[in]leaf_scale_factor_fractionScaling factor of the leaf/petiole to determine the actual initial leaf size at the time of creation (=1 applies no scaling).
[in]shoot_type_labelLabel of the shoot type to be used for the base stem shoot. This requires that the shoot type has already been defined using the defineShootType() method.
+
+
+
Returns
ID of the new shoot to be used to reference it later.
+ +

Definition at line 1391 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ addChildShoot()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
uint PlantArchitecture::addChildShoot (uint plantID,
int parent_shoot_ID,
uint parent_node_index,
uint current_node_number,
const AxisRotationshoot_base_rotation,
float internode_radius,
float internode_length_max,
float internode_length_scale_factor_fraction,
float leaf_scale_factor_fraction,
const std::string & shoot_type_label,
uint petiole_index = 0 
)
+
+ +

Manually add a child shoot at the axillary bud of a phytomer.

+
Parameters
+ + + + + + + + + + + + +
[in]plantIDID of the plant instance.
[in]parent_shoot_IDID of the shoot to which the new shoot will be added.
[in]parent_node_indexNumber of the node of the parent shoot at which the new shoot will be added.
[in]current_node_numberNumber of nodes of the newly added shoot.
[in]shoot_base_rotationAxisRotation object (pitch, yaw, roll) specifying the orientation of the base of the shoot.
[in]internode_radiusInitial radius of the internodes along the shoot.
[in]internode_length_maxLength of the internode of the newly appended shoot.
[in]internode_length_scale_factor_fractionScaling factor of the maximum internode length to determine the actual initial internode length at the time of creation (=1 applies no scaling).
[in]leaf_scale_factor_fractionScaling factor of the leaf/petiole to determine the actual initial leaf size at the time of creation (=1 applies no scaling).
[in]shoot_type_labelLabel of the shoot type to be used for the new shoot. This requires that the shoot type has already been defined using the defineShootType() method.
[in]petiole_index[OPTIONAL] Index of the petiole within the internode to which the new shoot will be attached (when there are multiple petioles per internode)
+
+
+
Returns
ID of the newly generated shoot.
+ +

Definition at line 1468 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ addPhytomerToShoot()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
int PlantArchitecture::addPhytomerToShoot (uint plantID,
uint shootID,
const PhytomerParametersphytomer_parameters,
float internode_radius,
float internode_length_max,
float internode_length_scale_factor_fraction,
float leaf_scale_factor_fraction 
)
+
+ +

Add a new phytomer at the terminal bud of a shoot.

+
Parameters
+ + + + + + + + +
[in]plantIDID of the plant instance.
[in]shootIDID of the shoot to which the phytomer will be added
[in]phytomer_parametersParameters of the phytomer to be added
[in]internode_radiusRadius of the phytomer internode at the time of creation
[in]internode_length_maxMaximum internode length at full elongation
[in]internode_length_scale_factor_fractionScaling factor of the maximum internode length to determine the actual initial internode length at the time of creation (=1 applies no scaling).
[in]leaf_scale_factor_fractionScaling factor of the leaf/petiole to determine the actual initial leaf size at the time of creation (=1 applies no scaling).
+
+
+
Returns
ID of generated phytomer
+ +

Definition at line 1533 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ addPlantInstance()

+ +
+
+ + + + + + + + + + + + + + + + + + +
uint PlantArchitecture::addPlantInstance (const helios::vec3base_position,
float current_age 
)
+
+ +

Create an instance of a plant.

+

This is the first step of the plant building process. It creates an empty plant instance that can be built up manually, or using a pre-defined plant type in the library.

Parameters
+ + + +
[in]base_positionCartesian coordinates of the base of the plant.
[in]current_ageAge of the plant in days.
+
+
+
Returns
ID of the plant instance.
+ +

Definition at line 2013 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ advanceTime()

+ +
+
+ + + + + + + + +
void PlantArchitecture::advanceTime (float dt)
+
+ +

Advance plant growth by a specified time interval.

+
Parameters
+ + +
[in]dtTime interval in days.
+
+
+ +

Definition at line 2099 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ appendShoot()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
uint PlantArchitecture::appendShoot (uint plantID,
int parent_shoot_ID,
uint current_node_number,
const AxisRotationbase_rotation,
float internode_radius,
float internode_length_max,
float internode_length_scale_factor_fraction,
float leaf_scale_factor_fraction,
const std::string & shoot_type_label 
)
+
+ +

Manually append a new shoot at the end of an existing shoot. This is used when the characteristics of a shoot change along its length (e.g., from a unifoliate to trifoliate leaf).

+
Parameters
+ + + + + + + + + + +
[in]plantIDID of the plant instance.
[in]parent_shoot_IDID of the shoot to which the new shoot will be appended.
[in]current_node_numberNumber of nodes/phytomers of the newly appended shoot.
[in]base_rotationAxisRotation object (pitch, yaw, roll) specifying the orientation of the base of the shoot relative to the parent shoot.
[in]internode_radiusInitial radius of the internodes along the shoot.
[in]internode_length_maxLength of the internode of the newly appended shoot.
[in]internode_length_scale_factor_fractionScaling factor of the maximum internode length to determine the actual initial internode length at the time of creation (=1 applies no scaling).
[in]leaf_scale_factor_fractionScaling factor of the leaf/petiole to determine the actual initial leaf size at the time of creation (=1 applies no scaling).
[in]shoot_type_labelLabel of the shoot type to be used for the new shoot. This requires that the shoot type has already been defined using the defineShootType() method.
+
+
+
Returns
ID of the new shoot to be used to reference it later.
+ +

Definition at line 1420 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ breakPlantDormancy()

+ +
+
+ + + + + + + + +
void PlantArchitecture::breakPlantDormancy (uint plantID)
+
+ +

Definition at line 1823 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ buildPlantInstanceFromLibrary()

+ +
+
+ + + + + + + + + + + + + + + + + + +
uint PlantArchitecture::buildPlantInstanceFromLibrary (const helios::vec3base_position,
float age 
)
+
+ +

Build a plant instance based on the model currently loaded from the library.

+
Parameters
+ + + +
[in]base_positionCartesian coordinates of the base of the plant.
[in]ageAge of the plant.
+
+
+
Returns
ID of the plant instance.
+ +

Definition at line 27 of file PlantLibrary.cpp.

+ +
+
+ +

◆ defineShootType()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PlantArchitecture::defineShootType (const std::string & shoot_type_label,
const ShootParametersshoot_params 
)
+
+ +

Define a new shoot type based on a set of ShootParameters.

+
Parameters
+ + + +
[in]shoot_type_labelUser-defined label for the new shoot type. This string is used later to reference this type of shoot.
[in]shoot_paramsParameters structure for the new shoot type.
+
+
+ +

Definition at line 205 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ disableInternodeContextBuild()

+ +
+
+ + + + + + + +
void PlantArchitecture::disableInternodeContextBuild ()
+
+ +

Do not build internode primitive geometry in the Context.

+ +

Definition at line 1560 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ disablePeduncleContextBuild()

+ +
+
+ + + + + + + +
void PlantArchitecture::disablePeduncleContextBuild ()
+
+ +

Do not build peduncle primitive geometry in the Context.

+ +

Definition at line 1568 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ disablePetioleContextBuild()

+ +
+
+ + + + + + + +
void PlantArchitecture::disablePetioleContextBuild ()
+
+ +

Do not build petiole primitive geometry in the Context.

+ +

Definition at line 1564 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ duplicatePlantInstance()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
uint PlantArchitecture::duplicatePlantInstance (uint plantID,
const helios::vec3base_position,
const AxisRotationbase_rotation,
float current_age 
)
+
+ +

Duplicate an existing plant instance and specify its base position and age.

+
Parameters
+ + + + +
[in]plantIDID of the existing plant instance to be duplicated.
[in]base_positionCartesian coordinates of the base of the new plant copy.
[in]current_ageAge of the new plant copy in days.
+
+
+
Returns
ID of the new plant instance.
+ +

Definition at line 2029 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ enableGroundClipping()

+ +
+
+ + + + + + + + +
void PlantArchitecture::enableGroundClipping (float ground_height = 0.f)
+
+ +

Enable automatic removal of organs that are below the ground plane.

+
Parameters
+ + +
[in]ground_height[OPTIONAL] Height of the ground plane (default = 0).
+
+
+ +

Definition at line 1572 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ generatePlantFromString() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
uint PlantArchitecture::generatePlantFromString (const std::string & generation_string,
const PhytomerParametersphytomer_parameters 
)
+
+ +

Definition at line 363 of file InputOutput.cpp.

+ +
+
+ +

◆ generatePlantFromString() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
uint PlantArchitecture::generatePlantFromString (const std::string & generation_string,
const std::map< std::string, PhytomerParameters > & phytomer_parameters 
)
+
+ +

Definition at line 369 of file InputOutput.cpp.

+ +
+
+ +

◆ getAllPlantObjectIDs()

+ +
+
+ + + + + + + + +
std::vector< uint > PlantArchitecture::getAllPlantObjectIDs (uint plantID) const
+
+ +

Get object IDs for all organs objects for a given plant.

+
Parameters
+ + +
[in]plantIDID of the plant instance.
+
+
+
Returns
Vector of object IDs for all organs in the plant.
+ +

Definition at line 1843 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getAllPlantUUIDs()

+ +
+
+ + + + + + + + +
std::vector< uint > PlantArchitecture::getAllPlantUUIDs (uint plantID) const
+
+ +

Get primitive UUIDs for all primitives in a given plant.

+
Parameters
+ + +
[in]plantIDID of the plant instance.
+
+
+
Returns
Vector of primitive UUIDs for all primitives in the plant.
+ +

Definition at line 1869 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getCurrentShootParameters() [1/2]

+ +
+
+ + + + + + + +
std::map< std::string, ShootParameters > PlantArchitecture::getCurrentShootParameters ()
+
+ +

Get the shoot parameters structure for all shoot types in the current plant model.

+
Returns
Map of shoot type labels to ShootParameters structures for all shoot types in the current plant model. The key is the user-defined label string for the shoot type, and the value is the corresponding ShootParameters structure.
+ +

Definition at line 75 of file PlantLibrary.cpp.

+ +
+
+ +

◆ getCurrentShootParameters() [2/2]

+ +
+
+ + + + + + + + +
ShootParameters PlantArchitecture::getCurrentShootParameters (const std::string & shoot_type_label)
+
+ +

Get the shoot parameters structure for a specific shoot type in the current plant model.

+
Parameters
+ + +
[in]shoot_type_labelUser-defined label for the shoot type.
+
+
+
Returns
ShootParameters structure for the specified shoot type.
+ +

Definition at line 66 of file PlantLibrary.cpp.

+ +
+
+ +

◆ getPlantAge()

+ +
+
+ + + + + + + + +
float PlantArchitecture::getPlantAge (uint plantID) const
+
+ +

Definition at line 1759 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getPlantBasePosition()

+ +
+
+ + + + + + + + +
helios::vec3 PlantArchitecture::getPlantBasePosition (uint plantID) const
+
+ +

Definition at line 1745 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getPlantFlowerObjectIDs()

+ +
+
+ + + + + + + + +
std::vector< uint > PlantArchitecture::getPlantFlowerObjectIDs (uint plantID) const
+
+ +

Get object IDs for all inflorescence objects for a given plant.

+
Parameters
+ + +
[in]plantIDID of the plant instance.
+
+
+
Returns
Vector of object IDs for all inflorescences in the plant.
+ +

Definition at line 1959 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getPlantFruitObjectIDs()

+ +
+
+ + + + + + + + +
std::vector< uint > PlantArchitecture::getPlantFruitObjectIDs (uint plantID) const
+
+ +

Get object IDs for all fruit objects for a given plant.

+
Parameters
+ + +
[in]plantIDID of the plant instance.
+
+
+
Returns
Vector of object IDs for all fruits in the plant.
+ +

Definition at line 1986 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getPlantInternodeObjectIDs()

+ +
+
+ + + + + + + + +
std::vector< uint > PlantArchitecture::getPlantInternodeObjectIDs (uint plantID) const
+
+ +

Get object IDs for all internode (Tube) objects for a given plant.

+
Parameters
+ + +
[in]plantIDID of the plant instance.
+
+
+
Returns
Vector of object IDs for all internodes in the plant.
+ +

Definition at line 1873 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getPlantLeafObjectIDs()

+ +
+
+ + + + + + + + +
std::vector< uint > PlantArchitecture::getPlantLeafObjectIDs (uint plantID) const
+
+ +

Get object IDs for all leaf objects for a given plant.

+
Parameters
+ + +
[in]plantIDID of the plant instance.
+
+
+
Returns
Vector of object IDs for all leaves in the plant.
+ +

Definition at line 1914 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getPlantPeduncleObjectIDs()

+ +
+
+ + + + + + + + +
std::vector< uint > PlantArchitecture::getPlantPeduncleObjectIDs (uint plantID) const
+
+ +

Get object IDs for all peduncle (Tube) objects for a given plant.

+
Parameters
+ + +
[in]plantIDID of the plant instance.
+
+
+
Returns
Vector of object IDs for all peduncles in the plant.
+ +

Definition at line 1935 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getPlantPetioleObjectIDs()

+ +
+
+ + + + + + + + +
std::vector< uint > PlantArchitecture::getPlantPetioleObjectIDs (uint plantID) const
+
+ +

Get object IDs for all petiole (Tube) objects for a given plant.

+
Parameters
+ + +
[in]plantIDID of the plant instance.
+
+
+
Returns
Vector of object IDs for all petioles in the plant.
+ +

Definition at line 1893 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getPlantString()

+ +
+
+ + + + + + + + +
std::string PlantArchitecture::getPlantString (uint plantID) const
+
+ +

Definition at line 57 of file InputOutput.cpp.

+ +
+
+ +

◆ getShootNodeCount()

+ +
+
+ + + + + + + + + + + + + + + + + + +
uint PlantArchitecture::getShootNodeCount (uint plantID,
uint shootID 
) const
+
+ +

Definition at line 1834 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ harvestPlant()

+ +
+
+ + + + + + + + +
void PlantArchitecture::harvestPlant (uint plantID)
+
+ +

Definition at line 1768 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ incrementAssimilatePool() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PlantArchitecture::incrementAssimilatePool (uint plantID,
float assimilate_increment_mg_g 
)
+
+ +

Definition at line 2419 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ incrementAssimilatePool() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PlantArchitecture::incrementAssimilatePool (uint plantID,
uint shootID,
float assimilate_increment_mg_g 
)
+
+ +

Definition at line 2407 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ incrementPhytomerInternodeGirth()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PlantArchitecture::incrementPhytomerInternodeGirth (uint plantID,
uint shootID,
uint node_number,
float girth_change 
)
+
+ +

Definition at line 1576 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ loadPlantModelFromLibrary()

+ +
+
+ + + + + + + + +
void PlantArchitecture::loadPlantModelFromLibrary (const std::string & plant_label)
+
+ +

Load an existing plant model from the library.

+
Parameters
+ + +
[in]plant_labelUser-defined label for the plant model to be loaded.
+
+
+ +

Definition at line 20 of file PlantLibrary.cpp.

+ +
+
+ +

◆ makePlantDormant()

+ +
+
+ + + + + + + + +
void PlantArchitecture::makePlantDormant (uint plantID)
+
+ +

Definition at line 1813 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ removePlantLeaves()

+ +
+
+ + + + + + + + +
void PlantArchitecture::removePlantLeaves (uint plantID)
+
+ +

Definition at line 1801 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ removeShootLeaves()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PlantArchitecture::removeShootLeaves (uint plantID,
uint shootID 
)
+
+ +

Definition at line 1784 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setPhytomerInternodeLengthScaleFraction()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PlantArchitecture::setPhytomerInternodeLengthScaleFraction (uint plantID,
uint shootID,
uint node_number,
float internode_scale_factor_fraction 
)
+
+ +

Definition at line 1631 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setPhytomerLeafScale()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PlantArchitecture::setPhytomerLeafScale (uint plantID,
uint shootID,
uint node_number,
float leaf_scale_factor_fraction 
)
+
+ +

Definition at line 1708 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setPlantAge()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PlantArchitecture::setPlantAge (uint plantID,
float current_age 
)
+
+ +

Definition at line 1754 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setPlantBasePosition()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PlantArchitecture::setPlantBasePosition (uint plantID,
const helios::vec3base_position 
)
+
+ +

Definition at line 1730 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setPlantPhenologicalThresholds()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PlantArchitecture::setPlantPhenologicalThresholds (uint plantID,
float time_to_dormancy_break,
float time_to_flower_initiation,
float time_to_flower_opening,
float time_to_fruit_set,
float time_to_fruit_maturity,
float time_to_senescence 
)
+
+ +

Specify the threshold values for plant phenological stages.

+
Parameters
+ + + + + + + + +
[in]plantIDID of the plant.
[in]time_to_dormancy_breakTime required to break dormancy.
[in]time_to_flower_initiationTime from emergence/dormancy required to reach flower creation (closed flowers).
[in]time_to_flower_openingTime from flower initiation to flower opening.
[in]time_to_fruit_setTime from flower opening required to reach fruit set (i.e., flower dies and fruit is created).
[in]time_to_fruit_maturityTime from fruit set date required to reach fruit maturity.
[in]time_to_senescenceTime from emergence/dormancy required to reach senescence.
+
+
+
Note
Any phenological stage can be skipped by specifying a negative threshold value. In this case, the stage will be skipped and the threshold for the next stage will be relative to the previous stage.
+ +

Definition at line 2083 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setShootOrigin()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PlantArchitecture::setShootOrigin (uint plantID,
uint shootID,
const helios::vec3origin 
)
+
+ +

Definition at line 1678 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ updateCurrentShootParameters() [1/2]

+ +
+
+ + + + + + + + +
void PlantArchitecture::updateCurrentShootParameters (const std::map< std::string, ShootParameters > & params)
+
+ +

Update the parameters of all shoot types in the current plant model.

+
Parameters
+ + + +
[in]shoot_type_labelUser-defined label for the shoot type to be updated.
[in]paramsUpdated parameters structure for the shoot type.
+
+
+
Note
This will overwrite any existing shoot parameter definitions.
+ +

Definition at line 86 of file PlantLibrary.cpp.

+ +
+
+ +

◆ updateCurrentShootParameters() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PlantArchitecture::updateCurrentShootParameters (const std::string & shoot_type_label,
const ShootParametersparams 
)
+
+ +

Update the parameters of a single shoot type in the current plant model.

+
Parameters
+ + + +
[in]shoot_type_labelUser-defined label for the shoot type to be updated.
[in]paramsUpdated parameters structure for the shoot type.
+
+
+
Note
This will overwrite any existing shoot parameter definitions.
+ +

Definition at line 82 of file PlantLibrary.cpp.

+ +
+
+

Friends And Related Function Documentation

+ +

◆ Shoot

+ +
+
+ + + + + +
+ + + + +
friend class Shoot
+
+friend
+
+ +

Definition at line 1119 of file PlantArchitecture.h.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/html/class_radiation_model.html b/doc/html/class_radiation_model.html index 743ee2220..15369069f 100644 --- a/doc/html/class_radiation_model.html +++ b/doc/html/class_radiation_model.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
include Directory Reference
+
+
+ + + + + + +

+Files

file  Assets.h [code]
 
file  PlantArchitecture.h [code]
 
+
+ + + + diff --git a/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.html b/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.html index c684bd55e..49dd103f5 100644 --- a/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.html +++ b/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
src Directory Reference
+
+
+ + + + + + + + + + +

+Files

file  Assets.cpp [code]
 
file  InputOutput.cpp [code]
 
file  PlantArchitecture.cpp [code]
 
file  PlantLibrary.cpp [code]
 
+
+ + + + diff --git a/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.html b/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.html index 6b42eb89a..631d721e7 100644 --- a/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.html +++ b/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
plantarchitecture Directory Reference
+
+
+ + + + + + +

+Directories

directory  include
 
directory  src
 
+
+ + + + diff --git a/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.html b/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.html index cef4441b6..b3275e2d8 100644 --- a/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.html +++ b/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
doc Directory Reference
+
+
+
+ + + + diff --git a/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html b/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html index be6d90a4a..48bf19c8c 100644 --- a/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html +++ b/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
+ +
AxisRotation Struct Reference
+
+
+ + + + + + + + +

+Public Member Functions

 AxisRotation (float a_pitch, float a_yaw, float a_roll)
 
AxisRotation operator+ (const AxisRotation &a) const
 
AxisRotation operator- (const AxisRotation &a) const
 
+ + + + + + + +

+Data Fields

float pitch
 
float yaw
 
float roll
 
+

Detailed Description

+
+

Definition at line 207 of file PlantArchitecture.h.

+

Constructor & Destructor Documentation

+ +

◆ AxisRotation() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
AxisRotation::AxisRotation ()
+
+inline
+
+ +

Definition at line 210 of file PlantArchitecture.h.

+ +
+
+ +

◆ AxisRotation() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
AxisRotation::AxisRotation (float a_pitch,
float a_yaw,
float a_roll 
)
+
+inline
+
+ +

Definition at line 216 of file PlantArchitecture.h.

+ +
+
+

Member Function Documentation

+ +

◆ operator+()

+ +
+
+ + + + + +
+ + + + + + + + +
AxisRotation AxisRotation::operator+ (const AxisRotationa) const
+
+inline
+
+ +

Definition at line 235 of file PlantArchitecture.h.

+ +
+
+ +

◆ operator-()

+ +
+
+ + + + + +
+ + + + + + + + +
AxisRotation AxisRotation::operator- (const AxisRotationa) const
+
+inline
+
+ +

Definition at line 239 of file PlantArchitecture.h.

+ +
+
+

Field Documentation

+ +

◆ pitch

+ +
+
+ + + + +
float AxisRotation::pitch
+
+ +

Definition at line 222 of file PlantArchitecture.h.

+ +
+
+ +

◆ roll

+ +
+
+ + + + +
float AxisRotation::roll
+
+ +

Definition at line 224 of file PlantArchitecture.h.

+ +
+
+ +

◆ yaw

+ +
+
+ + + + +
float AxisRotation::yaw
+
+ +

Definition at line 223 of file PlantArchitecture.h.

+ +
+
+
The documentation for this struct was generated from the following file: +
+ + + + diff --git a/doc/html/struct_b_b_lcoefficients.html b/doc/html/struct_b_b_lcoefficients.html index 907b1cae1..bece8bf65 100644 --- a/doc/html/struct_b_b_lcoefficients.html +++ b/doc/html/struct_b_b_lcoefficients.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
+ +
FloralBud Struct Reference
+
+
+ + + + + + + + + + + + +

+Data Fields

BudState state = BUD_DORMANT
 
float time_counter = 0
 
uint parent_petiole_index = 0
 
uint bud_index = 0
 
float current_fruit_scale_factor = 1
 
+

Detailed Description

+
+

Definition at line 324 of file PlantArchitecture.h.

+

Field Documentation

+ +

◆ bud_index

+ +
+
+ + + + +
uint FloralBud::bud_index = 0
+
+ +

Definition at line 333 of file PlantArchitecture.h.

+ +
+
+ +

◆ current_fruit_scale_factor

+ +
+
+ + + + +
float FloralBud::current_fruit_scale_factor = 1
+
+ +

Definition at line 335 of file PlantArchitecture.h.

+ +
+
+ +

◆ parent_petiole_index

+ +
+
+ + + + +
uint FloralBud::parent_petiole_index = 0
+
+ +

Definition at line 331 of file PlantArchitecture.h.

+ +
+
+ +

◆ state

+ +
+
+ + + + +
BudState FloralBud::state = BUD_DORMANT
+
+ +

Definition at line 327 of file PlantArchitecture.h.

+ +
+
+ +

◆ time_counter

+ +
+
+ + + + +
float FloralBud::time_counter = 0
+
+ +

Definition at line 329 of file PlantArchitecture.h.

+ +
+
+
The documentation for this struct was generated from the following file: +
+ + + + diff --git a/doc/html/struct_goblet_grapevine_parameters.html b/doc/html/struct_goblet_grapevine_parameters.html index d188a44f0..ae9927b91 100644 --- a/doc/html/struct_goblet_grapevine_parameters.html +++ b/doc/html/struct_goblet_grapevine_parameters.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
+ +
Phytomer Struct Reference
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Phytomer (const PhytomerParameters &params, Shoot *parent_shoot, uint phytomer_index, const helios::vec3 &parent_internode_axis, const helios::vec3 &parent_petiole_axis, helios::vec3 internode_base_origin, const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, uint rank, bool build_context_geometry_internode, bool build_context_geometry_petiole, bool build_context_geometry_peduncle, helios::Context *context_ptr)
 
helios::vec3 getInternodeAxisVector (float stem_fraction) const
 
helios::vec3 getPetioleAxisVector (float stem_fraction, uint petiole_index) const
 
helios::vec3 getAxisVector (float stem_fraction, const std::vector< helios::vec3 > &axis_vertices) const
 
float getInternodeLength () const
 
float getPetioleLength () const
 
float getInternodeRadius (float stem_fraction) const
 
bool hasLeaf () const
 
bool hasInflorescence () const
 
void addInflorescence (const helios::vec3 &base_position, const AxisRotation &base_rotation, const helios::vec3 &a_inflorescence_bending_axis, FloralBud &fbud)
 
void setInternodeLengthScaleFraction (float internode_scale_factor_fraction)
 
void setInternodeMaxLength (float internode_length_max)
 
void scaleInternodeMaxLength (float scale_factor)
 
void setInternodeMaxRadius (float internode_radius_max)
 
void setLeafScaleFraction (float leaf_scale_factor_fraction)
 
void setLeafPrototypeScale (float leaf_prototype_scale)
 
void scaleLeafPrototypeScale (float scale_factor)
 
void setInflorescenceScaleFraction (FloralBud &fbud, float inflorescence_scale_factor_fraction)
 
void setPetioleBase (const helios::vec3 &base_position)
 
void setPhytomerBase (const helios::vec3 &base_position)
 
void setVegetativeBudState (BudState state)
 
void setVegetativeBudState (BudState state, uint petiole_index, uint bud_index)
 
void setVegetativeBudState (BudState state, VegetativeBud &vbud)
 
void setFloralBudState (BudState state)
 
void setFloralBudState (BudState state, uint petiole_index, uint bud_index)
 
void setFloralBudState (BudState state, FloralBud &fbud)
 
void removeLeaf ()
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Data Fields

std::vector< helios::vec3internode_vertices
 
std::vector< std::vector< helios::vec3 > > petiole_vertices
 
std::vector< std::vector< helios::vec3 > > leaf_bases
 
std::vector< std::vector< std::vector< helios::vec3 > > > inflorescence_bases
 
float internode_length
 
std::vector< float > internode_radii
 
std::vector< std::vector< float > > petiole_radii
 
std::vector< float > petiole_length
 
std::vector< helios::RGBcolorinternode_colors
 
std::vector< helios::RGBcolorpetiole_colors
 
std::vector< uint > internode_objIDs
 
std::vector< std::vector< uint > > petiole_objIDs
 
std::vector< std::vector< uint > > leaf_objIDs
 
std::vector< std::vector< std::vector< uint > > > inflorescence_objIDs
 
std::vector< std::vector< std::vector< uint > > > peduncle_objIDs
 
PhytomerParameters phytomer_parameters
 
uint rank
 
helios::int2 shoot_index
 
float age = 0
 
float time_since_dormancy = 0
 
float current_internode_scale_factor = 1
 
float current_leaf_scale_factor = 1
 
std::vector< std::vector< VegetativeBud > > vegetative_buds
 
std::vector< std::vector< FloralBud > > floral_buds
 
float internode_radius_initial
 
float internode_radius_max
 
float internode_length_max
 
bool build_context_geometry_internode = true
 
bool build_context_geometry_petiole = true
 
bool build_context_geometry_peduncle = true
 
+

Detailed Description

+
+

Definition at line 644 of file PlantArchitecture.h.

+

Constructor & Destructor Documentation

+ +

◆ Phytomer()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Phytomer::Phytomer (const PhytomerParametersparams,
Shootparent_shoot,
uint phytomer_index,
const helios::vec3parent_internode_axis,
const helios::vec3parent_petiole_axis,
helios::vec3 internode_base_origin,
const AxisRotationshoot_base_rotation,
float internode_radius,
float internode_length_max,
float internode_length_scale_factor_fraction,
float leaf_scale_factor_fraction,
uint rank,
bool build_context_geometry_internode,
bool build_context_geometry_petiole,
bool build_context_geometry_peduncle,
helios::Contextcontext_ptr 
)
+
+ +

Definition at line 525 of file PlantArchitecture.cpp.

+ +
+
+

Member Function Documentation

+ +

◆ addInflorescence()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Phytomer::addInflorescence (const helios::vec3base_position,
const AxisRotationbase_rotation,
const helios::vec3a_inflorescence_bending_axis,
FloralBudfbud 
)
+
+ +

Definition at line 858 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getAxisVector()

+ +
+
+ + + + + + + + + + + + + + + + + + +
helios::vec3 Phytomer::getAxisVector (float stem_fraction,
const std::vector< helios::vec3 > & axis_vertices 
) const
+
+ +

Definition at line 225 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getInternodeAxisVector()

+ +
+
+ + + + + + + + +
helios::vec3 Phytomer::getInternodeAxisVector (float stem_fraction) const
+
+ +

Definition at line 214 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getInternodeLength()

+ +
+
+ + + + + + + +
float Phytomer::getInternodeLength () const
+
+ +

Definition at line 249 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getInternodeRadius()

+ +
+
+ + + + + + + + +
float Phytomer::getInternodeRadius (float stem_fraction) const
+
+ +

Definition at line 261 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getPetioleAxisVector()

+ +
+
+ + + + + + + + + + + + + + + + + + +
helios::vec3 Phytomer::getPetioleAxisVector (float stem_fraction,
uint petiole_index 
) const
+
+ +

Definition at line 218 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getPetioleLength()

+ +
+
+ + + + + + + +
float Phytomer::getPetioleLength () const
+
+ +

Definition at line 255 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ hasInflorescence()

+ +
+
+ + + + + + + +
bool Phytomer::hasInflorescence () const
+
+ +

Definition at line 1316 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ hasLeaf()

+ +
+
+ + + + + + + +
bool Phytomer::hasLeaf () const
+
+ +

Definition at line 1312 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ removeLeaf()

+ +
+
+ + + + + + + +
void Phytomer::removeLeaf ()
+
+ +

Definition at line 1299 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ scaleInternodeMaxLength()

+ +
+
+ + + + + + + + +
void Phytomer::scaleInternodeMaxLength (float scale_factor)
+
+ +

Definition at line 1165 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ scaleLeafPrototypeScale()

+ +
+
+ + + + + + + + +
void Phytomer::scaleLeafPrototypeScale (float scale_factor)
+
+ +

Definition at line 1262 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setFloralBudState() [1/3]

+ +
+
+ + + + + + + + +
void Phytomer::setFloralBudState (BudState state)
+
+ +

Definition at line 289 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setFloralBudState() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void Phytomer::setFloralBudState (BudState state,
FloralBudfbud 
)
+
+ +

Definition at line 307 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setFloralBudState() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Phytomer::setFloralBudState (BudState state,
uint petiole_index,
uint bud_index 
)
+
+ +

Definition at line 297 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setInflorescenceScaleFraction()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void Phytomer::setInflorescenceScaleFraction (FloralBudfbud,
float inflorescence_scale_factor_fraction 
)
+
+ +

Definition at line 1274 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setInternodeLengthScaleFraction()

+ +
+
+ + + + + + + + +
void Phytomer::setInternodeLengthScaleFraction (float internode_scale_factor_fraction)
+
+ +

Definition at line 1115 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setInternodeMaxLength()

+ +
+
+ + + + + + + + +
void Phytomer::setInternodeMaxLength (float internode_length_max)
+
+ +

Definition at line 1154 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setInternodeMaxRadius()

+ +
+
+ + + + + + + + +
void Phytomer::setInternodeMaxRadius (float internode_radius_max)
+
+ +

Definition at line 1176 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setLeafPrototypeScale()

+ +
+
+ + + + + + + + +
void Phytomer::setLeafPrototypeScale (float leaf_prototype_scale)
+
+ +

Definition at line 1252 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setLeafScaleFraction()

+ +
+
+ + + + + + + + +
void Phytomer::setLeafScaleFraction (float leaf_scale_factor_fraction)
+
+ +

Definition at line 1182 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setPetioleBase()

+ +
+
+ + + + + + + + +
void Phytomer::setPetioleBase (const helios::vec3base_position)
+
+ +

Definition at line 1039 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setPhytomerBase()

+ +
+
+ + + + + + + + +
void Phytomer::setPhytomerBase (const helios::vec3base_position)
+
+ +

Definition at line 1074 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setVegetativeBudState() [1/3]

+ +
+
+ + + + + + + + +
void Phytomer::setVegetativeBudState (BudState state)
+
+ +

Definition at line 267 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setVegetativeBudState() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Phytomer::setVegetativeBudState (BudState state,
uint petiole_index,
uint bud_index 
)
+
+ +

Definition at line 275 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ setVegetativeBudState() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void Phytomer::setVegetativeBudState (BudState state,
VegetativeBudvbud 
)
+
+ +

Definition at line 285 of file PlantArchitecture.cpp.

+ +
+
+

Field Documentation

+ +

◆ age

+ +
+
+ + + + +
float Phytomer::age = 0
+
+ +

Definition at line 734 of file PlantArchitecture.h.

+ +
+
+ +

◆ build_context_geometry_internode

+ +
+
+ + + + +
bool Phytomer::build_context_geometry_internode = true
+
+ +

Definition at line 747 of file PlantArchitecture.h.

+ +
+
+ +

◆ build_context_geometry_peduncle

+ +
+
+ + + + +
bool Phytomer::build_context_geometry_peduncle = true
+
+ +

Definition at line 749 of file PlantArchitecture.h.

+ +
+
+ +

◆ build_context_geometry_petiole

+ +
+
+ + + + +
bool Phytomer::build_context_geometry_petiole = true
+
+ +

Definition at line 748 of file PlantArchitecture.h.

+ +
+
+ +

◆ current_internode_scale_factor

+ +
+
+ + + + +
float Phytomer::current_internode_scale_factor = 1
+
+ +

Definition at line 737 of file PlantArchitecture.h.

+ +
+
+ +

◆ current_leaf_scale_factor

+ +
+
+ + + + +
float Phytomer::current_leaf_scale_factor = 1
+
+ +

Definition at line 738 of file PlantArchitecture.h.

+ +
+
+ +

◆ floral_buds

+ +
+
+ + + + +
std::vector<std::vector<FloralBud> > Phytomer::floral_buds
+
+ +

Definition at line 741 of file PlantArchitecture.h.

+ +
+
+ +

◆ inflorescence_bases

+ +
+
+ + + + +
std::vector<std::vector<std::vector<helios::vec3> > > Phytomer::inflorescence_bases
+
+ +

Definition at line 713 of file PlantArchitecture.h.

+ +
+
+ +

◆ inflorescence_objIDs

+ +
+
+ + + + +
std::vector<std::vector<std::vector<uint> > > Phytomer::inflorescence_objIDs
+
+ +

Definition at line 726 of file PlantArchitecture.h.

+ +
+
+ +

◆ internode_colors

+ +
+
+ + + + +
std::vector<helios::RGBcolor> Phytomer::internode_colors
+
+ +

Definition at line 720 of file PlantArchitecture.h.

+ +
+
+ +

◆ internode_length

+ +
+
+ + + + +
float Phytomer::internode_length
+
+ +

Definition at line 714 of file PlantArchitecture.h.

+ +
+
+ +

◆ internode_length_max

+ +
+
+ + + + +
float Phytomer::internode_length_max
+
+ +

Definition at line 745 of file PlantArchitecture.h.

+ +
+
+ +

◆ internode_objIDs

+ +
+
+ + + + +
std::vector<uint> Phytomer::internode_objIDs
+
+ +

Definition at line 723 of file PlantArchitecture.h.

+ +
+
+ +

◆ internode_radii

+ +
+
+ + + + +
std::vector<float> Phytomer::internode_radii
+
+ +

Definition at line 716 of file PlantArchitecture.h.

+ +
+
+ +

◆ internode_radius_initial

+ +
+
+ + + + +
float Phytomer::internode_radius_initial
+
+ +

Definition at line 743 of file PlantArchitecture.h.

+ +
+
+ +

◆ internode_radius_max

+ +
+
+ + + + +
float Phytomer::internode_radius_max
+
+ +

Definition at line 744 of file PlantArchitecture.h.

+ +
+
+ +

◆ internode_vertices

+ +
+
+ + + + +
std::vector<helios::vec3> Phytomer::internode_vertices
+
+ +

Definition at line 710 of file PlantArchitecture.h.

+ +
+
+ +

◆ leaf_bases

+ +
+
+ + + + +
std::vector<std::vector<helios::vec3> > Phytomer::leaf_bases
+
+ +

Definition at line 712 of file PlantArchitecture.h.

+ +
+
+ +

◆ leaf_objIDs

+ +
+
+ + + + +
std::vector<std::vector<uint> > Phytomer::leaf_objIDs
+
+ +

Definition at line 725 of file PlantArchitecture.h.

+ +
+
+ +

◆ peduncle_objIDs

+ +
+
+ + + + +
std::vector<std::vector<std::vector<uint> > > Phytomer::peduncle_objIDs
+
+ +

Definition at line 727 of file PlantArchitecture.h.

+ +
+
+ +

◆ petiole_colors

+ +
+
+ + + + +
std::vector<helios::RGBcolor> Phytomer::petiole_colors
+
+ +

Definition at line 721 of file PlantArchitecture.h.

+ +
+
+ +

◆ petiole_length

+ +
+
+ + + + +
std::vector<float> Phytomer::petiole_length
+
+ +

Definition at line 718 of file PlantArchitecture.h.

+ +
+
+ +

◆ petiole_objIDs

+ +
+
+ + + + +
std::vector<std::vector<uint> > Phytomer::petiole_objIDs
+
+ +

Definition at line 724 of file PlantArchitecture.h.

+ +
+
+ +

◆ petiole_radii

+ +
+
+ + + + +
std::vector<std::vector<float> > Phytomer::petiole_radii
+
+ +

Definition at line 717 of file PlantArchitecture.h.

+ +
+
+ +

◆ petiole_vertices

+ +
+
+ + + + +
std::vector<std::vector<helios::vec3> > Phytomer::petiole_vertices
+
+ +

Definition at line 711 of file PlantArchitecture.h.

+ +
+
+ +

◆ phytomer_parameters

+ +
+
+ + + + +
PhytomerParameters Phytomer::phytomer_parameters
+
+ +

Definition at line 729 of file PlantArchitecture.h.

+ +
+
+ +

◆ rank

+ +
+
+ + + + +
uint Phytomer::rank
+
+ +

Definition at line 731 of file PlantArchitecture.h.

+ +
+
+ +

◆ shoot_index

+ +
+
+ + + + +
helios::int2 Phytomer::shoot_index
+
+ +

Definition at line 732 of file PlantArchitecture.h.

+ +
+
+ +

◆ time_since_dormancy

+ +
+
+ + + + +
float Phytomer::time_since_dormancy = 0
+
+ +

Definition at line 735 of file PlantArchitecture.h.

+ +
+
+ +

◆ vegetative_buds

+ +
+
+ + + + +
std::vector<std::vector<VegetativeBud> > Phytomer::vegetative_buds
+
+ +

Definition at line 740 of file PlantArchitecture.h.

+ +
+
+
The documentation for this struct was generated from the following files: +
+ + + + diff --git a/doc/html/struct_phytomer_parameters.html b/doc/html/struct_phytomer_parameters.html new file mode 100644 index 000000000..8d53c057e --- /dev/null +++ b/doc/html/struct_phytomer_parameters.html @@ -0,0 +1,375 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
+ +
PhytomerParameters Struct Reference
+
+
+ + + + + + + + +

+Public Member Functions

 PhytomerParameters ()
 Default constructor - does not set random number generator.
 
 PhytomerParameters (std::minstd_rand0 *generator)
 Constructor - sets random number generator.
 
+ + + + + + + + + + + + + +

+Data Fields

InternodeParameters internode
 
PetioleParameters petiole
 
LeafParameters leaf
 
PeduncleParameters peduncle
 
InflorescenceParameters inflorescence
 
void(* phytomer_creation_function )(std::shared_ptr< Phytomer > phytomer_ptr, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age) = nullptr
 
+ + + + + + + +

+Friends

class PlantArchitecture
 
class Phytomer
 
class Shoot
 
+

Detailed Description

+
+

Definition at line 339 of file PlantArchitecture.h.

+

Constructor & Destructor Documentation

+ +

◆ PhytomerParameters() [1/2]

+ +
+
+ + + + + + + +
PhytomerParameters::PhytomerParameters ()
+
+ +

Default constructor - does not set random number generator.

+ +

Definition at line 91 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ PhytomerParameters() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
PhytomerParameters::PhytomerParameters (std::minstd_rand0 * generator)
+
+explicit
+
+ +

Constructor - sets random number generator.

+ +

Definition at line 93 of file PlantArchitecture.cpp.

+ +
+
+

Friends And Related Function Documentation

+ +

◆ Phytomer

+ +
+
+ + + + + +
+ + + + +
friend class Phytomer
+
+friend
+
+ +

Definition at line 517 of file PlantArchitecture.h.

+ +
+
+ +

◆ PlantArchitecture

+ +
+
+ + + + + +
+ + + + +
friend class PlantArchitecture
+
+friend
+
+ +

Definition at line 516 of file PlantArchitecture.h.

+ +
+
+ +

◆ Shoot

+ +
+
+ + + + + +
+ + + + +
friend class Shoot
+
+friend
+
+ +

Definition at line 518 of file PlantArchitecture.h.

+ +
+
+

Field Documentation

+ +

◆ inflorescence

+ +
+
+ + + + +
InflorescenceParameters PhytomerParameters::inflorescence
+
+ +

Definition at line 498 of file PlantArchitecture.h.

+ +
+
+ +

◆ internode

+ +
+
+ + + + +
InternodeParameters PhytomerParameters::internode
+
+ +

Definition at line 490 of file PlantArchitecture.h.

+ +
+
+ +

◆ leaf

+ +
+
+ + + + +
LeafParameters PhytomerParameters::leaf
+
+ +

Definition at line 494 of file PlantArchitecture.h.

+ +
+
+ +

◆ peduncle

+ +
+
+ + + + +
PeduncleParameters PhytomerParameters::peduncle
+
+ +

Definition at line 496 of file PlantArchitecture.h.

+ +
+
+ +

◆ petiole

+ +
+
+ + + + +
PetioleParameters PhytomerParameters::petiole
+
+ +

Definition at line 492 of file PlantArchitecture.h.

+ +
+
+ +

◆ phytomer_creation_function

+ +
+
+ + + + +
void(* PhytomerParameters::phytomer_creation_function) (std::shared_ptr< Phytomer > phytomer_ptr, uint shoot_node_index, uint parent_shoot_node_index, uint shoot_max_nodes, uint rank, float plant_age) = nullptr
+
+
Parameters
+ + + + + + +
[in]phytomer_ptrPointer to the phytomer to which the function will be applied
[in]shoot_node_indexIndex of the phytomer within the shoot starting from 0 at the shoot base
[in]parent_shoot_node_indexNode index of the current shoot along it's parent shoot
[in]shoot_max_nodesMaximum number of phytomers in the shoot
[in]plant_ageAge of the plant in days
+
+
+ +

Definition at line 508 of file PlantArchitecture.h.

+ +
+
+
The documentation for this struct was generated from the following files: +
+ + + + diff --git a/doc/html/struct_plant_instance.html b/doc/html/struct_plant_instance.html new file mode 100644 index 000000000..75ff6743f --- /dev/null +++ b/doc/html/struct_plant_instance.html @@ -0,0 +1,317 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
+ +
PlantInstance Struct Reference
+
+
+ + + + +

+Public Member Functions

 PlantInstance (const helios::vec3 &a_base_position, float a_current_age)
 
+ + + + + + + + + + + + + + + + + + + +

+Data Fields

std::vector< std::shared_ptr< Shoot > > shoot_tree
 
helios::vec3 base_position
 
float current_age
 
float dd_to_dormancy_break = 0
 
float dd_to_flower_initiation = 0
 
float dd_to_flower_opening = 0
 
float dd_to_fruit_set = 0
 
float dd_to_fruit_maturity = 0
 
float dd_to_senescence = 0
 
+

Detailed Description

+
+

Definition at line 824 of file PlantArchitecture.h.

+

Constructor & Destructor Documentation

+ +

◆ PlantInstance()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
PlantInstance::PlantInstance (const helios::vec3a_base_position,
float a_current_age 
)
+
+inline
+
+ +

Definition at line 826 of file PlantArchitecture.h.

+ +
+
+

Field Documentation

+ +

◆ base_position

+ +
+
+ + + + +
helios::vec3 PlantInstance::base_position
+
+ +

Definition at line 828 of file PlantArchitecture.h.

+ +
+
+ +

◆ current_age

+ +
+
+ + + + +
float PlantInstance::current_age
+
+ +

Definition at line 829 of file PlantArchitecture.h.

+ +
+
+ +

◆ dd_to_dormancy_break

+ +
+
+ + + + +
float PlantInstance::dd_to_dormancy_break = 0
+
+ +

Definition at line 832 of file PlantArchitecture.h.

+ +
+
+ +

◆ dd_to_flower_initiation

+ +
+
+ + + + +
float PlantInstance::dd_to_flower_initiation = 0
+
+ +

Definition at line 833 of file PlantArchitecture.h.

+ +
+
+ +

◆ dd_to_flower_opening

+ +
+
+ + + + +
float PlantInstance::dd_to_flower_opening = 0
+
+ +

Definition at line 834 of file PlantArchitecture.h.

+ +
+
+ +

◆ dd_to_fruit_maturity

+ +
+
+ + + + +
float PlantInstance::dd_to_fruit_maturity = 0
+
+ +

Definition at line 836 of file PlantArchitecture.h.

+ +
+
+ +

◆ dd_to_fruit_set

+ +
+
+ + + + +
float PlantInstance::dd_to_fruit_set = 0
+
+ +

Definition at line 835 of file PlantArchitecture.h.

+ +
+
+ +

◆ dd_to_senescence

+ +
+
+ + + + +
float PlantInstance::dd_to_senescence = 0
+
+ +

Definition at line 837 of file PlantArchitecture.h.

+ +
+
+ +

◆ shoot_tree

+ +
+
+ + + + +
std::vector<std::shared_ptr<Shoot> > PlantInstance::shoot_tree
+
+ +

Definition at line 827 of file PlantArchitecture.h.

+ +
+
+
The documentation for this struct was generated from the following file: +
+ + + + diff --git a/doc/html/struct_radiation_band.html b/doc/html/struct_radiation_band.html index 13d6e799f..1c2cb2573 100644 --- a/doc/html/struct_radiation_band.html +++ b/doc/html/struct_radiation_band.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
+ +
RandomParameter_float Struct Reference
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 RandomParameter_float ()
 Constructor initializing to a constant default value of 0.
 
 RandomParameter_float (float val)
 Constructor initializing to a constant value.
 
 RandomParameter_float (std::minstd_rand0 *rand_generator)
 Constructor initializing the random number generator.
 
void initialize (float a_val, std::minstd_rand0 *rand_generator)
 
void initialize (std::minstd_rand0 *rand_generator)
 
RandomParameter_floatoperator= (float a)
 
void uniformDistribution (float minval, float maxval)
 
void normalDistribution (float mean, float std_dev)
 
void weibullDistribution (float shape, float scale)
 
float val ()
 
float resample ()
 
+ + + + + +

+Data Fields

std::string distribution
 
std::vector< float > distribution_parameters
 
+

Detailed Description

+
+

Definition at line 28 of file PlantArchitecture.h.

+

Constructor & Destructor Documentation

+ +

◆ RandomParameter_float() [1/3]

+ +
+
+ + + + + +
+ + + + + + + +
RandomParameter_float::RandomParameter_float ()
+
+inlineexplicit
+
+ +

Constructor initializing to a constant default value of 0.

+

In order to make this a randomly varying parameter, the initialize() method must be called to set the random number generator.

+ +

Definition at line 35 of file PlantArchitecture.h.

+ +
+
+ +

◆ RandomParameter_float() [2/3]

+ +
+
+ + + + + +
+ + + + + + + + +
RandomParameter_float::RandomParameter_float (float val)
+
+inlineexplicit
+
+ +

Constructor initializing to a constant value.

+

In order to make this a randomly varying parameter, the initialize() method must be called to set the random number generator.

+ +

Definition at line 46 of file PlantArchitecture.h.

+ +
+
+ +

◆ RandomParameter_float() [3/3]

+ +
+
+ + + + + +
+ + + + + + + + +
RandomParameter_float::RandomParameter_float (std::minstd_rand0 * rand_generator)
+
+inlineexplicit
+
+ +

Constructor initializing the random number generator.

+
Parameters
+ + +
[in]rand_generatorPointer to a random number generator. Note: it is recommended to use the random number generator from the Context, which can be retrieved using the getContextRandomGenerator() method.
+
+
+ +

Definition at line 57 of file PlantArchitecture.h.

+ +
+
+

Member Function Documentation

+ +

◆ initialize() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void RandomParameter_float::initialize (float a_val,
std::minstd_rand0 * rand_generator 
)
+
+inline
+
+ +

Definition at line 64 of file PlantArchitecture.h.

+ +
+
+ +

◆ initialize() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void RandomParameter_float::initialize (std::minstd_rand0 * rand_generator)
+
+inline
+
+ +

Definition at line 71 of file PlantArchitecture.h.

+ +
+
+ +

◆ normalDistribution()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void RandomParameter_float::normalDistribution (float mean,
float std_dev 
)
+
+inline
+
+ +

Definition at line 91 of file PlantArchitecture.h.

+ +
+
+ +

◆ operator=()

+ +
+
+ + + + + +
+ + + + + + + + +
RandomParameter_float & RandomParameter_float::operator= (float a)
+
+inline
+
+ +

Definition at line 78 of file PlantArchitecture.h.

+ +
+
+ +

◆ resample()

+ +
+
+ + + + + +
+ + + + + + + +
float RandomParameter_float::resample ()
+
+inline
+
+ +

Definition at line 110 of file PlantArchitecture.h.

+ +
+
+ +

◆ uniformDistribution()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void RandomParameter_float::uniformDistribution (float minval,
float maxval 
)
+
+inline
+
+ +

Definition at line 85 of file PlantArchitecture.h.

+ +
+
+ +

◆ val()

+ +
+
+ + + + + +
+ + + + + + + +
float RandomParameter_float::val ()
+
+inline
+
+ +

Definition at line 103 of file PlantArchitecture.h.

+ +
+
+ +

◆ weibullDistribution()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void RandomParameter_float::weibullDistribution (float shape,
float scale 
)
+
+inline
+
+ +

Definition at line 97 of file PlantArchitecture.h.

+ +
+
+

Field Documentation

+ +

◆ distribution

+ +
+
+ + + + +
std::string RandomParameter_float::distribution
+
+ +

Definition at line 130 of file PlantArchitecture.h.

+ +
+
+ +

◆ distribution_parameters

+ +
+
+ + + + +
std::vector<float> RandomParameter_float::distribution_parameters
+
+ +

Definition at line 131 of file PlantArchitecture.h.

+ +
+
+
The documentation for this struct was generated from the following file: +
+ + + + diff --git a/doc/html/struct_random_parameter__int.html b/doc/html/struct_random_parameter__int.html new file mode 100644 index 000000000..91709a4c3 --- /dev/null +++ b/doc/html/struct_random_parameter__int.html @@ -0,0 +1,336 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
+ +
RandomParameter_int Struct Reference
+
+
+ + + + + + + + + + + + + + +

+Public Member Functions

void initialize (int a_val, std::minstd_rand0 *rand_generator)
 
void initialize (std::minstd_rand0 *rand_generator)
 
RandomParameter_intoperator= (int a)
 
void uniformDistribution (int minval, int maxval)
 
int val ()
 
int resample ()
 
+

Detailed Description

+
+

Definition at line 141 of file PlantArchitecture.h.

+

Constructor & Destructor Documentation

+ +

◆ RandomParameter_int()

+ +
+
+ + + + + +
+ + + + + + + +
RandomParameter_int::RandomParameter_int ()
+
+inlineexplicit
+
+ +

Definition at line 144 of file PlantArchitecture.h.

+ +
+
+

Member Function Documentation

+ +

◆ initialize() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void RandomParameter_int::initialize (int a_val,
std::minstd_rand0 * rand_generator 
)
+
+inline
+
+ +

Definition at line 151 of file PlantArchitecture.h.

+ +
+
+ +

◆ initialize() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void RandomParameter_int::initialize (std::minstd_rand0 * rand_generator)
+
+inline
+
+ +

Definition at line 158 of file PlantArchitecture.h.

+ +
+
+ +

◆ operator=()

+ +
+
+ + + + + +
+ + + + + + + + +
RandomParameter_int & RandomParameter_int::operator= (int a)
+
+inline
+
+ +

Definition at line 165 of file PlantArchitecture.h.

+ +
+
+ +

◆ resample()

+ +
+
+ + + + + +
+ + + + + + + +
int RandomParameter_int::resample ()
+
+inline
+
+ +

Definition at line 185 of file PlantArchitecture.h.

+ +
+
+ +

◆ uniformDistribution()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void RandomParameter_int::uniformDistribution (int minval,
int maxval 
)
+
+inline
+
+ +

Definition at line 172 of file PlantArchitecture.h.

+ +
+
+ +

◆ val()

+ +
+
+ + + + + +
+ + + + + + + +
int RandomParameter_int::val ()
+
+inline
+
+ +

Definition at line 178 of file PlantArchitecture.h.

+ +
+
+
The documentation for this struct was generated from the following file: +
+ + + + diff --git a/doc/html/struct_scan_metadata.html b/doc/html/struct_scan_metadata.html index 2c96b7c7c..66e508a21 100644 --- a/doc/html/struct_scan_metadata.html +++ b/doc/html/struct_scan_metadata.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
+ +
Shoot Struct Reference
+
+
+ + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Shoot (uint plant_ID, int shoot_ID, int parent_shoot_ID, uint parent_node, uint parent_petiole_index, uint rank, const helios::vec3 &origin, const AxisRotation &shoot_base_rotation, uint current_node_number, float internode_length_shoot_initial, ShootParameters shoot_params, const std::string &shoot_type_label, PlantArchitecture *plant_architecture_ptr)
 
void buildShootPhytomers (float internode_radius, float internode_length, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction)
 
int addPhytomer (const PhytomerParameters &params, const helios::vec3 internode_base_position, const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction)
 
bool sampleChildShootType (std::string &child_shoot_type_label) const
 Randomly sample the type of a child shoot based on the probabilities defined in the shoot parameters.
 
void terminateApicalBud ()
 
void terminateAxillaryVegetativeBuds ()
 
void breakDormancy ()
 
void makeDormant ()
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Data Fields

uint current_node_number
 
helios::vec3 origin
 
AxisRotation base_rotation
 
const int ID
 
const int parent_shoot_ID
 
const uint plantID
 
const uint parent_node_index
 
const uint rank
 
const uint parent_petiole_index
 
float assimilate_pool
 
bool dormant
 
uint dormancy_cycles = 0
 
bool meristem_is_alive = true
 
float phyllochron_counter = 0
 
float curvature_perturbation = 0
 
const float internode_length_max_shoot_initial
 
std::map< int, int > childIDs
 
ShootParameters shoot_parameters
 
std::string shoot_type_label
 
std::vector< std::shared_ptr< Phytomer > > phytomers
 
PlantArchitectureplant_architecture_ptr
 
helios::Contextcontext_ptr
 
+

Detailed Description

+
+

Definition at line 759 of file PlantArchitecture.h.

+

Constructor & Destructor Documentation

+ +

◆ Shoot()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Shoot::Shoot (uint plant_ID,
int shoot_ID,
int parent_shoot_ID,
uint parent_node,
uint parent_petiole_index,
uint rank,
const helios::vec3origin,
const AxisRotationshoot_base_rotation,
uint current_node_number,
float internode_length_shoot_initial,
ShootParameters shoot_params,
const std::string & shoot_type_label,
PlantArchitectureplant_architecture_ptr 
)
+
+ +

Definition at line 1320 of file PlantArchitecture.cpp.

+ +
+
+

Member Function Documentation

+ +

◆ addPhytomer()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
int Shoot::addPhytomer (const PhytomerParametersparams,
const helios::vec3 internode_base_position,
const AxisRotationshoot_base_rotation,
float internode_radius,
float internode_length_max,
float internode_length_scale_factor_fraction,
float leaf_scale_factor_fraction 
)
+
+ +

Definition at line 351 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ breakDormancy()

+ +
+
+ + + + + + + +
void Shoot::breakDormancy ()
+
+ +

Definition at line 450 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ buildShootPhytomers()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Shoot::buildShootPhytomers (float internode_radius,
float internode_length,
float internode_length_scale_factor_fraction,
float leaf_scale_factor_fraction 
)
+
+ +

Definition at line 1329 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ makeDormant()

+ +
+
+ + + + + + + +
void Shoot::makeDormant ()
+
+ +

Definition at line 482 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ sampleChildShootType()

+ +
+
+ + + + + + + + +
bool Shoot::sampleChildShootType (std::string & child_shoot_type_label) const
+
+ +

Randomly sample the type of a child shoot based on the probabilities defined in the shoot parameters.

+
Parameters
+ + +
[out]child_shoot_type_labelLabel of the randomly selected child shoot type.
+
+
+
Returns
false if the bud dies, true if the bud survives and will produce a new shoot.
+ +

Definition at line 1348 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ terminateApicalBud()

+ +
+
+ + + + + + + +
void Shoot::terminateApicalBud ()
+
+ +

Definition at line 509 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ terminateAxillaryVegetativeBuds()

+ +
+
+ + + + + + + +
void Shoot::terminateAxillaryVegetativeBuds ()
+
+ +

Definition at line 513 of file PlantArchitecture.cpp.

+ +
+
+

Field Documentation

+ +

◆ assimilate_pool

+ +
+
+ + + + +
float Shoot::assimilate_pool
+
+ +

Definition at line 793 of file PlantArchitecture.h.

+ +
+
+ +

◆ base_rotation

+ +
+
+ + + + +
AxisRotation Shoot::base_rotation
+
+ +

Definition at line 784 of file PlantArchitecture.h.

+ +
+
+ +

◆ childIDs

+ +
+
+ + + + +
std::map<int,int> Shoot::childIDs
+
+ +

Definition at line 810 of file PlantArchitecture.h.

+ +
+
+ +

◆ context_ptr

+ +
+
+ + + + +
helios::Context* Shoot::context_ptr
+
+ +

Definition at line 820 of file PlantArchitecture.h.

+ +
+
+ +

◆ current_node_number

+ +
+
+ + + + +
uint Shoot::current_node_number
+
+ +

Definition at line 780 of file PlantArchitecture.h.

+ +
+
+ +

◆ curvature_perturbation

+ +
+
+ + + + +
float Shoot::curvature_perturbation = 0
+
+ +

Definition at line 805 of file PlantArchitecture.h.

+ +
+
+ +

◆ dormancy_cycles

+ +
+
+ + + + +
uint Shoot::dormancy_cycles = 0
+
+ +

Definition at line 799 of file PlantArchitecture.h.

+ +
+
+ +

◆ dormant

+ +
+
+ + + + +
bool Shoot::dormant
+
+ +

Definition at line 798 of file PlantArchitecture.h.

+ +
+
+ +

◆ ID

+ +
+
+ + + + +
const int Shoot::ID
+
+ +

Definition at line 786 of file PlantArchitecture.h.

+ +
+
+ +

◆ internode_length_max_shoot_initial

+ +
+
+ + + + +
const float Shoot::internode_length_max_shoot_initial
+
+ +

Definition at line 807 of file PlantArchitecture.h.

+ +
+
+ +

◆ meristem_is_alive

+ +
+
+ + + + +
bool Shoot::meristem_is_alive = true
+
+ +

Definition at line 801 of file PlantArchitecture.h.

+ +
+
+ +

◆ origin

+ +
+
+ + + + +
helios::vec3 Shoot::origin
+
+ +

Definition at line 782 of file PlantArchitecture.h.

+ +
+
+ +

◆ parent_node_index

+ +
+
+ + + + +
const uint Shoot::parent_node_index
+
+ +

Definition at line 789 of file PlantArchitecture.h.

+ +
+
+ +

◆ parent_petiole_index

+ +
+
+ + + + +
const uint Shoot::parent_petiole_index
+
+ +

Definition at line 791 of file PlantArchitecture.h.

+ +
+
+ +

◆ parent_shoot_ID

+ +
+
+ + + + +
const int Shoot::parent_shoot_ID
+
+ +

Definition at line 787 of file PlantArchitecture.h.

+ +
+
+ +

◆ phyllochron_counter

+ +
+
+ + + + +
float Shoot::phyllochron_counter = 0
+
+ +

Definition at line 803 of file PlantArchitecture.h.

+ +
+
+ +

◆ phytomers

+ +
+
+ + + + +
std::vector<std::shared_ptr<Phytomer> > Shoot::phytomers
+
+ +

Definition at line 816 of file PlantArchitecture.h.

+ +
+
+ +

◆ plant_architecture_ptr

+ +
+
+ + + + +
PlantArchitecture* Shoot::plant_architecture_ptr
+
+ +

Definition at line 818 of file PlantArchitecture.h.

+ +
+
+ +

◆ plantID

+ +
+
+ + + + +
const uint Shoot::plantID
+
+ +

Definition at line 788 of file PlantArchitecture.h.

+ +
+
+ +

◆ rank

+ +
+
+ + + + +
const uint Shoot::rank
+
+ +

Definition at line 790 of file PlantArchitecture.h.

+ +
+
+ +

◆ shoot_parameters

+ +
+
+ + + + +
ShootParameters Shoot::shoot_parameters
+
+ +

Definition at line 812 of file PlantArchitecture.h.

+ +
+
+ +

◆ shoot_type_label

+ +
+
+ + + + +
std::string Shoot::shoot_type_label
+
+ +

Definition at line 814 of file PlantArchitecture.h.

+ +
+
+
The documentation for this struct was generated from the following files: +
+ + + + diff --git a/doc/html/struct_shoot_parameters.html b/doc/html/struct_shoot_parameters.html new file mode 100644 index 000000000..adf8e238f --- /dev/null +++ b/doc/html/struct_shoot_parameters.html @@ -0,0 +1,725 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
+ +
ShootParameters Struct Reference
+
+
+ + + + + + + + + + + + +

+Public Member Functions

 ShootParameters ()
 Default constructor - does not set random number generator.
 
 ShootParameters (std::minstd_rand0 *generator)
 Constructor - sets random number generator.
 
void defineChildShootTypes (const std::vector< std::string > &child_shoot_type_labels, const std::vector< float > &child_shoot_type_probabilities)
 
ShootParametersoperator= (const ShootParameters &a)
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Data Fields

PhytomerParameters phytomer_parameters
 
RandomParameter_int max_nodes
 
RandomParameter_float internode_radius_initial
 
RandomParameter_float child_insertion_angle_tip
 
RandomParameter_float child_insertion_angle_decay_rate
 
RandomParameter_float child_internode_length_max
 
RandomParameter_float child_internode_length_min
 
RandomParameter_float child_internode_length_decay_rate
 
RandomParameter_float base_roll
 
RandomParameter_float base_yaw
 
RandomParameter_float gravitropic_curvature
 
RandomParameter_float tortuosity
 
RandomParameter_float phyllochron
 
uint leaf_flush_count
 
RandomParameter_float elongation_rate
 
RandomParameter_float girth_growth_rate
 
RandomParameter_float internode_radius_max
 
RandomParameter_float vegetative_bud_break_probability
 
RandomParameter_float flower_bud_break_probability
 
RandomParameter_float fruit_set_probability
 
RandomParameter_float vegetative_bud_break_time
 
bool flowers_require_dormancy
 
bool growth_requires_dormancy
 
bool determinate_shoot_growth
 
+ + + + + +

+Friends

class PlantArchitecture
 
class Shoot
 
+

Detailed Description

+
+

Definition at line 522 of file PlantArchitecture.h.

+

Constructor & Destructor Documentation

+ +

◆ ShootParameters() [1/2]

+ +
+
+ + + + + + + +
ShootParameters::ShootParameters ()
+
+ +

Default constructor - does not set random number generator.

+ +

Definition at line 144 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ ShootParameters() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
ShootParameters::ShootParameters (std::minstd_rand0 * generator)
+
+explicit
+
+ +

Constructor - sets random number generator.

+ +

Definition at line 146 of file PlantArchitecture.cpp.

+ +
+
+

Member Function Documentation

+ +

◆ defineChildShootTypes()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void ShootParameters::defineChildShootTypes (const std::vector< std::string > & child_shoot_type_labels,
const std::vector< float > & child_shoot_type_probabilities 
)
+
+ +

Definition at line 189 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ operator=()

+ +
+
+ + + + + +
+ + + + + + + + +
ShootParameters & ShootParameters::operator= (const ShootParametersa)
+
+inline
+
+ +

Definition at line 582 of file PlantArchitecture.h.

+ +
+
+

Friends And Related Function Documentation

+ +

◆ PlantArchitecture

+ +
+
+ + + + + +
+ + + + +
friend class PlantArchitecture
+
+friend
+
+ +

Definition at line 634 of file PlantArchitecture.h.

+ +
+
+ +

◆ Shoot

+ +
+
+ + + + + +
+ + + + +
friend class Shoot
+
+friend
+
+ +

Definition at line 635 of file PlantArchitecture.h.

+ +
+
+

Field Documentation

+ +

◆ base_roll

+ +
+
+ + + + +
RandomParameter_float ShootParameters::base_roll
+
+ +

Definition at line 545 of file PlantArchitecture.h.

+ +
+
+ +

◆ base_yaw

+ +
+
+ + + + +
RandomParameter_float ShootParameters::base_yaw
+
+ +

Definition at line 546 of file PlantArchitecture.h.

+ +
+
+ +

◆ child_insertion_angle_decay_rate

+ +
+
+ + + + +
RandomParameter_float ShootParameters::child_insertion_angle_decay_rate
+
+ +

Definition at line 539 of file PlantArchitecture.h.

+ +
+
+ +

◆ child_insertion_angle_tip

+ +
+
+ + + + +
RandomParameter_float ShootParameters::child_insertion_angle_tip
+
+ +

Definition at line 538 of file PlantArchitecture.h.

+ +
+
+ +

◆ child_internode_length_decay_rate

+ +
+
+ + + + +
RandomParameter_float ShootParameters::child_internode_length_decay_rate
+
+ +

Definition at line 543 of file PlantArchitecture.h.

+ +
+
+ +

◆ child_internode_length_max

+ +
+
+ + + + +
RandomParameter_float ShootParameters::child_internode_length_max
+
+ +

Definition at line 541 of file PlantArchitecture.h.

+ +
+
+ +

◆ child_internode_length_min

+ +
+
+ + + + +
RandomParameter_float ShootParameters::child_internode_length_min
+
+ +

Definition at line 542 of file PlantArchitecture.h.

+ +
+
+ +

◆ determinate_shoot_growth

+ +
+
+ + + + +
bool ShootParameters::determinate_shoot_growth
+
+ +

Definition at line 576 of file PlantArchitecture.h.

+ +
+
+ +

◆ elongation_rate

+ +
+
+ + + + +
RandomParameter_float ShootParameters::elongation_rate
+
+ +

Definition at line 557 of file PlantArchitecture.h.

+ +
+
+ +

◆ flower_bud_break_probability

+ +
+
+ + + + +
RandomParameter_float ShootParameters::flower_bud_break_probability
+
+ +

Definition at line 566 of file PlantArchitecture.h.

+ +
+
+ +

◆ flowers_require_dormancy

+ +
+
+ + + + +
bool ShootParameters::flowers_require_dormancy
+
+ +

Definition at line 573 of file PlantArchitecture.h.

+ +
+
+ +

◆ fruit_set_probability

+ +
+
+ + + + +
RandomParameter_float ShootParameters::fruit_set_probability
+
+ +

Definition at line 569 of file PlantArchitecture.h.

+ +
+
+ +

◆ girth_growth_rate

+ +
+
+ + + + +
RandomParameter_float ShootParameters::girth_growth_rate
+
+ +

Definition at line 559 of file PlantArchitecture.h.

+ +
+
+ +

◆ gravitropic_curvature

+ +
+
+ + + + +
RandomParameter_float ShootParameters::gravitropic_curvature
+
+ +

Definition at line 548 of file PlantArchitecture.h.

+ +
+
+ +

◆ growth_requires_dormancy

+ +
+
+ + + + +
bool ShootParameters::growth_requires_dormancy
+
+ +

Definition at line 574 of file PlantArchitecture.h.

+ +
+
+ +

◆ internode_radius_initial

+ +
+
+ + + + +
RandomParameter_float ShootParameters::internode_radius_initial
+
+ +

Definition at line 536 of file PlantArchitecture.h.

+ +
+
+ +

◆ internode_radius_max

+ +
+
+ + + + +
RandomParameter_float ShootParameters::internode_radius_max
+
+ +

Definition at line 560 of file PlantArchitecture.h.

+ +
+
+ +

◆ leaf_flush_count

+ +
+
+ + + + +
uint ShootParameters::leaf_flush_count
+
+ +

Definition at line 555 of file PlantArchitecture.h.

+ +
+
+ +

◆ max_nodes

+ +
+
+ + + + +
RandomParameter_int ShootParameters::max_nodes
+
+ +

Definition at line 534 of file PlantArchitecture.h.

+ +
+
+ +

◆ phyllochron

+ +
+
+ + + + +
RandomParameter_float ShootParameters::phyllochron
+
+ +

Definition at line 554 of file PlantArchitecture.h.

+ +
+
+ +

◆ phytomer_parameters

+ +
+
+ + + + +
PhytomerParameters ShootParameters::phytomer_parameters
+
+ +

Definition at line 530 of file PlantArchitecture.h.

+ +
+
+ +

◆ tortuosity

+ +
+
+ + + + +
RandomParameter_float ShootParameters::tortuosity
+
+ +

Definition at line 550 of file PlantArchitecture.h.

+ +
+
+ +

◆ vegetative_bud_break_probability

+ +
+
+ + + + +
RandomParameter_float ShootParameters::vegetative_bud_break_probability
+
+ +

Definition at line 563 of file PlantArchitecture.h.

+ +
+
+ +

◆ vegetative_bud_break_time

+ +
+
+ + + + +
RandomParameter_float ShootParameters::vegetative_bud_break_time
+
+ +

Definition at line 571 of file PlantArchitecture.h.

+ +
+
+
The documentation for this struct was generated from the following files: +
+ + + + diff --git a/doc/html/struct_shx.html b/doc/html/struct_shx.html index 129303fa4..80784cbda 100644 --- a/doc/html/struct_shx.html +++ b/doc/html/struct_shx.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.14 +
+
+
+ + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
+ +
VegetativeBud Struct Reference
+
+
+ + + + + + + + +

+Data Fields

BudState state = BUD_DORMANT
 
std::string shoot_type_label
 
uint shoot_ID = -1
 
+

Detailed Description

+
+

Definition at line 313 of file PlantArchitecture.h.

+

Field Documentation

+ +

◆ shoot_ID

+ +
+
+ + + + +
uint VegetativeBud::shoot_ID = -1
+
+ +

Definition at line 320 of file PlantArchitecture.h.

+ +
+
+ +

◆ shoot_type_label

+ +
+
+ + + + +
std::string VegetativeBud::shoot_type_label
+
+ +

Definition at line 318 of file PlantArchitecture.h.

+ +
+
+ +

◆ state

+ +
+
+ + + + +
BudState VegetativeBud::state = BUD_DORMANT
+
+ +

Definition at line 316 of file PlantArchitecture.h.

+ +
+
+
The documentation for this struct was generated from the following file: +
+ + + + diff --git a/doc/html/struct_walnut_canopy_parameters.html b/doc/html/struct_walnut_canopy_parameters.html index e87b97f18..707d7a47b 100644 --- a/doc/html/struct_walnut_canopy_parameters.html +++ b/doc/html/struct_walnut_canopy_parameters.html @@ -38,14 +38,14 @@ Logo -
 v1.3.13 +
 v1.3.14
- +