diff --git a/README.md b/README.md index 76beed753..11cef50a5 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ For complete documentation of this software, please consult https://baileylab.ucdavis.edu/software/helios, or open the file doc/html/index.html in a web browser. -Helios is a C++ API for 3D physical simulation of plant and environmental systems. In order to build and compile the core library, you will need to install a C/C++ compiler (recommended are the GNU C compilers version 5.5+), and CMake. In order to run many of the model plug-ins, you will need to install NVIDIA CUDA 9.0+, and a GPU with compute capability 3.5+. The software has been tested on Linux, Mac, and Windows platforms. +Helios is a C++ library for 3D physical simulation of plant and environmental systems. It can generate and manipulate plant and other geometric objects, which can feed into biophysical model plug-ins such as radiation transfer, photosynthesis, and evapotranspiration, among others. + +In order to build and compile the core library, you will need to install a C/C++ compiler (recommended are the GNU C compilers version 7.0+), and CMake. In order to run many of the model plug-ins, you will need to install NVIDIA CUDA 10.2+, and a GPU with compute capability 5.0+. The software has been tested on Linux, Mac, and Windows platforms. The YouTube channel linked above has a number of tutorials for getting started. ![Almond Reconstruction](doc/images/AlmondVarietyReconstruction.png) \ No newline at end of file diff --git a/core/include/global.h b/core/include/global.h index 996410dd5..e8acd8393 100755 --- a/core/include/global.h +++ b/core/include/global.h @@ -1047,6 +1047,14 @@ namespace helios{ */ std::string getFilePath( const std::string &filepath, bool trailingslash = true ); +//! Check whether output file and/or directory is valid. Add a trailing slash if it is a directory. +/** + * \param[inout] output_path + * \param[in] allowable_file_extensions + * \return True if directory/file was valid, false otherwise + */ + bool validateOutputPath(std::string &output_directory, const std::vector &allowable_file_extensions = {}); + //! Read values contained in a text file into a one-dimensional vector of floats /** * \param[in] filepath Path to text file diff --git a/core/src/Context_fileIO.cpp b/core/src/Context_fileIO.cpp index 1e6d9e826..b1e9ae705 100644 --- a/core/src/Context_fileIO.cpp +++ b/core/src/Context_fileIO.cpp @@ -2676,6 +2676,14 @@ void Context::writeXML( const char* filename, const std::vector &UUIDs, bo std::string xmlfilename = filename; + if( !validateOutputPath(xmlfilename) ){ + helios_runtime_error("ERROR (Context::writeXML): Invalid output file " + xmlfilename + "."); + } + + if( getFileName(xmlfilename).empty() ){ + helios_runtime_error("ERROR (Context::writeXML): Invalid output file " + xmlfilename + ". No file name was provided."); + } + auto file_extension = getFileExtension(filename); if( file_extension != ".xml" && file_extension != ".XML" ) { // append xml to file name xmlfilename.append(".xml"); @@ -4160,7 +4168,7 @@ void Context::writeOBJ( const std::string &filename, const std::vector &UU } } - if( !std::filesystem::exists(file_path) ){ + if( !file_path.empty() && !std::filesystem::exists(file_path) ){ if( !std::filesystem::create_directory(file_path) ){ std::cout << "failed. Directory " << file_path << " does not exist and it could not be created - OBJ file will not be written." << std::endl; return; diff --git a/core/src/global.cpp b/core/src/global.cpp index 383407e3d..320c87837 100755 --- a/core/src/global.cpp +++ b/core/src/global.cpp @@ -2991,73 +2991,78 @@ float helios::point_distance( const helios::vec3 &p1 , const helios::vec3 &p2){ } std::string helios::getFileExtension( const std::string &filepath ){ - std::string ext; - - if( filepath.find_last_of('.')
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_a_p_i.html b/doc/html/_a_p_i.html index 84312fcd5..44d5aeb9b 100644 --- a/doc/html/_a_p_i.html +++ b/doc/html/_a_p_i.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_aerial_li_d_a_r_8cpp.html b/doc/html/_aerial_li_d_a_r_8cpp.html index dac6ecbad..682eb3386 100644 --- a/doc/html/_aerial_li_d_a_r_8cpp.html +++ b/doc/html/_aerial_li_d_a_r_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_aerial_li_d_a_r_8cpp_source.html b/doc/html/_aerial_li_d_a_r_8cpp_source.html index 63e5c8f22..afa324093 100644 --- a/doc/html/_aerial_li_d_a_r_8cpp_source.html +++ b/doc/html/_aerial_li_d_a_r_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_aerial_li_d_a_r_8cu.html b/doc/html/_aerial_li_d_a_r_8cu.html index 87d1472e8..47e38efd2 100644 --- a/doc/html/_aerial_li_d_a_r_8cu.html +++ b/doc/html/_aerial_li_d_a_r_8cu.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_aerial_li_d_a_r_8cu_source.html b/doc/html/_aerial_li_d_a_r_8cu_source.html index 0bbf912c1..420880f6f 100644 --- a/doc/html/_aerial_li_d_a_r_8cu_source.html +++ b/doc/html/_aerial_li_d_a_r_8cu_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_aerial_li_d_a_r_8h.html b/doc/html/_aerial_li_d_a_r_8h.html index 1ddc0a1f2..911920335 100644 --- a/doc/html/_aerial_li_d_a_r_8h.html +++ b/doc/html/_aerial_li_d_a_r_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_aerial_li_d_a_r_8h_source.html b/doc/html/_aerial_li_d_a_r_8h_source.html index 94e6d1765..7287065ab 100644 --- a/doc/html/_aerial_li_d_a_r_8h_source.html +++ b/doc/html/_aerial_li_d_a_r_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_aerial_li_d_a_r_doc.html b/doc/html/_aerial_li_d_a_r_doc.html index 4cf1bf522..ae9f96a0c 100644 --- a/doc/html/_aerial_li_d_a_r_doc.html +++ b/doc/html/_aerial_li_d_a_r_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_assets_8cpp.html b/doc/html/_assets_8cpp.html index c1c27f9ec..a6afa2b9c 100644 --- a/doc/html/_assets_8cpp.html +++ b/doc/html/_assets_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_assets_8cpp_source.html b/doc/html/_assets_8cpp_source.html index 7be9ef9ce..19bf67d0e 100644 --- a/doc/html/_assets_8cpp_source.html +++ b/doc/html/_assets_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -1259,7 +1259,7 @@
std::vector< uint > getObjectPrimitiveUUIDs(uint ObjID) const
Get primitive UUIDs associated with compound object (single object ID input)
Definition Context.cpp:2887
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition Context.cpp:1568
-
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...
+
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 scalePrimitive(uint UUID, const helios::vec3 &S)
Scale a primitive using its UUID relative to the origin (0,0,0)
Definition Context.cpp:1481
void scalePrimitiveAboutPoint(uint UUID, const helios::vec3 &S, const helios::vec3 point)
Scale a primitive using its UUID about an arbitrary point in space.
Definition Context.cpp:1502
SphericalCoord nullrotation
Default null SphericalCoord that applies no rotation.
Definition global.cpp:57
diff --git a/doc/html/_assets_8h_source.html b/doc/html/_assets_8h_source.html index dfe48ce46..a88e1fdd4 100644 --- a/doc/html/_assets_8h_source.html +++ b/doc/html/_assets_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_b_l_conductance_doc.html b/doc/html/_b_l_conductance_doc.html index aa6e8c40d..0ce4fde2a 100644 --- a/doc/html/_b_l_conductance_doc.html +++ b/doc/html/_b_l_conductance_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_boundary_layer_conductance_model_8cpp.html b/doc/html/_boundary_layer_conductance_model_8cpp.html index 7ad165cda..95cc3a767 100644 --- a/doc/html/_boundary_layer_conductance_model_8cpp.html +++ b/doc/html/_boundary_layer_conductance_model_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_boundary_layer_conductance_model_8cpp_source.html b/doc/html/_boundary_layer_conductance_model_8cpp_source.html index 3822f5d92..3cfc04ab5 100644 --- a/doc/html/_boundary_layer_conductance_model_8cpp_source.html +++ b/doc/html/_boundary_layer_conductance_model_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_boundary_layer_conductance_model_8h.html b/doc/html/_boundary_layer_conductance_model_8h.html index d4edc8a0f..32de3d5fc 100644 --- a/doc/html/_boundary_layer_conductance_model_8h.html +++ b/doc/html/_boundary_layer_conductance_model_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_boundary_layer_conductance_model_8h_source.html b/doc/html/_boundary_layer_conductance_model_8h_source.html index 853d7e9e9..0a1651780 100644 --- a/doc/html/_boundary_layer_conductance_model_8h_source.html +++ b/doc/html/_boundary_layer_conductance_model_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_c_lion_i_d_e.html b/doc/html/_c_lion_i_d_e.html index 0538382cd..9e8a5ec70 100644 --- a/doc/html/_c_lion_i_d_e.html +++ b/doc/html/_c_lion_i_d_e.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_camera_calibration_8cpp.html b/doc/html/_camera_calibration_8cpp.html index 5e84cc570..4de50b226 100644 --- a/doc/html/_camera_calibration_8cpp.html +++ b/doc/html/_camera_calibration_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_camera_calibration_8cpp_source.html b/doc/html/_camera_calibration_8cpp_source.html index fd6059119..1855f8a05 100644 --- a/doc/html/_camera_calibration_8cpp_source.html +++ b/doc/html/_camera_calibration_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_camera_calibration_8h.html b/doc/html/_camera_calibration_8h.html index ad53239a4..8db674de6 100644 --- a/doc/html/_camera_calibration_8h.html +++ b/doc/html/_camera_calibration_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_camera_calibration_8h_source.html b/doc/html/_camera_calibration_8h_source.html index 81a971070..de5e5e117 100644 --- a/doc/html/_camera_calibration_8h_source.html +++ b/doc/html/_camera_calibration_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_canopy_generator_8cpp.html b/doc/html/_canopy_generator_8cpp.html index d5a47486f..128bb7746 100644 --- a/doc/html/_canopy_generator_8cpp.html +++ b/doc/html/_canopy_generator_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_canopy_generator_8cpp_source.html b/doc/html/_canopy_generator_8cpp_source.html index 01342ddc8..9996e1d37 100644 --- a/doc/html/_canopy_generator_8cpp_source.html +++ b/doc/html/_canopy_generator_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_canopy_generator_8h.html b/doc/html/_canopy_generator_8h.html index b3d371de6..c391f8766 100644 --- a/doc/html/_canopy_generator_8h.html +++ b/doc/html/_canopy_generator_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_canopy_generator_8h_source.html b/doc/html/_canopy_generator_8h_source.html index baaf3f2ff..5d1c0b58c 100644 --- a/doc/html/_canopy_generator_8h_source.html +++ b/doc/html/_canopy_generator_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_canopy_generator_doc.html b/doc/html/_canopy_generator_doc.html index 9353faa55..084810a80 100644 --- a/doc/html/_canopy_generator_doc.html +++ b/doc/html/_canopy_generator_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_carbohydrate_model_8cpp.html b/doc/html/_carbohydrate_model_8cpp.html index 659f0d8b0..b1e334a40 100644 --- a/doc/html/_carbohydrate_model_8cpp.html +++ b/doc/html/_carbohydrate_model_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_carbohydrate_model_8cpp_source.html b/doc/html/_carbohydrate_model_8cpp_source.html index 4646d35c6..58cea1895 100644 --- a/doc/html/_carbohydrate_model_8cpp_source.html +++ b/doc/html/_carbohydrate_model_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_choosing_c_u_d_a.html b/doc/html/_choosing_c_u_d_a.html index 6ad24486f..fd0273f78 100644 --- a/doc/html/_choosing_c_u_d_a.html +++ b/doc/html/_choosing_c_u_d_a.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_context_8cpp.html b/doc/html/_context_8cpp.html index 3e769a5bd..8fe0ed6cc 100644 --- a/doc/html/_context_8cpp.html +++ b/doc/html/_context_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_context_8cpp_source.html b/doc/html/_context_8cpp_source.html index a4669becc..1d3c7b648 100644 --- a/doc/html/_context_8cpp_source.html +++ b/doc/html/_context_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -9326,7 +9326,7 @@
vec3 nullorigin
Default null vec3 that gives the origin (0,0,0)
Definition global.cpp:58
helios::int2 getImageResolutionJPEG(const std::string &filename)
Function to read a JPEG image file into pixel data array.
Definition global.cpp:1744
void readPNG(const std::string &filename, uint &width, uint &height, std::vector< helios::RGBAcolor > &pixel_data)
Function to read a PNG image file into pixel data array.
Definition global.cpp:1505
-
std::string getFileStem(const std::string &filepath)
Parse a file string to get the filename without extension.
Definition global.cpp:3019
+
std::string getFileStem(const std::string &filepath)
Parse a file string to get the filename without extension.
Definition global.cpp:2998
void makeIdentityMatrix(float(&T)[16])
Construct an identity matrix.
Definition global.cpp:555
SphericalCoord nullrotation
Default null SphericalCoord that applies no rotation.
Definition global.cpp:57
std::vector< std::vector< bool > > readPNGAlpha(const std::string &filename)
Function to read the alpha channel from a PNG image.
Definition global.cpp:1406
diff --git a/doc/html/_context_8h.html b/doc/html/_context_8h.html index 4757716db..270700f05 100644 --- a/doc/html/_context_8h.html +++ b/doc/html/_context_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_context_8h_source.html b/doc/html/_context_8h_source.html index 98cf21388..95fcb722b 100644 --- a/doc/html/_context_8h_source.html +++ b/doc/html/_context_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -2961,7 +2961,7 @@
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.
void scaleObjectAboutPoint(uint ObjID, const helios::vec3 &scalefact, const helios::vec3 &point)
Method to scale a compound object in the x-, y- and z-directions.
Definition Context.cpp:2877
float getTubeObjectSegmentVolume(uint ObjID, uint segment_index) const
get the volume of a segment within a Tube object
Definition Context.cpp:8120
-
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...
+
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:7071
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:2622
@@ -2972,7 +2972,7 @@
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1396
void getObjectBoundingBox(uint ObjID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single object.
Definition Context.cpp:7942
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:6997
-
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.
+
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:3916
void cleanDeletedUUIDs(std::vector< uint > &UUIDs) const
Delete UUIDs from vector if primitives no longer exist (1D vector)
Definition Context.cpp:1783
uint getConeObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Cone object from the context
Definition Context.cpp:8194
@@ -3051,13 +3051,13 @@
std::vector< uint > getObjectPrimitiveUUIDs(uint ObjID) const
Get primitive UUIDs associated with compound object (single object ID input)
Definition Context.cpp:2887
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition Context.cpp:1568
helios::int2 getPrimitiveTextureSize(uint UUID) const
Get the size (number of pixels) of primitive texture map image.
Definition Context.cpp:7111
-
void writeOBJ(const std::string &filename) const
Write geometry in the Context to a Wavefront file (.obj)
+
void writeOBJ(const std::string &filename) const
Write geometry in the Context to a Wavefront file (.obj)
void renameGlobalData(const char *old_label, const char *new_label)
Rename global data.
helios::vec3 getTriangleVertex(uint UUID, uint number) const
Get a single vertex of a Triangle based on an index.
Definition Context.cpp:1701
helios::Time getTime() const
Get the simulation time.
Definition Context.cpp:1164
helios::RGBcolor getPrimitiveColorRGB(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition Context.cpp:7075
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...
+
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:2026
void duplicatePrimitiveData(uint UUID, const char *old_label, const char *new_label)
Duplicate/copy primitive data.
uint getDiskObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Disk object from the context
Definition Context.cpp:8190
@@ -3084,7 +3084,7 @@
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.
std::vector< helios::vec3 > getTubeObjectNodes(uint ObjID) const
get the nodes of a Tube object from the context
Definition Context.cpp:8104
-
void writePLY(const char *filename) const
Write geometry in the Context to a Stanford polygon file (.ply)
+
void writePLY(const char *filename) const
Write geometry in the Context to a Stanford polygon file (.ply)
helios::vec3 getTileObjectCenter(uint ObjID) const
Get the Cartesian (x,y,z) center position of a tile object.
Definition Context.cpp:8060
void scaleTubeGirth(uint ObjID, float scale_factor)
Scale the girth for all nodes of a tube object.
Definition Context.cpp:8138
void setGlobalData(const char *label, const int &data)
Add global data value (int)
@@ -3097,7 +3097,7 @@
void scalePrimitive(uint UUID, const helios::vec3 &S)
Scale a primitive using its UUID relative to the origin (0,0,0)
Definition Context.cpp:1481
Tube * getTubeObjectPointer(uint ObjID) const
Get a pointer to a Tube Compound Object.
Definition Context.cpp:3466
helios::vec2 getPatchSize(uint UUID) const
Get the size of a patch element.
Definition Context.cpp:1674
-
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 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.
std::vector< helios::vec3 > getTileObjectVertices(uint ObjID) const
get the vertices of a tile object from the context
Definition Context.cpp:8080
void markGeometryDirty()
Mark the Context geometry as "dirty", meaning that the geometry has been modified since last set as c...
Definition Context.cpp:151
void getPrimitiveBoundingBox(uint UUID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single primitive.
Definition Context.cpp:7001
diff --git a/doc/html/_context__data_8cpp.html b/doc/html/_context__data_8cpp.html index 7f1d747b2..425f2e0ad 100644 --- a/doc/html/_context__data_8cpp.html +++ b/doc/html/_context__data_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_context__data_8cpp_source.html b/doc/html/_context__data_8cpp_source.html index 1b1bc06ad..cd0d4a315 100644 --- a/doc/html/_context__data_8cpp_source.html +++ b/doc/html/_context__data_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_context__file_i_o_8cpp.html b/doc/html/_context__file_i_o_8cpp.html index b24b6591e..16d148034 100644 --- a/doc/html/_context__file_i_o_8cpp.html +++ b/doc/html/_context__file_i_o_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_context__file_i_o_8cpp_source.html b/doc/html/_context__file_i_o_8cpp_source.html index a8376fb75..14f0f7b4d 100644 --- a/doc/html/_context__file_i_o_8cpp_source.html +++ b/doc/html/_context__file_i_o_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -2823,2186 +2823,2194 @@
2676
2677 std::string xmlfilename = filename;
2678
-
2679 auto file_extension = getFileExtension(filename);
-
2680 if( file_extension != ".xml" && file_extension != ".XML" ) { // append xml to file name
-
2681 xmlfilename.append(".xml");
-
2682 }
-
2683
-
2684 std::vector<uint> objectIDs = getUniquePrimitiveParentObjectIDs( UUIDs, false );
-
2685
-
2686 std::ofstream outfile;
-
2687 outfile.open(xmlfilename);
-
2688
-
2689 outfile << "<?xml version=\"1.0\"?>\n\n";
-
2690
-
2691 outfile << "<helios>\n\n";
-
2692
-
2693 // -- time/date -- //
-
2694
-
2695 Date date = getDate();
+
2679 if( !validateOutputPath(xmlfilename) ){
+
2680 helios_runtime_error("ERROR (Context::writeXML): Invalid output file " + xmlfilename + ".");
+
2681 }
+
2682
+
2683 if( getFileName(xmlfilename).empty() ){
+
2684 helios_runtime_error("ERROR (Context::writeXML): Invalid output file " + xmlfilename + ". No file name was provided.");
+
2685 }
+
2686
+
2687 auto file_extension = getFileExtension(filename);
+
2688 if( file_extension != ".xml" && file_extension != ".XML" ) { // append xml to file name
+
2689 xmlfilename.append(".xml");
+
2690 }
+
2691
+
2692 std::vector<uint> objectIDs = getUniquePrimitiveParentObjectIDs( UUIDs, false );
+
2693
+
2694 std::ofstream outfile;
+
2695 outfile.open(xmlfilename);
2696
-
2697 outfile << " <date>" << std::endl;
+
2697 outfile << "<?xml version=\"1.0\"?>\n\n";
2698
-
2699 outfile << "\t<day>" << date.day << "</day>" << std::endl;
-
2700 outfile << "\t<month>" << date.month << "</month>" << std::endl;
-
2701 outfile << "\t<year>" << date.year << "</year>" << std::endl;
+
2699 outfile << "<helios>\n\n";
+
2700
+
2701 // -- time/date -- //
2702
-
2703 outfile << " </date>" << std::endl;
+
2703 Date date = getDate();
2704
-
2705 Time time = getTime();
+
2705 outfile << " <date>" << std::endl;
2706
-
2707 outfile << " <time>" << std::endl;
-
2708
-
2709 outfile << "\t<hour>" << time.hour << "</hour>" << std::endl;
-
2710 outfile << "\t<minute>" << time.minute << "</minute>" << std::endl;
-
2711 outfile << "\t<second>" << time.second << "</second>" << std::endl;
+
2707 outfile << "\t<day>" << date.day << "</day>" << std::endl;
+
2708 outfile << "\t<month>" << date.month << "</month>" << std::endl;
+
2709 outfile << "\t<year>" << date.year << "</year>" << std::endl;
+
2710
+
2711 outfile << " </date>" << std::endl;
2712
-
2713 outfile << " </time>" << std::endl;
+
2713 Time time = getTime();
2714
-
2715 // -- primitives -- //
+
2715 outfile << " <time>" << std::endl;
2716
-
2717 for( uint UUID : UUIDs ){
-
2718
-
2719 uint p = UUID;
+
2717 outfile << "\t<hour>" << time.hour << "</hour>" << std::endl;
+
2718 outfile << "\t<minute>" << time.minute << "</minute>" << std::endl;
+
2719 outfile << "\t<second>" << time.second << "</second>" << std::endl;
2720
-
2721 if( !doesPrimitiveExist(p) ){
-
2722 if( doesObjectExist(p) ){
-
2723 helios_runtime_error("ERROR (Context::writeXML): Primitive with UUID of " + std::to_string(p) + " does not exist. There is a compound object with this ID - did you mean to call Context::writeXML_byobject()?");
-
2724 }else{
-
2725 helios_runtime_error("ERROR (Context::writeXML): Primitive with UUID of " + std::to_string(p) + " does not exist.");
-
2726 }
-
2727 }
+
2721 outfile << " </time>" << std::endl;
+
2722
+
2723 // -- primitives -- //
+
2724
+
2725 for( uint UUID : UUIDs ){
+
2726
+
2727 uint p = UUID;
2728
-
2729 Primitive* prim = getPrimitivePointer_private(p);
-
2730
-
2731 uint parent_objID = prim->getParentObjectID();
-
2732
-
2733 RGBAcolor color = prim->getColorRGBA();
-
2734
-
2735 std::string texture_file = prim->getTextureFile();
+
2729 if( !doesPrimitiveExist(p) ){
+
2730 if( doesObjectExist(p) ){
+
2731 helios_runtime_error("ERROR (Context::writeXML): Primitive with UUID of " + std::to_string(p) + " does not exist. There is a compound object with this ID - did you mean to call Context::writeXML_byobject()?");
+
2732 }else{
+
2733 helios_runtime_error("ERROR (Context::writeXML): Primitive with UUID of " + std::to_string(p) + " does not exist.");
+
2734 }
+
2735 }
2736
-
2737 std::vector<std::string> pdata = prim->listPrimitiveData();
+
2737 Primitive* prim = getPrimitivePointer_private(p);
2738
-
2739 //if this primitive is a member of a compound object that is "complete", don't write it to XML
-
2740 //\todo This was included to make the XML files more efficient and avoid writing all object primitives to file. However, it doesn't work in some cases because it makes it hard to figure out the primitive transformations.
-
2741// if( parent_objID>0 && areObjectPrimitivesComplete(parent_objID) ){
-
2742// continue;
-
2743// }
+
2739 uint parent_objID = prim->getParentObjectID();
+
2740
+
2741 RGBAcolor color = prim->getColorRGBA();
+
2742
+
2743 std::string texture_file = prim->getTextureFile();
2744
-
2745 if( prim->getType()==PRIMITIVE_TYPE_PATCH ){
-
2746 outfile << " <patch>" << std::endl;
-
2747 }else if( prim->getType()==PRIMITIVE_TYPE_TRIANGLE ){
-
2748 outfile << " <triangle>" << std::endl;
-
2749 }else if( prim->getType()==PRIMITIVE_TYPE_VOXEL ){
-
2750 outfile << " <voxel>" << std::endl;
-
2751 }
+
2745 std::vector<std::string> pdata = prim->listPrimitiveData();
+
2746
+
2747 //if this primitive is a member of a compound object that is "complete", don't write it to XML
+
2748 //\todo This was included to make the XML files more efficient and avoid writing all object primitives to file. However, it doesn't work in some cases because it makes it hard to figure out the primitive transformations.
+
2749// if( parent_objID>0 && areObjectPrimitivesComplete(parent_objID) ){
+
2750// continue;
+
2751// }
2752
-
2753 outfile << "\t<UUID>" << p << "</UUID>" << std::endl;
-
2754
-
2755 if( parent_objID>0 ){
-
2756 outfile << "\t<objID>" << parent_objID << "</objID>" << std::endl;
-
2757 }
-
2758
-
2759 outfile << "\t<color>" << color.r << " " << color.g << " " << color.b << " " << color.a << "</color>" << std::endl;
-
2760 if( prim->hasTexture() ){
-
2761 outfile << "\t<texture>" << texture_file << "</texture>" << std::endl;
-
2762 }
-
2763
-
2764 if( !pdata.empty() ){
-
2765 writeDataToXMLstream( "primitive", pdata, prim, outfile );
-
2766 }
-
2767
-
2768 //Patches
-
2769 if( prim->getType()==PRIMITIVE_TYPE_PATCH ){
-
2770
-
2771 Patch* patch = getPatchPointer_private(p);
-
2772 float transform[16];
-
2773 prim->getTransformationMatrix(transform);
-
2774
-
2775 outfile << "\t<transform>";
-
2776 for(float i : transform){
-
2777 outfile << i << " ";
-
2778 }
-
2779 outfile << "</transform>" << std::endl;
-
2780 std::vector<vec2> uv = patch->getTextureUV();
-
2781 if( !uv.empty() ){
-
2782 outfile << "\t<textureUV>" << std::flush;
-
2783 for( int i=0; i<uv.size(); i++ ){
-
2784 outfile << uv.at(i).x << " " << uv.at(i).y << std::flush;
-
2785 if( i!=uv.size()-1 ){
-
2786 outfile << " " << std::flush;
-
2787 }
-
2788 }
-
2789 outfile << "</textureUV>" << std::endl;
-
2790 }
- -
2792 outfile << "\t<solid_fraction>" << getPrimitiveSolidFraction(p) << "</solid_fraction>\n";
-
2793 }
-
2794 outfile << " </patch>" << std::endl;
-
2795
-
2796 //Triangles
-
2797 }else if( prim->getType()==PRIMITIVE_TYPE_TRIANGLE ){
-
2798
-
2799 float transform[16];
-
2800 prim->getTransformationMatrix(transform);
-
2801
-
2802 outfile << "\t<transform>";
-
2803 for(float i : transform){
-
2804 outfile << i << " ";
-
2805 }
-
2806 outfile << "</transform>" << std::endl;
-
2807
-
2808 std::vector<vec2> uv = getTrianglePointer_private(p)->getTextureUV();
-
2809 if( !uv.empty() ){
-
2810 outfile << "\t<textureUV>" << std::flush;
-
2811 for( int i=0; i<uv.size(); i++ ){
-
2812 outfile << uv.at(i).x << " " << uv.at(i).y << std::flush;
-
2813 if( i!=uv.size()-1 ){
-
2814 outfile << " " << std::flush;
-
2815 }
-
2816 }
-
2817 outfile << "</textureUV>" << std::endl;
-
2818 }
- -
2820 outfile << "\t<solid_fraction>" << getPrimitiveSolidFraction(p) << "</solid_fraction>\n";
-
2821 }
-
2822 outfile << " </triangle>" << std::endl;
-
2823
-
2824 //Voxels
-
2825 }else if( prim->getType()==PRIMITIVE_TYPE_VOXEL ){
-
2826
-
2827 float transform[16];
-
2828 prim->getTransformationMatrix(transform);
-
2829
-
2830 outfile << "\t<transform>";
-
2831 for(float i : transform){
-
2832 outfile << i << " ";
-
2833 }
-
2834 outfile << "</transform>" << std::endl;
- -
2836 outfile << "\t<solid_fraction>" << getPrimitiveSolidFraction(p) << "</solid_fraction>\n";
-
2837 }
-
2838
-
2839 outfile << " </voxel>" << std::endl;
-
2840
-
2841 }
-
2842
-
2843 }
-
2844
-
2845 // -- objects -- //
+
2753 if( prim->getType()==PRIMITIVE_TYPE_PATCH ){
+
2754 outfile << " <patch>" << std::endl;
+
2755 }else if( prim->getType()==PRIMITIVE_TYPE_TRIANGLE ){
+
2756 outfile << " <triangle>" << std::endl;
+
2757 }else if( prim->getType()==PRIMITIVE_TYPE_VOXEL ){
+
2758 outfile << " <voxel>" << std::endl;
+
2759 }
+
2760
+
2761 outfile << "\t<UUID>" << p << "</UUID>" << std::endl;
+
2762
+
2763 if( parent_objID>0 ){
+
2764 outfile << "\t<objID>" << parent_objID << "</objID>" << std::endl;
+
2765 }
+
2766
+
2767 outfile << "\t<color>" << color.r << " " << color.g << " " << color.b << " " << color.a << "</color>" << std::endl;
+
2768 if( prim->hasTexture() ){
+
2769 outfile << "\t<texture>" << texture_file << "</texture>" << std::endl;
+
2770 }
+
2771
+
2772 if( !pdata.empty() ){
+
2773 writeDataToXMLstream( "primitive", pdata, prim, outfile );
+
2774 }
+
2775
+
2776 //Patches
+
2777 if( prim->getType()==PRIMITIVE_TYPE_PATCH ){
+
2778
+
2779 Patch* patch = getPatchPointer_private(p);
+
2780 float transform[16];
+
2781 prim->getTransformationMatrix(transform);
+
2782
+
2783 outfile << "\t<transform>";
+
2784 for(float i : transform){
+
2785 outfile << i << " ";
+
2786 }
+
2787 outfile << "</transform>" << std::endl;
+
2788 std::vector<vec2> uv = patch->getTextureUV();
+
2789 if( !uv.empty() ){
+
2790 outfile << "\t<textureUV>" << std::flush;
+
2791 for( int i=0; i<uv.size(); i++ ){
+
2792 outfile << uv.at(i).x << " " << uv.at(i).y << std::flush;
+
2793 if( i!=uv.size()-1 ){
+
2794 outfile << " " << std::flush;
+
2795 }
+
2796 }
+
2797 outfile << "</textureUV>" << std::endl;
+
2798 }
+ +
2800 outfile << "\t<solid_fraction>" << getPrimitiveSolidFraction(p) << "</solid_fraction>\n";
+
2801 }
+
2802 outfile << " </patch>" << std::endl;
+
2803
+
2804 //Triangles
+
2805 }else if( prim->getType()==PRIMITIVE_TYPE_TRIANGLE ){
+
2806
+
2807 float transform[16];
+
2808 prim->getTransformationMatrix(transform);
+
2809
+
2810 outfile << "\t<transform>";
+
2811 for(float i : transform){
+
2812 outfile << i << " ";
+
2813 }
+
2814 outfile << "</transform>" << std::endl;
+
2815
+
2816 std::vector<vec2> uv = getTrianglePointer_private(p)->getTextureUV();
+
2817 if( !uv.empty() ){
+
2818 outfile << "\t<textureUV>" << std::flush;
+
2819 for( int i=0; i<uv.size(); i++ ){
+
2820 outfile << uv.at(i).x << " " << uv.at(i).y << std::flush;
+
2821 if( i!=uv.size()-1 ){
+
2822 outfile << " " << std::flush;
+
2823 }
+
2824 }
+
2825 outfile << "</textureUV>" << std::endl;
+
2826 }
+ +
2828 outfile << "\t<solid_fraction>" << getPrimitiveSolidFraction(p) << "</solid_fraction>\n";
+
2829 }
+
2830 outfile << " </triangle>" << std::endl;
+
2831
+
2832 //Voxels
+
2833 }else if( prim->getType()==PRIMITIVE_TYPE_VOXEL ){
+
2834
+
2835 float transform[16];
+
2836 prim->getTransformationMatrix(transform);
+
2837
+
2838 outfile << "\t<transform>";
+
2839 for(float i : transform){
+
2840 outfile << i << " ";
+
2841 }
+
2842 outfile << "</transform>" << std::endl;
+ +
2844 outfile << "\t<solid_fraction>" << getPrimitiveSolidFraction(p) << "</solid_fraction>\n";
+
2845 }
2846
-
2847 for( auto o : objectIDs ){
+
2847 outfile << " </voxel>" << std::endl;
2848
-
2849 CompoundObject* obj = objects.at(o);
+
2849 }
2850
-
2851 std::string texture_file = obj->getTextureFile();
+
2851 }
2852
-
2853 std::vector<std::string> odata = obj->listObjectData();
+
2853 // -- objects -- //
2854
-
2855 if( obj->getObjectType()==OBJECT_TYPE_TILE ){
-
2856 outfile << " <tile>" << std::endl;
-
2857 }else if( obj->getObjectType()==OBJECT_TYPE_BOX ){
-
2858 outfile << " <box>" << std::endl;
-
2859 }else if( obj->getObjectType()==OBJECT_TYPE_CONE ){
-
2860 outfile << " <cone>" << std::endl;
-
2861 }else if( obj->getObjectType()==OBJECT_TYPE_DISK ){
-
2862 outfile << " <disk>" << std::endl;
-
2863 }else if( obj->getObjectType()==OBJECT_TYPE_SPHERE ){
-
2864 outfile << " <sphere>" << std::endl;
-
2865 }else if( obj->getObjectType()==OBJECT_TYPE_TUBE ){
-
2866 outfile << " <tube>" << std::endl;
-
2867 }else if( obj->getObjectType()==OBJECT_TYPE_POLYMESH ){
-
2868 outfile << " <polymesh>" << std::endl;
-
2869 }
-
2870
-
2871 outfile << "\t<objID>" << o << "</objID>" << std::endl;
-
2872 if( obj->hasTexture() ){
-
2873 outfile << "\t<texture>" << texture_file << "</texture>" << std::endl;
-
2874 }
-
2875
-
2876 if( !odata.empty() ){
-
2877 writeDataToXMLstream( "object", odata, obj, outfile );
-
2878 }
-
2879
-
2880 std::vector<std::string> pdata_labels;
-
2881 std::vector<HeliosDataType> pdata_types;
-
2882 std::vector<uint> primitiveUUIDs = obj->getPrimitiveUUIDs();
-
2883 for( uint UUID : primitiveUUIDs ){
-
2884 std::vector<std::string> labels = getPrimitivePointer_private(UUID)->listPrimitiveData();
-
2885 for( int i=0; i<labels.size(); i++ ){
-
2886 if( find(pdata_labels.begin(),pdata_labels.end(),labels.at(i)) == pdata_labels.end() ){
-
2887 pdata_labels.push_back(labels.at(i));
-
2888 pdata_types.push_back(getPrimitiveDataType(UUID,labels.at(i).c_str()));
-
2889 }
-
2890 }
-
2891 }
-
2892 for( size_t l=0; l<pdata_labels.size(); l++ ) {
-
2893 if( pdata_types.at(l)==HELIOS_TYPE_FLOAT ) {
-
2894 outfile << "\t<primitive_data_float " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
-
2895 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
-
2896 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
-
2897 std::vector<float> data;
-
2898 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
-
2899 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
-
2900 for (size_t i = 0; i < data.size(); i++) {
-
2901 outfile << data.at(i) << std::flush;
-
2902 }
-
2903 outfile << " </data>" << std::endl;
-
2904 }
-
2905 }
-
2906 outfile << "\t</primitive_data_float>" << std::endl;
-
2907 }else if( pdata_types.at(l)==HELIOS_TYPE_DOUBLE ) {
-
2908 outfile << "\t<primitive_data_double " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
-
2909 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
-
2910 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
-
2911 std::vector<double> data;
-
2912 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
-
2913 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
-
2914 for (size_t i = 0; i < data.size(); i++) {
-
2915 outfile << data.at(i) << std::flush;
-
2916 }
-
2917 outfile << " </data>" << std::endl;
-
2918 }
-
2919 }
-
2920 outfile << "\t</primitive_data_double>" << std::endl;
-
2921 }else if( pdata_types.at(l)==HELIOS_TYPE_UINT ) {
-
2922 outfile << "\t<primitive_data_uint " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
-
2923 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
-
2924 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
-
2925 std::vector<uint> data;
-
2926 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
-
2927 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
-
2928 for (size_t i = 0; i < data.size(); i++) {
-
2929 outfile << data.at(i) << std::flush;
-
2930 }
-
2931 outfile << " </data>" << std::endl;
-
2932 }
-
2933 }
-
2934 outfile << "\t</primitive_data_uint>" << std::endl;
-
2935 }else if( pdata_types.at(l)==HELIOS_TYPE_INT ) {
-
2936 outfile << "\t<primitive_data_int " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
-
2937 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
-
2938 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
-
2939 std::vector<int> data;
-
2940 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
-
2941 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
-
2942 for (size_t i = 0; i < data.size(); i++) {
-
2943 outfile << data.at(i) << std::flush;
-
2944 }
-
2945 outfile << " </data>" << std::endl;
-
2946 }
-
2947 }
-
2948 outfile << "\t</primitive_data_int>" << std::endl;
-
2949 }else if( pdata_types.at(l)==HELIOS_TYPE_INT2 ) {
-
2950 outfile << "\t<primitive_data_int2 " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
-
2951 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
-
2952 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
-
2953 std::vector<int2> data;
-
2954 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
-
2955 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
-
2956 for (size_t i = 0; i < data.size(); i++) {
-
2957 outfile << data.at(i).x << " " << data.at(i).y << std::flush;
-
2958 }
-
2959 outfile << " </data>" << std::endl;
-
2960 }
-
2961 }
-
2962 outfile << "\t</primitive_data_int2>" << std::endl;
-
2963 }else if( pdata_types.at(l)==HELIOS_TYPE_INT3 ) {
-
2964 outfile << "\t<primitive_data_int3 " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
-
2965 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
-
2966 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
-
2967 std::vector<int3> data;
-
2968 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
-
2969 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
-
2970 for (size_t i = 0; i < data.size(); i++) {
-
2971 outfile << data.at(i).x << " " << data.at(i).y << " " << data.at(i).z << std::flush;
-
2972 }
-
2973 outfile << " </data>" << std::endl;
-
2974 }
-
2975 }
-
2976 outfile << "\t</primitive_data_int3>" << std::endl;
-
2977 }else if( pdata_types.at(l)==HELIOS_TYPE_INT4 ) {
-
2978 outfile << "\t<primitive_data_int4 " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
-
2979 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
-
2980 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
-
2981 std::vector<int4> data;
-
2982 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
-
2983 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
-
2984 for (size_t i = 0; i < data.size(); i++) {
-
2985 outfile << data.at(i).x << " " << data.at(i).y << " " << data.at(i).z << " " << data.at(i).w << std::flush;
-
2986 }
-
2987 outfile << " </data>" << std::endl;
-
2988 }
-
2989 }
-
2990 outfile << "\t</primitive_data_int4>" << std::endl;
-
2991 }else if( pdata_types.at(l)==HELIOS_TYPE_VEC2 ) {
-
2992 outfile << "\t<primitive_data_vec2 " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
-
2993 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
-
2994 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
-
2995 std::vector<vec2> data;
-
2996 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
-
2997 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
-
2998 for (size_t i = 0; i < data.size(); i++) {
-
2999 outfile << data.at(i).x << " " << data.at(i).y << std::flush;
-
3000 }
-
3001 outfile << " </data>" << std::endl;
-
3002 }
-
3003 }
-
3004 outfile << "\t</primitive_data_vec2>" << std::endl;
-
3005 }else if( pdata_types.at(l)==HELIOS_TYPE_VEC3 ) {
-
3006 outfile << "\t<primitive_data_vec3 " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
-
3007 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
-
3008 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
-
3009 std::vector<vec3> data;
-
3010 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
-
3011 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
-
3012 for (size_t i = 0; i < data.size(); i++) {
-
3013 outfile << data.at(i).x << " " << data.at(i).y << " " << data.at(i).z << std::flush;
-
3014 }
-
3015 outfile << " </data>" << std::endl;
-
3016 }
-
3017 }
-
3018 outfile << "\t</primitive_data_vec3>" << std::endl;
-
3019 }else if( pdata_types.at(l)==HELIOS_TYPE_VEC4 ) {
-
3020 outfile << "\t<primitive_data_vec4 " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
-
3021 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
-
3022 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
-
3023 std::vector<vec4> data;
-
3024 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
-
3025 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
-
3026 for (size_t i = 0; i < data.size(); i++) {
-
3027 outfile << data.at(i).x << " " << data.at(i).y << " " << data.at(i).z << " " << data.at(i).w << std::flush;
-
3028 }
-
3029 outfile << " </data>" << std::endl;
-
3030 }
-
3031 }
-
3032 outfile << "\t</primitive_data_vec4>" << std::endl;
-
3033 }else if( pdata_types.at(l)==HELIOS_TYPE_STRING ) {
-
3034 outfile << "\t<primitive_data_string " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
-
3035 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
-
3036 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
-
3037 std::vector<std::string> data;
-
3038 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
-
3039 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
-
3040 for (size_t i = 0; i < data.size(); i++) {
-
3041 outfile << data.at(i) << std::flush;
-
3042 }
-
3043 outfile << " </data>" << std::endl;
-
3044 }
-
3045 }
-
3046 outfile << "\t</primitive_data_string>" << std::endl;
-
3047 }
-
3048
-
3049
-
3050 }
-
3051
-
3052 //Tiles
-
3053 if( obj->getObjectType()==OBJECT_TYPE_TILE ){
-
3054
-
3055 Tile* tile = getTileObjectPointer(o);
+
2855 for( auto o : objectIDs ){
+
2856
+
2857 CompoundObject* obj = objects.at(o);
+
2858
+
2859 std::string texture_file = obj->getTextureFile();
+
2860
+
2861 std::vector<std::string> odata = obj->listObjectData();
+
2862
+
2863 if( obj->getObjectType()==OBJECT_TYPE_TILE ){
+
2864 outfile << " <tile>" << std::endl;
+
2865 }else if( obj->getObjectType()==OBJECT_TYPE_BOX ){
+
2866 outfile << " <box>" << std::endl;
+
2867 }else if( obj->getObjectType()==OBJECT_TYPE_CONE ){
+
2868 outfile << " <cone>" << std::endl;
+
2869 }else if( obj->getObjectType()==OBJECT_TYPE_DISK ){
+
2870 outfile << " <disk>" << std::endl;
+
2871 }else if( obj->getObjectType()==OBJECT_TYPE_SPHERE ){
+
2872 outfile << " <sphere>" << std::endl;
+
2873 }else if( obj->getObjectType()==OBJECT_TYPE_TUBE ){
+
2874 outfile << " <tube>" << std::endl;
+
2875 }else if( obj->getObjectType()==OBJECT_TYPE_POLYMESH ){
+
2876 outfile << " <polymesh>" << std::endl;
+
2877 }
+
2878
+
2879 outfile << "\t<objID>" << o << "</objID>" << std::endl;
+
2880 if( obj->hasTexture() ){
+
2881 outfile << "\t<texture>" << texture_file << "</texture>" << std::endl;
+
2882 }
+
2883
+
2884 if( !odata.empty() ){
+
2885 writeDataToXMLstream( "object", odata, obj, outfile );
+
2886 }
+
2887
+
2888 std::vector<std::string> pdata_labels;
+
2889 std::vector<HeliosDataType> pdata_types;
+
2890 std::vector<uint> primitiveUUIDs = obj->getPrimitiveUUIDs();
+
2891 for( uint UUID : primitiveUUIDs ){
+
2892 std::vector<std::string> labels = getPrimitivePointer_private(UUID)->listPrimitiveData();
+
2893 for( int i=0; i<labels.size(); i++ ){
+
2894 if( find(pdata_labels.begin(),pdata_labels.end(),labels.at(i)) == pdata_labels.end() ){
+
2895 pdata_labels.push_back(labels.at(i));
+
2896 pdata_types.push_back(getPrimitiveDataType(UUID,labels.at(i).c_str()));
+
2897 }
+
2898 }
+
2899 }
+
2900 for( size_t l=0; l<pdata_labels.size(); l++ ) {
+
2901 if( pdata_types.at(l)==HELIOS_TYPE_FLOAT ) {
+
2902 outfile << "\t<primitive_data_float " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
+
2903 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
+
2904 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
+
2905 std::vector<float> data;
+
2906 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
+
2907 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
+
2908 for (size_t i = 0; i < data.size(); i++) {
+
2909 outfile << data.at(i) << std::flush;
+
2910 }
+
2911 outfile << " </data>" << std::endl;
+
2912 }
+
2913 }
+
2914 outfile << "\t</primitive_data_float>" << std::endl;
+
2915 }else if( pdata_types.at(l)==HELIOS_TYPE_DOUBLE ) {
+
2916 outfile << "\t<primitive_data_double " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
+
2917 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
+
2918 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
+
2919 std::vector<double> data;
+
2920 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
+
2921 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
+
2922 for (size_t i = 0; i < data.size(); i++) {
+
2923 outfile << data.at(i) << std::flush;
+
2924 }
+
2925 outfile << " </data>" << std::endl;
+
2926 }
+
2927 }
+
2928 outfile << "\t</primitive_data_double>" << std::endl;
+
2929 }else if( pdata_types.at(l)==HELIOS_TYPE_UINT ) {
+
2930 outfile << "\t<primitive_data_uint " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
+
2931 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
+
2932 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
+
2933 std::vector<uint> data;
+
2934 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
+
2935 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
+
2936 for (size_t i = 0; i < data.size(); i++) {
+
2937 outfile << data.at(i) << std::flush;
+
2938 }
+
2939 outfile << " </data>" << std::endl;
+
2940 }
+
2941 }
+
2942 outfile << "\t</primitive_data_uint>" << std::endl;
+
2943 }else if( pdata_types.at(l)==HELIOS_TYPE_INT ) {
+
2944 outfile << "\t<primitive_data_int " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
+
2945 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
+
2946 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
+
2947 std::vector<int> data;
+
2948 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
+
2949 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
+
2950 for (size_t i = 0; i < data.size(); i++) {
+
2951 outfile << data.at(i) << std::flush;
+
2952 }
+
2953 outfile << " </data>" << std::endl;
+
2954 }
+
2955 }
+
2956 outfile << "\t</primitive_data_int>" << std::endl;
+
2957 }else if( pdata_types.at(l)==HELIOS_TYPE_INT2 ) {
+
2958 outfile << "\t<primitive_data_int2 " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
+
2959 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
+
2960 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
+
2961 std::vector<int2> data;
+
2962 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
+
2963 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
+
2964 for (size_t i = 0; i < data.size(); i++) {
+
2965 outfile << data.at(i).x << " " << data.at(i).y << std::flush;
+
2966 }
+
2967 outfile << " </data>" << std::endl;
+
2968 }
+
2969 }
+
2970 outfile << "\t</primitive_data_int2>" << std::endl;
+
2971 }else if( pdata_types.at(l)==HELIOS_TYPE_INT3 ) {
+
2972 outfile << "\t<primitive_data_int3 " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
+
2973 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
+
2974 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
+
2975 std::vector<int3> data;
+
2976 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
+
2977 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
+
2978 for (size_t i = 0; i < data.size(); i++) {
+
2979 outfile << data.at(i).x << " " << data.at(i).y << " " << data.at(i).z << std::flush;
+
2980 }
+
2981 outfile << " </data>" << std::endl;
+
2982 }
+
2983 }
+
2984 outfile << "\t</primitive_data_int3>" << std::endl;
+
2985 }else if( pdata_types.at(l)==HELIOS_TYPE_INT4 ) {
+
2986 outfile << "\t<primitive_data_int4 " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
+
2987 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
+
2988 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
+
2989 std::vector<int4> data;
+
2990 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
+
2991 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
+
2992 for (size_t i = 0; i < data.size(); i++) {
+
2993 outfile << data.at(i).x << " " << data.at(i).y << " " << data.at(i).z << " " << data.at(i).w << std::flush;
+
2994 }
+
2995 outfile << " </data>" << std::endl;
+
2996 }
+
2997 }
+
2998 outfile << "\t</primitive_data_int4>" << std::endl;
+
2999 }else if( pdata_types.at(l)==HELIOS_TYPE_VEC2 ) {
+
3000 outfile << "\t<primitive_data_vec2 " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
+
3001 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
+
3002 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
+
3003 std::vector<vec2> data;
+
3004 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
+
3005 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
+
3006 for (size_t i = 0; i < data.size(); i++) {
+
3007 outfile << data.at(i).x << " " << data.at(i).y << std::flush;
+
3008 }
+
3009 outfile << " </data>" << std::endl;
+
3010 }
+
3011 }
+
3012 outfile << "\t</primitive_data_vec2>" << std::endl;
+
3013 }else if( pdata_types.at(l)==HELIOS_TYPE_VEC3 ) {
+
3014 outfile << "\t<primitive_data_vec3 " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
+
3015 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
+
3016 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
+
3017 std::vector<vec3> data;
+
3018 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
+
3019 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
+
3020 for (size_t i = 0; i < data.size(); i++) {
+
3021 outfile << data.at(i).x << " " << data.at(i).y << " " << data.at(i).z << std::flush;
+
3022 }
+
3023 outfile << " </data>" << std::endl;
+
3024 }
+
3025 }
+
3026 outfile << "\t</primitive_data_vec3>" << std::endl;
+
3027 }else if( pdata_types.at(l)==HELIOS_TYPE_VEC4 ) {
+
3028 outfile << "\t<primitive_data_vec4 " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
+
3029 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
+
3030 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
+
3031 std::vector<vec4> data;
+
3032 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
+
3033 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
+
3034 for (size_t i = 0; i < data.size(); i++) {
+
3035 outfile << data.at(i).x << " " << data.at(i).y << " " << data.at(i).z << " " << data.at(i).w << std::flush;
+
3036 }
+
3037 outfile << " </data>" << std::endl;
+
3038 }
+
3039 }
+
3040 outfile << "\t</primitive_data_vec4>" << std::endl;
+
3041 }else if( pdata_types.at(l)==HELIOS_TYPE_STRING ) {
+
3042 outfile << "\t<primitive_data_string " << "label=\"" << pdata_labels.at(l) << "\">" << std::endl;
+
3043 for (size_t p = 0; p < primitiveUUIDs.size(); p++) {
+
3044 if (doesPrimitiveDataExist(primitiveUUIDs.at(p), pdata_labels.at(l).c_str())) {
+
3045 std::vector<std::string> data;
+
3046 getPrimitiveData(primitiveUUIDs.at(p), pdata_labels.at(l).c_str(), data);
+
3047 outfile << "\t\t<data label=\"" << p << "\"> " << std::flush;
+
3048 for (size_t i = 0; i < data.size(); i++) {
+
3049 outfile << data.at(i) << std::flush;
+
3050 }
+
3051 outfile << " </data>" << std::endl;
+
3052 }
+
3053 }
+
3054 outfile << "\t</primitive_data_string>" << std::endl;
+
3055 }
3056
-
3057 float transform[16];
-
3058 tile->getTransformationMatrix(transform);
+
3057
+
3058 }
3059
-
3060 int2 subdiv = tile->getSubdivisionCount();
-
3061 outfile << "\t<subdivisions>" << subdiv.x << " " << subdiv.y << "</subdivisions>" << std::endl;
+
3060 //Tiles
+
3061 if( obj->getObjectType()==OBJECT_TYPE_TILE ){
3062
-
3063 outfile << "\t<transform> ";
-
3064 for(float i : transform){
-
3065 outfile << i << " ";
-
3066 }
-
3067 outfile << "</transform>" << std::endl;
-
3068
-
3069 outfile << " </tile>" << std::endl;
+
3063 Tile* tile = getTileObjectPointer(o);
+
3064
+
3065 float transform[16];
+
3066 tile->getTransformationMatrix(transform);
+
3067
+
3068 int2 subdiv = tile->getSubdivisionCount();
+
3069 outfile << "\t<subdivisions>" << subdiv.x << " " << subdiv.y << "</subdivisions>" << std::endl;
3070
-
3071 //Spheres
-
3072 }else if( obj->getObjectType()==OBJECT_TYPE_SPHERE ){
-
3073
-
3074 Sphere* sphere = getSphereObjectPointer(o);
-
3075
-
3076 float transform[16];
-
3077 sphere->getTransformationMatrix(transform);
+
3071 outfile << "\t<transform> ";
+
3072 for(float i : transform){
+
3073 outfile << i << " ";
+
3074 }
+
3075 outfile << "</transform>" << std::endl;
+
3076
+
3077 outfile << " </tile>" << std::endl;
3078
-
3079 outfile << "\t<transform> ";
-
3080 for(float i : transform){
-
3081 outfile << i << " ";
-
3082 }
-
3083 outfile << "</transform>" << std::endl;
-
3084
-
3085 uint subdiv = sphere->getSubdivisionCount();
-
3086 outfile << "\t<subdivisions> " << subdiv << " </subdivisions>" << std::endl;
-
3087
-
3088 outfile << " </sphere>" << std::endl;
-
3089
-
3090 //Tubes
-
3091 }else if( obj->getObjectType()==OBJECT_TYPE_TUBE ) {
+
3079 //Spheres
+
3080 }else if( obj->getObjectType()==OBJECT_TYPE_SPHERE ){
+
3081
+
3082 Sphere* sphere = getSphereObjectPointer(o);
+
3083
+
3084 float transform[16];
+
3085 sphere->getTransformationMatrix(transform);
+
3086
+
3087 outfile << "\t<transform> ";
+
3088 for(float i : transform){
+
3089 outfile << i << " ";
+
3090 }
+
3091 outfile << "</transform>" << std::endl;
3092
-
3093 Tube *tube = getTubeObjectPointer(o);
-
3094
-
3095 float transform[16];
-
3096 tube->getTransformationMatrix(transform);
+
3093 uint subdiv = sphere->getSubdivisionCount();
+
3094 outfile << "\t<subdivisions> " << subdiv << " </subdivisions>" << std::endl;
+
3095
+
3096 outfile << " </sphere>" << std::endl;
3097
-
3098 outfile << "\t<transform> ";
-
3099 for (float i: transform) {
-
3100 outfile << i << " ";
-
3101 }
-
3102 outfile << "</transform>" << std::endl;
-
3103
-
3104 uint subdiv = tube->getSubdivisionCount();
-
3105 outfile << "\t<subdivisions> " << subdiv << " </subdivisions>" << std::endl;
-
3106
-
3107 std::vector<vec3> nodes = tube->getNodes();
-
3108 std::vector<float> radius = tube->getNodeRadii();
-
3109
-
3110 assert(nodes.size() == radius.size());
-
3111 outfile << "\t<nodes> " << std::endl;
-
3112 for (int i = 0; i < nodes.size(); i++) {
-
3113 outfile << "\t\t" << nodes.at(i).x << " " << nodes.at(i).y << " " << nodes.at(i).z << std::endl;
-
3114 }
-
3115 outfile << "\t</nodes> " << std::endl;
-
3116 outfile << "\t<radius> " << std::endl;
-
3117 for (int i = 0; i < radius.size(); i++) {
-
3118 outfile << "\t\t" << radius.at(i) << std::endl;
-
3119 }
-
3120 outfile << "\t</radius> " << std::endl;
-
3121
-
3122 if( texture_file.empty() ) {
-
3123 std::vector<RGBcolor> colors = tube->getNodeColors();
-
3124
-
3125 outfile << "\t<color> " << std::endl;
-
3126 for (int i = 0; i < colors.size(); i++) {
-
3127 outfile << "\t\t" << colors.at(i).r << " " << colors.at(i).g << " " << colors.at(i).b << std::endl;
-
3128 }
-
3129 outfile << "\t</color> " << std::endl;
-
3130
-
3131 }
+
3098 //Tubes
+
3099 }else if( obj->getObjectType()==OBJECT_TYPE_TUBE ) {
+
3100
+
3101 Tube *tube = getTubeObjectPointer(o);
+
3102
+
3103 float transform[16];
+
3104 tube->getTransformationMatrix(transform);
+
3105
+
3106 outfile << "\t<transform> ";
+
3107 for (float i: transform) {
+
3108 outfile << i << " ";
+
3109 }
+
3110 outfile << "</transform>" << std::endl;
+
3111
+
3112 uint subdiv = tube->getSubdivisionCount();
+
3113 outfile << "\t<subdivisions> " << subdiv << " </subdivisions>" << std::endl;
+
3114
+
3115 std::vector<vec3> nodes = tube->getNodes();
+
3116 std::vector<float> radius = tube->getNodeRadii();
+
3117
+
3118 assert(nodes.size() == radius.size());
+
3119 outfile << "\t<nodes> " << std::endl;
+
3120 for (int i = 0; i < nodes.size(); i++) {
+
3121 outfile << "\t\t" << nodes.at(i).x << " " << nodes.at(i).y << " " << nodes.at(i).z << std::endl;
+
3122 }
+
3123 outfile << "\t</nodes> " << std::endl;
+
3124 outfile << "\t<radius> " << std::endl;
+
3125 for (int i = 0; i < radius.size(); i++) {
+
3126 outfile << "\t\t" << radius.at(i) << std::endl;
+
3127 }
+
3128 outfile << "\t</radius> " << std::endl;
+
3129
+
3130 if( texture_file.empty() ) {
+
3131 std::vector<RGBcolor> colors = tube->getNodeColors();
3132
-
3133 outfile << " </tube>" << std::endl;
-
3134
-
3135 //Boxes
-
3136 }else if( obj->getObjectType()==OBJECT_TYPE_BOX ) {
-
3137
-
3138 Box *box = getBoxObjectPointer(o);
-
3139
-
3140 float transform[16];
-
3141 box->getTransformationMatrix(transform);
+
3133 outfile << "\t<color> " << std::endl;
+
3134 for (int i = 0; i < colors.size(); i++) {
+
3135 outfile << "\t\t" << colors.at(i).r << " " << colors.at(i).g << " " << colors.at(i).b << std::endl;
+
3136 }
+
3137 outfile << "\t</color> " << std::endl;
+
3138
+
3139 }
+
3140
+
3141 outfile << " </tube>" << std::endl;
3142
-
3143 outfile << "\t<transform> ";
-
3144 for (float i: transform) {
-
3145 outfile << i << " ";
-
3146 }
-
3147 outfile << "</transform>" << std::endl;
-
3148
-
3149 int3 subdiv = box->getSubdivisionCount();
-
3150 outfile << "\t<subdivisions> " << subdiv.x << " " << subdiv.y << " " << subdiv.z << " </subdivisions>" << std::endl;
-
3151
-
3152 outfile << " </box>" << std::endl;
-
3153
-
3154 //Disks
-
3155 }else if( obj->getObjectType()==OBJECT_TYPE_DISK ) {
+
3143 //Boxes
+
3144 }else if( obj->getObjectType()==OBJECT_TYPE_BOX ) {
+
3145
+
3146 Box *box = getBoxObjectPointer(o);
+
3147
+
3148 float transform[16];
+
3149 box->getTransformationMatrix(transform);
+
3150
+
3151 outfile << "\t<transform> ";
+
3152 for (float i: transform) {
+
3153 outfile << i << " ";
+
3154 }
+
3155 outfile << "</transform>" << std::endl;
3156
-
3157 Disk *disk = getDiskObjectPointer(o);
-
3158
-
3159 float transform[16];
-
3160 disk->getTransformationMatrix(transform);
+
3157 int3 subdiv = box->getSubdivisionCount();
+
3158 outfile << "\t<subdivisions> " << subdiv.x << " " << subdiv.y << " " << subdiv.z << " </subdivisions>" << std::endl;
+
3159
+
3160 outfile << " </box>" << std::endl;
3161
-
3162 outfile << "\t<transform> ";
-
3163 for (float i: transform) {
-
3164 outfile << i << " ";
-
3165 }
-
3166 outfile << "</transform>" << std::endl;
-
3167
-
3168 int2 subdiv = disk->getSubdivisionCount();
-
3169 outfile << "\t<subdivisions> " << subdiv.x << " " << subdiv.y << " </subdivisions>" << std::endl;
-
3170
-
3171 outfile << " </disk>" << std::endl;
-
3172
-
3173 //Cones
-
3174 }else if( obj->getObjectType()==OBJECT_TYPE_CONE ) {
+
3162 //Disks
+
3163 }else if( obj->getObjectType()==OBJECT_TYPE_DISK ) {
+
3164
+
3165 Disk *disk = getDiskObjectPointer(o);
+
3166
+
3167 float transform[16];
+
3168 disk->getTransformationMatrix(transform);
+
3169
+
3170 outfile << "\t<transform> ";
+
3171 for (float i: transform) {
+
3172 outfile << i << " ";
+
3173 }
+
3174 outfile << "</transform>" << std::endl;
3175
-
3176 Cone *cone = getConeObjectPointer(o);
-
3177
-
3178 float transform[16];
-
3179 cone->getTransformationMatrix(transform);
+
3176 int2 subdiv = disk->getSubdivisionCount();
+
3177 outfile << "\t<subdivisions> " << subdiv.x << " " << subdiv.y << " </subdivisions>" << std::endl;
+
3178
+
3179 outfile << " </disk>" << std::endl;
3180
-
3181 outfile << "\t<transform> ";
-
3182 for (float i: transform) {
-
3183 outfile << i << " ";
-
3184 }
-
3185 outfile << "</transform>" << std::endl;
-
3186
-
3187 uint subdiv = cone->getSubdivisionCount();
-
3188 outfile << "\t<subdivisions> " << subdiv << " </subdivisions>" << std::endl;
-
3189
-
3190 std::vector<vec3> nodes = cone->getNodeCoordinates();
-
3191 std::vector<float> radius = cone->getNodeRadii();
-
3192
-
3193 assert(nodes.size() == radius.size());
-
3194 outfile << "\t<nodes> " << std::endl;
-
3195 for (int i = 0; i < nodes.size(); i++) {
-
3196 outfile << "\t\t" << nodes.at(i).x << " " << nodes.at(i).y << " " << nodes.at(i).z << std::endl;
-
3197 }
-
3198 outfile << "\t</nodes> " << std::endl;
-
3199 outfile << "\t<radius> " << std::endl;
-
3200 for (int i = 0; i < radius.size(); i++) {
-
3201 outfile << "\t\t" << radius.at(i) << std::endl;
-
3202 }
-
3203 outfile << "\t</radius> " << std::endl;
-
3204
-
3205 outfile << " </cone>" << std::endl;
-
3206
-
3207 //Polymesh
-
3208 }else if( obj->getObjectType()==OBJECT_TYPE_POLYMESH ) {
-
3209
-
3210 outfile << " </polymesh>" << std::endl;
-
3211
-
3212 }
-
3213
-
3214 }
-
3215
-
3216
-
3217 // -- global data -- //
-
3218
-
3219 for(const auto & iter : globaldata){
-
3220 std::string label = iter.first;
-
3221 GlobalData data = iter.second;
-
3222 HeliosDataType type = data.type;
-
3223 if( type==HELIOS_TYPE_UINT ){
-
3224 outfile << " <globaldata_uint label=\"" << label << "\">" << std::flush;
-
3225 for( size_t i=0; i<data.size; i++ ){
-
3226 outfile << data.global_data_uint.at(i) << std::flush;
-
3227 if( i!=data.size-1 ){
-
3228 outfile << " " << std::flush;
-
3229 }
-
3230 }
-
3231 outfile << "</globaldata_uint>" << std::endl;
-
3232 }else if( type==HELIOS_TYPE_INT ){
-
3233 outfile << " <globaldata_int label=\"" << label << "\">" << std::flush;
-
3234 for( size_t i=0; i<data.size; i++ ){
-
3235 outfile << data.global_data_int.at(i) << std::flush;
-
3236 if( i!=data.size-1 ){
-
3237 outfile << " " << std::flush;
-
3238 }
-
3239 }
-
3240 outfile << "</globaldata_int>" << std::endl;
-
3241 }else if( type==HELIOS_TYPE_FLOAT ){
-
3242 outfile << " <globaldata_float label=\"" << label << "\">" << std::flush;
-
3243 for( size_t i=0; i<data.size; i++ ){
-
3244 outfile << data.global_data_float.at(i) << std::flush;
-
3245 if( i!=data.size-1 ){
-
3246 outfile << " " << std::flush;
-
3247 }
-
3248 }
-
3249 outfile << "</globaldata_float>" << std::endl;
-
3250 }else if( type==HELIOS_TYPE_DOUBLE ){
-
3251 outfile << " <globaldata_double label=\"" << label << "\">" << std::flush;
-
3252 for( size_t i=0; i<data.size; i++ ){
-
3253 outfile << data.global_data_double.at(i) << std::flush;
-
3254 if( i!=data.size-1 ){
-
3255 outfile << " " << std::flush;
-
3256 }
-
3257 }
-
3258 outfile << "</globaldata_double>" << std::endl;
-
3259 }else if( type==HELIOS_TYPE_VEC2 ){
-
3260 outfile << " <globaldata_vec2 label=\"" << label << "\">" << std::flush;
-
3261 for( size_t i=0; i<data.size; i++ ){
-
3262 outfile << data.global_data_vec2.at(i).x << " " << data.global_data_vec2.at(i).y << std::flush;
-
3263 if( i!=data.size-1 ){
-
3264 outfile << " " << std::flush;
-
3265 }
-
3266 }
-
3267 outfile << "</globaldata_vec2>" << std::endl;
-
3268 }else if( type==HELIOS_TYPE_VEC3 ){
-
3269 outfile << " <globaldata_vec3 label=\"" << label << "\">" << std::flush;
-
3270 for( size_t i=0; i<data.size; i++ ){
-
3271 outfile << data.global_data_vec3.at(i).x << " " << data.global_data_vec3.at(i).y << " " << data.global_data_vec3.at(i).z << std::flush;
-
3272 if( i!=data.size-1 ){
-
3273 outfile << " " << std::flush;
-
3274 }
-
3275 }
-
3276 outfile << "</globaldata_vec3>" << std::endl;
-
3277 }else if( type==HELIOS_TYPE_VEC4 ){
-
3278 outfile << " <globaldata_vec4 label=\"" << label << "\">" << std::flush;
-
3279 for( size_t i=0; i<data.size; i++ ){
-
3280 outfile << data.global_data_vec4.at(i).x << " " << data.global_data_vec4.at(i).y << " " << data.global_data_vec4.at(i).z << " " << data.global_data_vec4.at(i).w << std::flush;
-
3281 if( i!=data.size-1 ){
-
3282 outfile << " " << std::flush;
-
3283 }
-
3284 }
-
3285 outfile << "</globaldata_vec4>" << std::endl;
-
3286 }else if( type==HELIOS_TYPE_INT2 ){
-
3287 outfile << " <globaldata_int2 label=\"" << label << "\">" << std::flush;
-
3288 for( size_t i=0; i<data.size; i++ ){
-
3289 outfile << data.global_data_int2.at(i).x << " " << data.global_data_int2.at(i).y << std::flush;
-
3290 if( i!=data.size-1 ){
-
3291 outfile << " " << std::flush;
-
3292 }
-
3293 }
-
3294 outfile << "</globaldata_int2>" << std::endl;
-
3295 }else if( type==HELIOS_TYPE_INT3 ){
-
3296 outfile << " <globaldata_int3 label=\"" << label << "\">" << std::flush;
-
3297 for( size_t i=0; i<data.size; i++ ){
-
3298 outfile << data.global_data_int3.at(i).x << " " << data.global_data_int3.at(i).y << data.global_data_int3.at(i).z << std::flush;
-
3299 if( i!=data.size-1 ){
-
3300 outfile << " " << std::flush;
-
3301 }
-
3302 }
-
3303 outfile << "</globaldata_int3>" << std::endl;
-
3304 }else if( type==HELIOS_TYPE_INT4 ){
-
3305 outfile << " <globaldata_int4 label=\"" << label << "\">" << std::flush;
-
3306 for( size_t i=0; i<data.size; i++ ){
-
3307 outfile << data.global_data_int4.at(i).x << " " << data.global_data_int4.at(i).y << data.global_data_int4.at(i).z << data.global_data_int4.at(i).w << std::flush;
-
3308 if( i!=data.size-1 ){
-
3309 outfile << " " << std::flush;
-
3310 }
-
3311 }
-
3312 outfile << "</globaldata_int4>" << std::endl;
-
3313 }else if( type==HELIOS_TYPE_STRING ){
-
3314 outfile << " <globaldata_string label=\"" << label << "\">" << std::flush;
-
3315 for( size_t i=0; i<data.size; i++ ){
-
3316 outfile << data.global_data_string.at(i) << std::flush;
-
3317 if( i!=data.size-1 ){
-
3318 outfile << " " << std::flush;
-
3319 }
-
3320 }
-
3321 outfile << "</globaldata_string>" << std::endl;
-
3322 }
-
3323
-
3324 }
-
3325
-
3326 // -- timeseries -- //
-
3327
-
3328 for(const auto & iter : timeseries_data){
-
3329
-
3330 std::string label = iter.first;
+
3181 //Cones
+
3182 }else if( obj->getObjectType()==OBJECT_TYPE_CONE ) {
+
3183
+
3184 Cone *cone = getConeObjectPointer(o);
+
3185
+
3186 float transform[16];
+
3187 cone->getTransformationMatrix(transform);
+
3188
+
3189 outfile << "\t<transform> ";
+
3190 for (float i: transform) {
+
3191 outfile << i << " ";
+
3192 }
+
3193 outfile << "</transform>" << std::endl;
+
3194
+
3195 uint subdiv = cone->getSubdivisionCount();
+
3196 outfile << "\t<subdivisions> " << subdiv << " </subdivisions>" << std::endl;
+
3197
+
3198 std::vector<vec3> nodes = cone->getNodeCoordinates();
+
3199 std::vector<float> radius = cone->getNodeRadii();
+
3200
+
3201 assert(nodes.size() == radius.size());
+
3202 outfile << "\t<nodes> " << std::endl;
+
3203 for (int i = 0; i < nodes.size(); i++) {
+
3204 outfile << "\t\t" << nodes.at(i).x << " " << nodes.at(i).y << " " << nodes.at(i).z << std::endl;
+
3205 }
+
3206 outfile << "\t</nodes> " << std::endl;
+
3207 outfile << "\t<radius> " << std::endl;
+
3208 for (int i = 0; i < radius.size(); i++) {
+
3209 outfile << "\t\t" << radius.at(i) << std::endl;
+
3210 }
+
3211 outfile << "\t</radius> " << std::endl;
+
3212
+
3213 outfile << " </cone>" << std::endl;
+
3214
+
3215 //Polymesh
+
3216 }else if( obj->getObjectType()==OBJECT_TYPE_POLYMESH ) {
+
3217
+
3218 outfile << " </polymesh>" << std::endl;
+
3219
+
3220 }
+
3221
+
3222 }
+
3223
+
3224
+
3225 // -- global data -- //
+
3226
+
3227 for(const auto & iter : globaldata){
+
3228 std::string label = iter.first;
+
3229 GlobalData data = iter.second;
+
3230 HeliosDataType type = data.type;
+
3231 if( type==HELIOS_TYPE_UINT ){
+
3232 outfile << " <globaldata_uint label=\"" << label << "\">" << std::flush;
+
3233 for( size_t i=0; i<data.size; i++ ){
+
3234 outfile << data.global_data_uint.at(i) << std::flush;
+
3235 if( i!=data.size-1 ){
+
3236 outfile << " " << std::flush;
+
3237 }
+
3238 }
+
3239 outfile << "</globaldata_uint>" << std::endl;
+
3240 }else if( type==HELIOS_TYPE_INT ){
+
3241 outfile << " <globaldata_int label=\"" << label << "\">" << std::flush;
+
3242 for( size_t i=0; i<data.size; i++ ){
+
3243 outfile << data.global_data_int.at(i) << std::flush;
+
3244 if( i!=data.size-1 ){
+
3245 outfile << " " << std::flush;
+
3246 }
+
3247 }
+
3248 outfile << "</globaldata_int>" << std::endl;
+
3249 }else if( type==HELIOS_TYPE_FLOAT ){
+
3250 outfile << " <globaldata_float label=\"" << label << "\">" << std::flush;
+
3251 for( size_t i=0; i<data.size; i++ ){
+
3252 outfile << data.global_data_float.at(i) << std::flush;
+
3253 if( i!=data.size-1 ){
+
3254 outfile << " " << std::flush;
+
3255 }
+
3256 }
+
3257 outfile << "</globaldata_float>" << std::endl;
+
3258 }else if( type==HELIOS_TYPE_DOUBLE ){
+
3259 outfile << " <globaldata_double label=\"" << label << "\">" << std::flush;
+
3260 for( size_t i=0; i<data.size; i++ ){
+
3261 outfile << data.global_data_double.at(i) << std::flush;
+
3262 if( i!=data.size-1 ){
+
3263 outfile << " " << std::flush;
+
3264 }
+
3265 }
+
3266 outfile << "</globaldata_double>" << std::endl;
+
3267 }else if( type==HELIOS_TYPE_VEC2 ){
+
3268 outfile << " <globaldata_vec2 label=\"" << label << "\">" << std::flush;
+
3269 for( size_t i=0; i<data.size; i++ ){
+
3270 outfile << data.global_data_vec2.at(i).x << " " << data.global_data_vec2.at(i).y << std::flush;
+
3271 if( i!=data.size-1 ){
+
3272 outfile << " " << std::flush;
+
3273 }
+
3274 }
+
3275 outfile << "</globaldata_vec2>" << std::endl;
+
3276 }else if( type==HELIOS_TYPE_VEC3 ){
+
3277 outfile << " <globaldata_vec3 label=\"" << label << "\">" << std::flush;
+
3278 for( size_t i=0; i<data.size; i++ ){
+
3279 outfile << data.global_data_vec3.at(i).x << " " << data.global_data_vec3.at(i).y << " " << data.global_data_vec3.at(i).z << std::flush;
+
3280 if( i!=data.size-1 ){
+
3281 outfile << " " << std::flush;
+
3282 }
+
3283 }
+
3284 outfile << "</globaldata_vec3>" << std::endl;
+
3285 }else if( type==HELIOS_TYPE_VEC4 ){
+
3286 outfile << " <globaldata_vec4 label=\"" << label << "\">" << std::flush;
+
3287 for( size_t i=0; i<data.size; i++ ){
+
3288 outfile << data.global_data_vec4.at(i).x << " " << data.global_data_vec4.at(i).y << " " << data.global_data_vec4.at(i).z << " " << data.global_data_vec4.at(i).w << std::flush;
+
3289 if( i!=data.size-1 ){
+
3290 outfile << " " << std::flush;
+
3291 }
+
3292 }
+
3293 outfile << "</globaldata_vec4>" << std::endl;
+
3294 }else if( type==HELIOS_TYPE_INT2 ){
+
3295 outfile << " <globaldata_int2 label=\"" << label << "\">" << std::flush;
+
3296 for( size_t i=0; i<data.size; i++ ){
+
3297 outfile << data.global_data_int2.at(i).x << " " << data.global_data_int2.at(i).y << std::flush;
+
3298 if( i!=data.size-1 ){
+
3299 outfile << " " << std::flush;
+
3300 }
+
3301 }
+
3302 outfile << "</globaldata_int2>" << std::endl;
+
3303 }else if( type==HELIOS_TYPE_INT3 ){
+
3304 outfile << " <globaldata_int3 label=\"" << label << "\">" << std::flush;
+
3305 for( size_t i=0; i<data.size; i++ ){
+
3306 outfile << data.global_data_int3.at(i).x << " " << data.global_data_int3.at(i).y << data.global_data_int3.at(i).z << std::flush;
+
3307 if( i!=data.size-1 ){
+
3308 outfile << " " << std::flush;
+
3309 }
+
3310 }
+
3311 outfile << "</globaldata_int3>" << std::endl;
+
3312 }else if( type==HELIOS_TYPE_INT4 ){
+
3313 outfile << " <globaldata_int4 label=\"" << label << "\">" << std::flush;
+
3314 for( size_t i=0; i<data.size; i++ ){
+
3315 outfile << data.global_data_int4.at(i).x << " " << data.global_data_int4.at(i).y << data.global_data_int4.at(i).z << data.global_data_int4.at(i).w << std::flush;
+
3316 if( i!=data.size-1 ){
+
3317 outfile << " " << std::flush;
+
3318 }
+
3319 }
+
3320 outfile << "</globaldata_int4>" << std::endl;
+
3321 }else if( type==HELIOS_TYPE_STRING ){
+
3322 outfile << " <globaldata_string label=\"" << label << "\">" << std::flush;
+
3323 for( size_t i=0; i<data.size; i++ ){
+
3324 outfile << data.global_data_string.at(i) << std::flush;
+
3325 if( i!=data.size-1 ){
+
3326 outfile << " " << std::flush;
+
3327 }
+
3328 }
+
3329 outfile << "</globaldata_string>" << std::endl;
+
3330 }
3331
-
3332 std::vector<float> data = iter.second;
-
3333 std::vector<double> dateval = timeseries_datevalue.at(label);
-
3334
-
3335 assert( data.size()==dateval.size() );
-
3336
-
3337 outfile << " <timeseries label=\"" << label << "\">" << std::endl;
-
3338
-
3339 for( size_t i=0; i<data.size(); i++ ){
-
3340
-
3341 Date a_date = queryTimeseriesDate( label.c_str(), i );
-
3342 Time a_time = queryTimeseriesTime( label.c_str(), i );
-
3343
-
3344 outfile << "\t<datapoint>" << std::endl;
-
3345
-
3346 outfile << "\t <date>" << a_date.day << " " << a_date.month << " " << a_date.year << "</date>" << std::endl;
-
3347
-
3348 outfile << "\t <time>" << a_time.hour << " " << a_time.minute << " " << a_time.second << "</time>" << std::endl;
-
3349
-
3350 outfile << "\t <value>" << data.at(i) << "</value>" << std::endl;
+
3332 }
+
3333
+
3334 // -- timeseries -- //
+
3335
+
3336 for(const auto & iter : timeseries_data){
+
3337
+
3338 std::string label = iter.first;
+
3339
+
3340 std::vector<float> data = iter.second;
+
3341 std::vector<double> dateval = timeseries_datevalue.at(label);
+
3342
+
3343 assert( data.size()==dateval.size() );
+
3344
+
3345 outfile << " <timeseries label=\"" << label << "\">" << std::endl;
+
3346
+
3347 for( size_t i=0; i<data.size(); i++ ){
+
3348
+
3349 Date a_date = queryTimeseriesDate( label.c_str(), i );
+
3350 Time a_time = queryTimeseriesTime( label.c_str(), i );
3351
-
3352 outfile << "\t</datapoint>" << std::endl;
-
3353 }
-
3354
-
3355 outfile << " </timeseries>" << std::endl;
-
3356
-
3357 }
-
3358
-
3359 // ----------------- //
-
3360
-
3361 outfile << "\n</helios>\n";
+
3352 outfile << "\t<datapoint>" << std::endl;
+
3353
+
3354 outfile << "\t <date>" << a_date.day << " " << a_date.month << " " << a_date.year << "</date>" << std::endl;
+
3355
+
3356 outfile << "\t <time>" << a_time.hour << " " << a_time.minute << " " << a_time.second << "</time>" << std::endl;
+
3357
+
3358 outfile << "\t <value>" << data.at(i) << "</value>" << std::endl;
+
3359
+
3360 outfile << "\t</datapoint>" << std::endl;
+
3361 }
3362
-
3363 outfile.close();
+
3363 outfile << " </timeseries>" << std::endl;
3364
-
3365 if( !quiet ) {
-
3366 std::cout << "done." << std::endl;
-
3367 }
-
3368}
-
-
3369
-
-
3370std::vector<uint> Context::loadPLY(const char* filename, bool silent ){
-
3371 return loadPLY( filename, nullorigin, 0, nullrotation, RGB::blue, "YUP", silent );
-
3372}
-
-
3373
-
-
3374std::vector<uint> Context::loadPLY(const char* filename, const vec3 &origin, float height, const std::string &upaxis, bool silent ){
-
3375 return loadPLY( filename, origin, height, make_SphericalCoord(0,0), RGB::blue, upaxis, silent );
+
3365 }
+
3366
+
3367 // ----------------- //
+
3368
+
3369 outfile << "\n</helios>\n";
+
3370
+
3371 outfile.close();
+
3372
+
3373 if( !quiet ) {
+
3374 std::cout << "done." << std::endl;
+
3375 }
3376}
3377
-
3378std::vector<uint> Context::loadPLY(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const std::string &upaxis, bool silent ){
-
3379 return loadPLY( filename, origin, height, rotation, RGB::blue, upaxis, silent );
+
3378std::vector<uint> Context::loadPLY(const char* filename, bool silent ){
+
3379 return loadPLY( filename, nullorigin, 0, nullrotation, RGB::blue, "YUP", silent );
3380}
3381
-
3382std::vector<uint> Context::loadPLY(const char* filename, const vec3 &origin, float height, const RGBcolor &default_color, const std::string &upaxis, bool silent ){
-
3383 return loadPLY( filename, origin, height, make_SphericalCoord(0,0), default_color, upaxis, silent );
+
3382std::vector<uint> Context::loadPLY(const char* filename, const vec3 &origin, float height, const std::string &upaxis, bool silent ){
+
3383 return loadPLY( filename, origin, height, make_SphericalCoord(0,0), RGB::blue, upaxis, silent );
3384}
3385
-
3386std::vector<uint> Context::loadPLY(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, const std::string &upaxis, bool silent ){
-
3387
-
3388 if( !silent ) {
-
3389 std::cout << "Reading PLY file " << filename << "..." << std::flush;
-
3390 }
-
3391
-
3392 std::string fn = filename;
-
3393 std::string ext = getFileExtension(filename);
-
3394 if( ext != ".ply" && ext != ".PLY" ) {
-
3395 helios_runtime_error("ERROR (Context::loadPLY): File " + fn + " is not PLY format.");
-
3396 }
-
3397
-
3398 if( upaxis!="XUP" && upaxis!="YUP" && upaxis!="ZUP" ){
-
3399 helios_runtime_error("ERROR (Context::loadPLY): " + upaxis + " is not a valid up-axis. Please specify a value of XUP, YUP, or ZUP.");
-
3400 }
-
3401
-
3402 std::string line, prop;
-
3403
-
3404 uint vertexCount=0, faceCount=0;
+
3386std::vector<uint> Context::loadPLY(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const std::string &upaxis, bool silent ){
+
3387 return loadPLY( filename, origin, height, rotation, RGB::blue, upaxis, silent );
+
3388}
+
+
3389
+
+
3390std::vector<uint> Context::loadPLY(const char* filename, const vec3 &origin, float height, const RGBcolor &default_color, const std::string &upaxis, bool silent ){
+
3391 return loadPLY( filename, origin, height, make_SphericalCoord(0,0), default_color, upaxis, silent );
+
3392}
+
+
3393
+
+
3394std::vector<uint> Context::loadPLY(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, const std::string &upaxis, bool silent ){
+
3395
+
3396 if( !silent ) {
+
3397 std::cout << "Reading PLY file " << filename << "..." << std::flush;
+
3398 }
+
3399
+
3400 std::string fn = filename;
+
3401 std::string ext = getFileExtension(filename);
+
3402 if( ext != ".ply" && ext != ".PLY" ) {
+
3403 helios_runtime_error("ERROR (Context::loadPLY): File " + fn + " is not PLY format.");
+
3404 }
3405
-
3406 std::vector<vec3> vertices;
-
3407 std::vector<std::vector<int> > faces;
-
3408 std::vector<RGBcolor> colors;
-
3409 std::vector<std::string> properties;
-
3410
-
3411 bool ifColor=false;
-
3412
-
3413 std::ifstream inputPly;
-
3414 inputPly.open(filename);
-
3415
-
3416 if (!inputPly.is_open()) {
-
3417 helios_runtime_error("ERROR (Context::loadPLY): Couldn't open " + std::string(filename) );
-
3418 }
-
3419
-
3420 //--- read header info -----//
-
3421
-
3422 //first line should always be 'ply'
-
3423 inputPly>>line;
-
3424 if( "ply"!=line ){
-
3425 helios_runtime_error("ERROR (Context::loadPLY): " + std::string(filename) + " is not a PLY file.");
+
3406 if( upaxis!="XUP" && upaxis!="YUP" && upaxis!="ZUP" ){
+
3407 helios_runtime_error("ERROR (Context::loadPLY): " + upaxis + " is not a valid up-axis. Please specify a value of XUP, YUP, or ZUP.");
+
3408 }
+
3409
+
3410 std::string line, prop;
+
3411
+
3412 uint vertexCount=0, faceCount=0;
+
3413
+
3414 std::vector<vec3> vertices;
+
3415 std::vector<std::vector<int> > faces;
+
3416 std::vector<RGBcolor> colors;
+
3417 std::vector<std::string> properties;
+
3418
+
3419 bool ifColor=false;
+
3420
+
3421 std::ifstream inputPly;
+
3422 inputPly.open(filename);
+
3423
+
3424 if (!inputPly.is_open()) {
+
3425 helios_runtime_error("ERROR (Context::loadPLY): Couldn't open " + std::string(filename) );
3426 }
3427
-
3428 //read format
-
3429 inputPly>>line;
-
3430 if( "format"!=line ){
-
3431 helios_runtime_error("ERROR (Context::loadPLY): could not determine data format of " + std::string(filename) );
-
3432 }
-
3433
-
3434 inputPly>>line;
-
3435 if( "ascii"!=line ){
-
3436 helios_runtime_error("ERROR (Context::loadPLY): Only ASCII data types are supported.");
-
3437 }
-
3438
-
3439 std::string temp_string;
-
3440
-
3441 while( "end_header"!=line ){
-
3442
-
3443 inputPly>>line;
-
3444
-
3445 if( "comment"==line ){
-
3446 getline(inputPly, line);
-
3447 }
-
3448 else if( "element"==line ){
-
3449
-
3450 inputPly>>line;
-
3451
-
3452 if( "vertex"==line ){
-
3453 inputPly>>temp_string;
-
3454 if( !parse_uint(temp_string,vertexCount) ){
-
3455 helios_runtime_error("ERROR (Context::loadPLY): PLY file read failed. Vertex count value should be a non-negative integer.");
-
3456 }
-
3457 }else if( "face"==line ){
-
3458 inputPly>>temp_string;
-
3459 if( !parse_uint(temp_string,faceCount) ){
-
3460 helios_runtime_error("ERROR (Context::loadPLY): PLY file read failed. Face count value should be a non-negative integer.");
-
3461 }
-
3462 }
-
3463
-
3464 }else if( "property"==line ){
-
3465
-
3466 inputPly>>line; //type
-
3467
-
3468 if( "list"!=line ){
-
3469
-
3470 inputPly>>prop; //value
-
3471 properties.push_back(prop);
-
3472
-
3473 }
-
3474
-
3475 }
-
3476
-
3477 }
-
3478
-
3479 for(auto & property : properties){
-
3480 if( property=="red" ){
-
3481 ifColor = true;
-
3482 }
-
3483 }
-
3484 if( !silent ) {
-
3485 std::cout << "forming " << faceCount << " triangles..." << std::flush;
-
3486 }
-
3487
-
3488 vertices.resize(vertexCount);
-
3489 colors.resize(vertexCount);
-
3490 faces.resize(faceCount);
-
3491
-
3492
-
3493 //--- read vertices ----//
-
3494
-
3495 for( uint row=0; row<vertexCount; row++ ){
-
3496
-
3497 for(auto & property : properties){
-
3498 if( property=="x" ){
-
3499 inputPly >> temp_string;
-
3500 float x;
-
3501 if( !parse_float(temp_string,x) ){
-
3502 helios_runtime_error("ERROR (Context::loadPLY): X value for vertex " + std::to_string(row) + " is invalid and could not be read.");
-
3503 }
-
3504 if( upaxis=="XUP"){
-
3505 vertices.at(row).z = x;
-
3506 }else if( upaxis=="YUP" ){
-
3507 vertices.at(row).y = x;
-
3508 }else if( upaxis=="ZUP" ){
-
3509 vertices.at(row).x = x;
-
3510 }
-
3511 }else if( property=="y" ){
-
3512 inputPly >> temp_string;
-
3513 float y;
-
3514 if( !parse_float(temp_string,y) ){
-
3515 helios_runtime_error("ERROR (Context::loadPLY): Y value for vertex " + std::to_string(row) + " is invalid and could not be read.");
-
3516 }
-
3517 if( upaxis=="XUP"){
-
3518 vertices.at(row).x = y;
-
3519 }else if( upaxis=="YUP" ){
-
3520 vertices.at(row).z = y;
-
3521 }else if( upaxis=="ZUP" ){
-
3522 vertices.at(row).y = y;
-
3523 }
-
3524 }else if( property=="z" ){
-
3525 inputPly >> temp_string;
-
3526 float z;
-
3527 if( !parse_float(temp_string,z) ){
-
3528 helios_runtime_error("ERROR (Context::loadPLY): Z value for vertex " + std::to_string(row) + " is invalid and could not be read.");
-
3529 }
-
3530 if( upaxis=="XUP"){
-
3531 vertices.at(row).y = z;
-
3532 }else if( upaxis=="YUP" ){
-
3533 vertices.at(row).x = z;
-
3534 }else if( upaxis=="ZUP" ){
-
3535 vertices.at(row).z = z;
-
3536 }
-
3537 }else if( property=="red" ){
-
3538 inputPly >> temp_string;
-
3539 if( !parse_float(temp_string,colors.at(row).r) ){
-
3540 helios_runtime_error("ERROR (Context::loadPLY): red color value for vertex " + std::to_string(row) + " is invalid and could not be read.");
-
3541 }
-
3542 colors.at(row).r /= 255.f;
-
3543 }else if( property=="green" ){
-
3544 inputPly >> temp_string;
-
3545 if( !parse_float(temp_string,colors.at(row).g) ){
-
3546 helios_runtime_error("ERROR (Context::loadPLY): green color value for vertex " + std::to_string(row) + " is invalid and could not be read.");
-
3547 }
-
3548 colors.at(row).g /= 255.f;
-
3549 }else if( property=="blue" ){
-
3550 inputPly >> temp_string;
-
3551 if( !parse_float(temp_string,colors.at(row).b) ){
-
3552 helios_runtime_error("ERROR (Context::loadPLY): blue color value for vertex " + std::to_string(row) + " is invalid and could not be read.");
-
3553 }
-
3554 colors.at(row).b /= 255.f;
-
3555 }else{
-
3556 inputPly >> line;
-
3557 }
-
3558 }
-
3559
-
3560 if( inputPly.eof() ){
-
3561 helios_runtime_error("ERROR (Context::loadPLY): Read past end of file while reading vertices. Vertex count specified in header may be incorrect.");
-
3562 }
-
3563
-
3564 }
-
3565
-
3566 //determine bounding box
+
3428 //--- read header info -----//
+
3429
+
3430 //first line should always be 'ply'
+
3431 inputPly>>line;
+
3432 if( "ply"!=line ){
+
3433 helios_runtime_error("ERROR (Context::loadPLY): " + std::string(filename) + " is not a PLY file.");
+
3434 }
+
3435
+
3436 //read format
+
3437 inputPly>>line;
+
3438 if( "format"!=line ){
+
3439 helios_runtime_error("ERROR (Context::loadPLY): could not determine data format of " + std::string(filename) );
+
3440 }
+
3441
+
3442 inputPly>>line;
+
3443 if( "ascii"!=line ){
+
3444 helios_runtime_error("ERROR (Context::loadPLY): Only ASCII data types are supported.");
+
3445 }
+
3446
+
3447 std::string temp_string;
+
3448
+
3449 while( "end_header"!=line ){
+
3450
+
3451 inputPly>>line;
+
3452
+
3453 if( "comment"==line ){
+
3454 getline(inputPly, line);
+
3455 }
+
3456 else if( "element"==line ){
+
3457
+
3458 inputPly>>line;
+
3459
+
3460 if( "vertex"==line ){
+
3461 inputPly>>temp_string;
+
3462 if( !parse_uint(temp_string,vertexCount) ){
+
3463 helios_runtime_error("ERROR (Context::loadPLY): PLY file read failed. Vertex count value should be a non-negative integer.");
+
3464 }
+
3465 }else if( "face"==line ){
+
3466 inputPly>>temp_string;
+
3467 if( !parse_uint(temp_string,faceCount) ){
+
3468 helios_runtime_error("ERROR (Context::loadPLY): PLY file read failed. Face count value should be a non-negative integer.");
+
3469 }
+
3470 }
+
3471
+
3472 }else if( "property"==line ){
+
3473
+
3474 inputPly>>line; //type
+
3475
+
3476 if( "list"!=line ){
+
3477
+
3478 inputPly>>prop; //value
+
3479 properties.push_back(prop);
+
3480
+
3481 }
+
3482
+
3483 }
+
3484
+
3485 }
+
3486
+
3487 for(auto & property : properties){
+
3488 if( property=="red" ){
+
3489 ifColor = true;
+
3490 }
+
3491 }
+
3492 if( !silent ) {
+
3493 std::cout << "forming " << faceCount << " triangles..." << std::flush;
+
3494 }
+
3495
+
3496 vertices.resize(vertexCount);
+
3497 colors.resize(vertexCount);
+
3498 faces.resize(faceCount);
+
3499
+
3500
+
3501 //--- read vertices ----//
+
3502
+
3503 for( uint row=0; row<vertexCount; row++ ){
+
3504
+
3505 for(auto & property : properties){
+
3506 if( property=="x" ){
+
3507 inputPly >> temp_string;
+
3508 float x;
+
3509 if( !parse_float(temp_string,x) ){
+
3510 helios_runtime_error("ERROR (Context::loadPLY): X value for vertex " + std::to_string(row) + " is invalid and could not be read.");
+
3511 }
+
3512 if( upaxis=="XUP"){
+
3513 vertices.at(row).z = x;
+
3514 }else if( upaxis=="YUP" ){
+
3515 vertices.at(row).y = x;
+
3516 }else if( upaxis=="ZUP" ){
+
3517 vertices.at(row).x = x;
+
3518 }
+
3519 }else if( property=="y" ){
+
3520 inputPly >> temp_string;
+
3521 float y;
+
3522 if( !parse_float(temp_string,y) ){
+
3523 helios_runtime_error("ERROR (Context::loadPLY): Y value for vertex " + std::to_string(row) + " is invalid and could not be read.");
+
3524 }
+
3525 if( upaxis=="XUP"){
+
3526 vertices.at(row).x = y;
+
3527 }else if( upaxis=="YUP" ){
+
3528 vertices.at(row).z = y;
+
3529 }else if( upaxis=="ZUP" ){
+
3530 vertices.at(row).y = y;
+
3531 }
+
3532 }else if( property=="z" ){
+
3533 inputPly >> temp_string;
+
3534 float z;
+
3535 if( !parse_float(temp_string,z) ){
+
3536 helios_runtime_error("ERROR (Context::loadPLY): Z value for vertex " + std::to_string(row) + " is invalid and could not be read.");
+
3537 }
+
3538 if( upaxis=="XUP"){
+
3539 vertices.at(row).y = z;
+
3540 }else if( upaxis=="YUP" ){
+
3541 vertices.at(row).x = z;
+
3542 }else if( upaxis=="ZUP" ){
+
3543 vertices.at(row).z = z;
+
3544 }
+
3545 }else if( property=="red" ){
+
3546 inputPly >> temp_string;
+
3547 if( !parse_float(temp_string,colors.at(row).r) ){
+
3548 helios_runtime_error("ERROR (Context::loadPLY): red color value for vertex " + std::to_string(row) + " is invalid and could not be read.");
+
3549 }
+
3550 colors.at(row).r /= 255.f;
+
3551 }else if( property=="green" ){
+
3552 inputPly >> temp_string;
+
3553 if( !parse_float(temp_string,colors.at(row).g) ){
+
3554 helios_runtime_error("ERROR (Context::loadPLY): green color value for vertex " + std::to_string(row) + " is invalid and could not be read.");
+
3555 }
+
3556 colors.at(row).g /= 255.f;
+
3557 }else if( property=="blue" ){
+
3558 inputPly >> temp_string;
+
3559 if( !parse_float(temp_string,colors.at(row).b) ){
+
3560 helios_runtime_error("ERROR (Context::loadPLY): blue color value for vertex " + std::to_string(row) + " is invalid and could not be read.");
+
3561 }
+
3562 colors.at(row).b /= 255.f;
+
3563 }else{
+
3564 inputPly >> line;
+
3565 }
+
3566 }
3567
-
3568 vec3 boxmin = make_vec3(10000,10000,10000);
-
3569 vec3 boxmax = make_vec3(-10000,-10000,-10000);
-
3570
-
3571 for( uint row=0; row<vertexCount; row++ ){
-
3572
-
3573 if(vertices.at(row).x < boxmin.x ){
-
3574 boxmin.x = vertices.at(row).x;
-
3575 }
-
3576 if(vertices.at(row).y < boxmin.y ){
-
3577 boxmin.y = vertices.at(row).y;
-
3578 }
-
3579 if(vertices.at(row).z < boxmin.z ){
-
3580 boxmin.z = vertices.at(row).z;
-
3581 }
-
3582
-
3583 if(vertices.at(row).x > boxmax.x ){
-
3584 boxmax.x = vertices.at(row).x;
-
3585 }
-
3586 if(vertices.at(row).y > boxmax.y ){
-
3587 boxmax.y = vertices.at(row).y;
-
3588 }
-
3589 if(vertices.at(row).z > boxmax.z ){
-
3590 boxmax.z = vertices.at(row).z;
-
3591 }
-
3592
-
3593 }
-
3594
-
3595 //center PLY object at `origin' and scale to have height `height'
-
3596 float scl = 1.f;
-
3597 if( height>0.f ){
-
3598 scl = height/(boxmax.z-boxmin.z);
-
3599 }
-
3600 for( uint row=0; row<vertexCount; row++ ){
-
3601 vertices.at(row).z -= boxmin.z;
+
3568 if( inputPly.eof() ){
+
3569 helios_runtime_error("ERROR (Context::loadPLY): Read past end of file while reading vertices. Vertex count specified in header may be incorrect.");
+
3570 }
+
3571
+
3572 }
+
3573
+
3574 //determine bounding box
+
3575
+
3576 vec3 boxmin = make_vec3(10000,10000,10000);
+
3577 vec3 boxmax = make_vec3(-10000,-10000,-10000);
+
3578
+
3579 for( uint row=0; row<vertexCount; row++ ){
+
3580
+
3581 if(vertices.at(row).x < boxmin.x ){
+
3582 boxmin.x = vertices.at(row).x;
+
3583 }
+
3584 if(vertices.at(row).y < boxmin.y ){
+
3585 boxmin.y = vertices.at(row).y;
+
3586 }
+
3587 if(vertices.at(row).z < boxmin.z ){
+
3588 boxmin.z = vertices.at(row).z;
+
3589 }
+
3590
+
3591 if(vertices.at(row).x > boxmax.x ){
+
3592 boxmax.x = vertices.at(row).x;
+
3593 }
+
3594 if(vertices.at(row).y > boxmax.y ){
+
3595 boxmax.y = vertices.at(row).y;
+
3596 }
+
3597 if(vertices.at(row).z > boxmax.z ){
+
3598 boxmax.z = vertices.at(row).z;
+
3599 }
+
3600
+
3601 }
3602
-
3603 vertices.at(row).x *= scl;
-
3604 vertices.at(row).y *= scl;
-
3605 vertices.at(row).z *= scl;
-
3606
-
3607 vertices.at(row) = rotatePoint(vertices.at(row),rotation) + origin;
-
3608 }
-
3609
-
3610 //--- read faces ----//
-
3611
-
3612 uint v,ID;
-
3613 std::vector<uint> UUID;
-
3614 for( uint row=0; row<faceCount; row++ ){
-
3615
-
3616 inputPly >> temp_string;
+
3603 //center PLY object at `origin' and scale to have height `height'
+
3604 float scl = 1.f;
+
3605 if( height>0.f ){
+
3606 scl = height/(boxmax.z-boxmin.z);
+
3607 }
+
3608 for( uint row=0; row<vertexCount; row++ ){
+
3609 vertices.at(row).z -= boxmin.z;
+
3610
+
3611 vertices.at(row).x *= scl;
+
3612 vertices.at(row).y *= scl;
+
3613 vertices.at(row).z *= scl;
+
3614
+
3615 vertices.at(row) = rotatePoint(vertices.at(row),rotation) + origin;
+
3616 }
3617
-
3618 if( !parse_uint(temp_string,v) ){
-
3619 helios_runtime_error("ERROR (Context::loadPLY): Vertex count for face " + std::to_string(row) + " should be a non-negative integer.");
-
3620 }
-
3621
-
3622 faces.at(row).resize(v);
+
3618 //--- read faces ----//
+
3619
+
3620 uint v,ID;
+
3621 std::vector<uint> UUID;
+
3622 for( uint row=0; row<faceCount; row++ ){
3623
-
3624 for( uint i=0; i<v; i++ ){
-
3625 inputPly >> temp_string;
-
3626 if( !parse_int(temp_string,faces.at(row).at(i)) ){
-
3627 helios_runtime_error("ERROR (Context::loadPLY): Vertex index for face " + std::to_string(row) + " is invalid and could not be read.");
-
3628 }
-
3629 }
-
3630
-
3631 //Add triangles to context
-
3632
-
3633 for( uint t=2; t<v; t++ ){
-
3634
-
3635 RGBcolor color;
-
3636 if( ifColor ){
-
3637 color = colors.at(faces.at(row).front());
-
3638 }else{
-
3639 color = default_color;
-
3640 }
-
3641
-
3642 vec3 v0 = vertices.at(faces.at(row).front());
-
3643 vec3 v1 = vertices.at(faces.at(row).at(t-1));
-
3644 vec3 v2 = vertices.at(faces.at(row).at(t));
-
3645
-
3646 if( (v0-v1).magnitude()==0 || (v0-v2).magnitude()==0 || (v1-v2).magnitude()==0 ){
-
3647 continue;
+
3624 inputPly >> temp_string;
+
3625
+
3626 if( !parse_uint(temp_string,v) ){
+
3627 helios_runtime_error("ERROR (Context::loadPLY): Vertex count for face " + std::to_string(row) + " should be a non-negative integer.");
+
3628 }
+
3629
+
3630 faces.at(row).resize(v);
+
3631
+
3632 for( uint i=0; i<v; i++ ){
+
3633 inputPly >> temp_string;
+
3634 if( !parse_int(temp_string,faces.at(row).at(i)) ){
+
3635 helios_runtime_error("ERROR (Context::loadPLY): Vertex index for face " + std::to_string(row) + " is invalid and could not be read.");
+
3636 }
+
3637 }
+
3638
+
3639 //Add triangles to context
+
3640
+
3641 for( uint t=2; t<v; t++ ){
+
3642
+
3643 RGBcolor color;
+
3644 if( ifColor ){
+
3645 color = colors.at(faces.at(row).front());
+
3646 }else{
+
3647 color = default_color;
3648 }
3649
-
3650 ID = addTriangle( v0, v1, v2, color );
-
3651
-
3652 UUID.push_back(ID);
+
3650 vec3 v0 = vertices.at(faces.at(row).front());
+
3651 vec3 v1 = vertices.at(faces.at(row).at(t-1));
+
3652 vec3 v2 = vertices.at(faces.at(row).at(t));
3653
-
3654 }
-
3655
-
3656 if( inputPly.eof() ){
-
3657 helios_runtime_error("ERROR (Context::loadPLY): Read past end of file while reading faces. Face count specified in header may be incorrect.");
-
3658 }
+
3654 if( (v0-v1).magnitude()==0 || (v0-v2).magnitude()==0 || (v1-v2).magnitude()==0 ){
+
3655 continue;
+
3656 }
+
3657
+
3658 ID = addTriangle( v0, v1, v2, color );
3659
-
3660 }
+
3660 UUID.push_back(ID);
3661
-
3662 if( !silent ) {
-
3663 std::cout << "done." << std::endl;
-
3664 }
-
3665
-
3666 return UUID;
+
3662 }
+
3663
+
3664 if( inputPly.eof() ){
+
3665 helios_runtime_error("ERROR (Context::loadPLY): Read past end of file while reading faces. Face count specified in header may be incorrect.");
+
3666 }
3667
-
3668}
-
+
3668 }
3669
-
-
3670void Context::writePLY( const char* filename ) const{
-
3671
-
3672 std::ofstream PLYfile;
-
3673 PLYfile.open(filename);
-
3674
-
3675 PLYfile << "ply" << std::endl << "format ascii 1.0" << std::endl << "comment HELIOS generated" << std::endl;
-
3676
-
3677 std::vector<int3> faces;
-
3678 std::vector<vec3> verts;
-
3679 std::vector<RGBcolor> colors;
-
3680
-
3681 size_t vertex_count = 0;
+
3670 if( !silent ) {
+
3671 std::cout << "done." << std::endl;
+
3672 }
+
3673
+
3674 return UUID;
+
3675
+
3676}
+
+
3677
+
+
3678void Context::writePLY( const char* filename ) const{
+
3679
+
3680 std::ofstream PLYfile;
+
3681 PLYfile.open(filename);
3682
-
3683 for(auto primitive : primitives){
+
3683 PLYfile << "ply" << std::endl << "format ascii 1.0" << std::endl << "comment HELIOS generated" << std::endl;
3684
-
3685 uint p = primitive.first;
-
3686
-
3687 std::vector<vec3> vertices = getPrimitivePointer_private(p)->getVertices();
-
3688 PrimitiveType type = getPrimitivePointer_private(p)->getType();
-
3689 RGBcolor C = getPrimitivePointer_private(p)->getColor();
-
3690 C.scale(255.f);
-
3691
-
3692 if( type==PRIMITIVE_TYPE_TRIANGLE ){
-
3693
-
3694 faces.push_back( make_int3( (int)vertex_count, (int)vertex_count+1, (int)vertex_count+2 ) );
-
3695 for( int i=0; i<3; i++ ){
-
3696 verts.push_back( vertices.at(i) );
-
3697 colors.push_back( C );
-
3698 vertex_count ++;
-
3699 }
-
3700
-
3701 }else if( type==PRIMITIVE_TYPE_PATCH ){
-
3702
-
3703 faces.push_back( make_int3( (int)vertex_count, (int)vertex_count+1, (int)vertex_count+2 ) );
-
3704 faces.push_back( make_int3( (int)vertex_count, (int)vertex_count+2, (int)vertex_count+3 ) );
-
3705 for( int i=0; i<4; i++ ){
-
3706 verts.push_back( vertices.at(i) );
-
3707 colors.push_back( C );
-
3708 vertex_count ++;
-
3709 }
+
3685 std::vector<int3> faces;
+
3686 std::vector<vec3> verts;
+
3687 std::vector<RGBcolor> colors;
+
3688
+
3689 size_t vertex_count = 0;
+
3690
+
3691 for(auto primitive : primitives){
+
3692
+
3693 uint p = primitive.first;
+
3694
+
3695 std::vector<vec3> vertices = getPrimitivePointer_private(p)->getVertices();
+
3696 PrimitiveType type = getPrimitivePointer_private(p)->getType();
+
3697 RGBcolor C = getPrimitivePointer_private(p)->getColor();
+
3698 C.scale(255.f);
+
3699
+
3700 if( type==PRIMITIVE_TYPE_TRIANGLE ){
+
3701
+
3702 faces.push_back( make_int3( (int)vertex_count, (int)vertex_count+1, (int)vertex_count+2 ) );
+
3703 for( int i=0; i<3; i++ ){
+
3704 verts.push_back( vertices.at(i) );
+
3705 colors.push_back( C );
+
3706 vertex_count ++;
+
3707 }
+
3708
+
3709 }else if( type==PRIMITIVE_TYPE_PATCH ){
3710
-
3711 }
-
3712
-
3713 }
-
3714
-
3715 PLYfile << "element vertex " << verts.size() << std::endl;
-
3716 PLYfile << "property float x" << std::endl << "property float y" << std::endl << "property float z" << std::endl;
-
3717 PLYfile << "property uchar red" << std::endl << "property uchar green" << std::endl << "property uchar blue" << std::endl;
-
3718 PLYfile << "element face " << faces.size() << std::endl;
-
3719 PLYfile << "property list uchar int vertex_indices" << std::endl << "end_header" << std::endl;
+
3711 faces.push_back( make_int3( (int)vertex_count, (int)vertex_count+1, (int)vertex_count+2 ) );
+
3712 faces.push_back( make_int3( (int)vertex_count, (int)vertex_count+2, (int)vertex_count+3 ) );
+
3713 for( int i=0; i<4; i++ ){
+
3714 verts.push_back( vertices.at(i) );
+
3715 colors.push_back( C );
+
3716 vertex_count ++;
+
3717 }
+
3718
+
3719 }
3720
-
3721 for( size_t v=0; v<verts.size(); v++ ){
-
3722 PLYfile << verts.at(v).x << " " << verts.at(v).y << " " << verts.at(v).z << " " << round(colors.at(v).r) << " " << round(colors.at(v).g) << " " << round(colors.at(v).b) << std::endl;
-
3723 }
-
3724
-
3725 for(auto & face : faces){
-
3726 PLYfile << "3 " << face.x << " " << face.y << " " << face.z << std::endl;
-
3727 }
+
3721 }
+
3722
+
3723 PLYfile << "element vertex " << verts.size() << std::endl;
+
3724 PLYfile << "property float x" << std::endl << "property float y" << std::endl << "property float z" << std::endl;
+
3725 PLYfile << "property uchar red" << std::endl << "property uchar green" << std::endl << "property uchar blue" << std::endl;
+
3726 PLYfile << "element face " << faces.size() << std::endl;
+
3727 PLYfile << "property list uchar int vertex_indices" << std::endl << "end_header" << std::endl;
3728
-
3729 PLYfile.close();
-
3730
-
3731
-
3732}
-
-
3733
-
-
3734std::vector<uint> Context::loadOBJ(const char* filename, bool silent ){
-
3735 return loadOBJ(filename,nullorigin,0,nullrotation,RGB::blue,"ZUP",silent);
-
3736}
-
-
3737
-
-
3738std::vector<uint> Context::loadOBJ(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, bool silent ){
-
3739 return loadOBJ(filename,origin,make_vec3(0,0,height),rotation,default_color,"ZUP",silent);
+
3729 for( size_t v=0; v<verts.size(); v++ ){
+
3730 PLYfile << verts.at(v).x << " " << verts.at(v).y << " " << verts.at(v).z << " " << round(colors.at(v).r) << " " << round(colors.at(v).g) << " " << round(colors.at(v).b) << std::endl;
+
3731 }
+
3732
+
3733 for(auto & face : faces){
+
3734 PLYfile << "3 " << face.x << " " << face.y << " " << face.z << std::endl;
+
3735 }
+
3736
+
3737 PLYfile.close();
+
3738
+
3739
3740}
3741
-
3742std::vector<uint> Context::loadOBJ(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, const char* upaxis, bool silent ) {
-
3743 return loadOBJ(filename,origin,make_vec3(0,0,height),rotation,default_color,upaxis,silent);
+
3742std::vector<uint> Context::loadOBJ(const char* filename, bool silent ){
+
3743 return loadOBJ(filename,nullorigin,0,nullrotation,RGB::blue,"ZUP",silent);
3744}
3745
-
3746std::vector<uint> Context::loadOBJ(const char* filename, const vec3 &origin, const helios::vec3 &scale, const SphericalCoord &rotation, const RGBcolor &default_color, const char* upaxis, bool silent ){
-
3747
-
3748 if( !silent ) {
-
3749 std::cout << "Reading OBJ file " << filename << "..." << std::flush;
-
3750 }
-
3751
-
3752 std::string fn = filename;
-
3753 std::string ext = getFileExtension(filename);
-
3754 if( ext != ".obj" && ext != ".OBJ" ) {
-
3755 helios_runtime_error("ERROR (Context::loadOBJ): File " + fn + " is not OBJ format.");
-
3756 }
-
3757
-
3758 if( strcmp(upaxis,"XUP") != 0 && strcmp(upaxis,"YUP") != 0 && strcmp(upaxis,"ZUP") != 0 ){
-
3759 helios_runtime_error("ERROR (Context::loadOBJ): Up axis of " + std::string(upaxis) + " is not valid. Should be one of 'XUP', 'YUP', or 'ZUP'.");
-
3760 }
-
3761
-
3762 std::string line, prop;
-
3763
-
3764 std::vector<vec3> vertices;
-
3765 std::vector<std::string> objects;
-
3766 std::vector<vec2> texture_uv;
-
3767 std::map<std::string,std::vector<std::vector<int> > > face_inds, texture_inds;
-
3768
-
3769 std::map<std::string,OBJmaterial> materials;
-
3770
-
3771 std::vector<uint> UUID;
-
3772
-
3773 std::ifstream inputOBJ, inputMTL;
-
3774 inputOBJ.open(filename);
-
3775
-
3776 if (!inputOBJ.is_open()) {
-
3777 helios_runtime_error("ERROR (Context::loadOBJ): Couldn't open " + std::string(filename) );
-
3778 }
-
3779
-
3780 //determine the base file path for 'filename'
-
3781 std::string fstring = filename;
-
3782 std::string filebase = getFilePath(fstring);
+
3746std::vector<uint> Context::loadOBJ(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, bool silent ){
+
3747 return loadOBJ(filename,origin,make_vec3(0,0,height),rotation,default_color,"ZUP",silent);
+
3748}
+
+
3749
+
+
3750std::vector<uint> Context::loadOBJ(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, const char* upaxis, bool silent ) {
+
3751 return loadOBJ(filename,origin,make_vec3(0,0,height),rotation,default_color,upaxis,silent);
+
3752}
+
+
3753
+
+
3754std::vector<uint> Context::loadOBJ(const char* filename, const vec3 &origin, const helios::vec3 &scale, const SphericalCoord &rotation, const RGBcolor &default_color, const char* upaxis, bool silent ){
+
3755
+
3756 if( !silent ) {
+
3757 std::cout << "Reading OBJ file " << filename << "..." << std::flush;
+
3758 }
+
3759
+
3760 std::string fn = filename;
+
3761 std::string ext = getFileExtension(filename);
+
3762 if( ext != ".obj" && ext != ".OBJ" ) {
+
3763 helios_runtime_error("ERROR (Context::loadOBJ): File " + fn + " is not OBJ format.");
+
3764 }
+
3765
+
3766 if( strcmp(upaxis,"XUP") != 0 && strcmp(upaxis,"YUP") != 0 && strcmp(upaxis,"ZUP") != 0 ){
+
3767 helios_runtime_error("ERROR (Context::loadOBJ): Up axis of " + std::string(upaxis) + " is not valid. Should be one of 'XUP', 'YUP', or 'ZUP'.");
+
3768 }
+
3769
+
3770 std::string line, prop;
+
3771
+
3772 std::vector<vec3> vertices;
+
3773 std::vector<std::string> objects;
+
3774 std::vector<vec2> texture_uv;
+
3775 std::map<std::string,std::vector<std::vector<int> > > face_inds, texture_inds;
+
3776
+
3777 std::map<std::string,OBJmaterial> materials;
+
3778
+
3779 std::vector<uint> UUID;
+
3780
+
3781 std::ifstream inputOBJ, inputMTL;
+
3782 inputOBJ.open(filename);
3783
-
3784 //determine bounding box
-
3785 float boxmin = 100000;
-
3786 float boxmax = -100000;
+
3784 if (!inputOBJ.is_open()) {
+
3785 helios_runtime_error("ERROR (Context::loadOBJ): Couldn't open " + std::string(filename) );
+
3786 }
3787
-
3788 std::string current_material = "none";
-
3789 std::string current_object = "none";
-
3790
-
3791 size_t lineno = 0;
-
3792 while( inputOBJ.good() ){
-
3793
-
3794 lineno++;
+
3788 //determine the base file path for 'filename'
+
3789 std::string fstring = filename;
+
3790 std::string filebase = getFilePath(fstring);
+
3791
+
3792 //determine bounding box
+
3793 float boxmin = 100000;
+
3794 float boxmax = -100000;
3795
-
3796 inputOBJ>>line;
-
3797
-
3798 // ------- COMMENTS --------- //
-
3799 if( line=="#" ){
-
3800 getline(inputOBJ, line);
+
3796 std::string current_material = "none";
+
3797 std::string current_object = "none";
+
3798
+
3799 size_t lineno = 0;
+
3800 while( inputOBJ.good() ){
3801
-
3802 // ------- MATERIAL LIBRARY ------- //
-
3803 }else if( line=="mtllib" ){
-
3804 getline(inputOBJ, line);
-
3805 std::string material_file = trim_whitespace(line);
-
3806 materials = loadMTL( filebase, material_file );
-
3807
-
3808 // ------- OBJECT ------- //
-
3809 }else if( line=="o" ){
-
3810 getline(inputOBJ, line);
-
3811 current_object = trim_whitespace(line);
-
3812
-
3813 // ------- VERTICES --------- //
-
3814 }else if( line=="v" ){
-
3815 getline(inputOBJ, line);
-
3816 //parse vertices into points
-
3817 vec3 verts(string2vec3(line.c_str()));
-
3818 vertices.emplace_back(verts);
-
3819 objects.emplace_back(current_object);
+
3802 lineno++;
+
3803
+
3804 inputOBJ>>line;
+
3805
+
3806 // ------- COMMENTS --------- //
+
3807 if( line=="#" ){
+
3808 getline(inputOBJ, line);
+
3809
+
3810 // ------- MATERIAL LIBRARY ------- //
+
3811 }else if( line=="mtllib" ){
+
3812 getline(inputOBJ, line);
+
3813 std::string material_file = trim_whitespace(line);
+
3814 materials = loadMTL( filebase, material_file );
+
3815
+
3816 // ------- OBJECT ------- //
+
3817 }else if( line=="o" ){
+
3818 getline(inputOBJ, line);
+
3819 current_object = trim_whitespace(line);
3820
-
3821 if(verts.z < boxmin ){
-
3822 boxmin = verts.z;
-
3823 }
-
3824 if(verts.z > boxmax ){
-
3825 boxmax = verts.z;
-
3826 }
-
3827
-
3828 // ------- TEXTURE COORDINATES --------- //
-
3829 }else if( line=="vt" ){
-
3830 getline(inputOBJ, line);
-
3831 line = trim_whitespace(line);
-
3832 //parse coordinates into uv
-
3833 vec2 uv(string2vec2(line.c_str()));
-
3834 texture_uv.emplace_back(uv);
+
3821 // ------- VERTICES --------- //
+
3822 }else if( line=="v" ){
+
3823 getline(inputOBJ, line);
+
3824 //parse vertices into points
+
3825 vec3 verts(string2vec3(line.c_str()));
+
3826 vertices.emplace_back(verts);
+
3827 objects.emplace_back(current_object);
+
3828
+
3829 if(verts.z < boxmin ){
+
3830 boxmin = verts.z;
+
3831 }
+
3832 if(verts.z > boxmax ){
+
3833 boxmax = verts.z;
+
3834 }
3835
-
3836 // ------- MATERIALS --------- //
-
3837 }else if( line=="usemtl" ){
+
3836 // ------- TEXTURE COORDINATES --------- //
+
3837 }else if( line=="vt" ){
3838 getline(inputOBJ, line);
-
3839 current_material = trim_whitespace(line);
-
3840
-
3841 // ------- FACES --------- //
-
3842 }else if( line=="f" ){
-
3843 getline(inputOBJ, line);
-
3844 //parse face vertices
-
3845 std::istringstream stream(line);
-
3846 std::string tmp, digitf, digitu;
-
3847 std::vector<int> f, u;
-
3848 while( stream.good() ){
-
3849
-
3850 stream >> tmp;
-
3851
-
3852 digitf="";
-
3853 int ic = 0;
-
3854 for(char i : tmp){
-
3855 if( isdigit(i) ){
-
3856 digitf.push_back( i );
-
3857 ic++;
-
3858 }else{
-
3859 break;
-
3860 }
-
3861 }
-
3862
-
3863 digitu="";
-
3864 for( int i=ic+1; i<tmp.size(); i++ ){
-
3865 if( isdigit(tmp[i]) ){
-
3866 digitu.push_back( tmp[i] );
-
3867 }else{
-
3868 break;
-
3869 }
-
3870 }
-
3871
-
3872 if( !digitf.empty() ) {
-
3873 int face;
-
3874 if( !parse_int( digitf, face ) ){
-
3875 helios_runtime_error("ERROR (Context::loadOBJ): Face index on line " + std::to_string(lineno) + " must be a non-negative integer value.");
-
3876 }
-
3877 f.push_back(face);
+
3839 line = trim_whitespace(line);
+
3840 //parse coordinates into uv
+
3841 vec2 uv(string2vec2(line.c_str()));
+
3842 texture_uv.emplace_back(uv);
+
3843
+
3844 // ------- MATERIALS --------- //
+
3845 }else if( line=="usemtl" ){
+
3846 getline(inputOBJ, line);
+
3847 current_material = trim_whitespace(line);
+
3848
+
3849 // ------- FACES --------- //
+
3850 }else if( line=="f" ){
+
3851 getline(inputOBJ, line);
+
3852 //parse face vertices
+
3853 std::istringstream stream(line);
+
3854 std::string tmp, digitf, digitu;
+
3855 std::vector<int> f, u;
+
3856 while( stream.good() ){
+
3857
+
3858 stream >> tmp;
+
3859
+
3860 digitf="";
+
3861 int ic = 0;
+
3862 for(char i : tmp){
+
3863 if( isdigit(i) ){
+
3864 digitf.push_back( i );
+
3865 ic++;
+
3866 }else{
+
3867 break;
+
3868 }
+
3869 }
+
3870
+
3871 digitu="";
+
3872 for( int i=ic+1; i<tmp.size(); i++ ){
+
3873 if( isdigit(tmp[i]) ){
+
3874 digitu.push_back( tmp[i] );
+
3875 }else{
+
3876 break;
+
3877 }
3878 }
-
3879 if( !digitu.empty() ){
-
3880 int uv;
-
3881 if( !parse_int( digitu, uv ) ){
-
3882 helios_runtime_error("ERROR (Context::loadOBJ): u,v index on line " + std::to_string(lineno) + " must be a non-negative integer value.");
-
3883 }
-
3884 u.push_back( uv );
-
3885 }
-
3886
-
3887 }
-
3888 face_inds[current_material].push_back(f);
-
3889 texture_inds[current_material].push_back(u);
-
3890
-
3891 // ------ OTHER STUFF --------- //
-
3892 }else{
-
3893 getline(inputOBJ, line);
-
3894 }
-
3895 }
-
3896
-
3897 vec3 scl = scale;
-
3898 if( scl.x==0 && scl.y==0 && scl.z>0 ) {
-
3899 scl = make_vec3( scale.z / (boxmax - boxmin), scale.z / (boxmax - boxmin), scale.z / (boxmax - boxmin) );
-
3900 }else {
-
3901
-
3902 if( scl.x==0 && (scl.y!=0 || scl.z!=0) ) {
-
3903 std::cout << "WARNING (Context::loadOBJ): Scaling factor given for x-direction is zero. Setting scaling factor to 1"<< std::endl;
-
3904 }
-
3905 if( scl.y==0 && (scl.x!=0 || scl.z!=0) ) {
-
3906 std::cout << "WARNING (Context::loadOBJ): Scaling factor given for y-direction is zero. Setting scaling factor to 1" << std::endl;
-
3907 }
-
3908 if( scl.z==0 && (scl.x!=0 || scl.y!=0) ) {
-
3909 std::cout << "WARNING (Context::loadOBJ): Scaling factor given for z-direction is zero. Setting scaling factor to 1" << std::endl;
-
3910 }
-
3911
-
3912 if (scl.x == 0) {
-
3913 scl.x = 1;
-
3914 }
-
3915 if (scl.y == 0) {
-
3916 scl.y = 1;
-
3917 }
-
3918 if (scl.z == 0) {
-
3919 scl.z = 1;
-
3920 }
-
3921
-
3922 }
-
3923
-
3924 for( auto iter = face_inds.begin(); iter != face_inds.end(); ++iter){
-
3925
-
3926 std::string materialname = iter->first;
-
3927
-
3928 std::string texture;
-
3929 RGBcolor color = default_color;
-
3930 bool textureColorIsOverridden = false;
+
3879
+
3880 if( !digitf.empty() ) {
+
3881 int face;
+
3882 if( !parse_int( digitf, face ) ){
+
3883 helios_runtime_error("ERROR (Context::loadOBJ): Face index on line " + std::to_string(lineno) + " must be a non-negative integer value.");
+
3884 }
+
3885 f.push_back(face);
+
3886 }
+
3887 if( !digitu.empty() ){
+
3888 int uv;
+
3889 if( !parse_int( digitu, uv ) ){
+
3890 helios_runtime_error("ERROR (Context::loadOBJ): u,v index on line " + std::to_string(lineno) + " must be a non-negative integer value.");
+
3891 }
+
3892 u.push_back( uv );
+
3893 }
+
3894
+
3895 }
+
3896 face_inds[current_material].push_back(f);
+
3897 texture_inds[current_material].push_back(u);
+
3898
+
3899 // ------ OTHER STUFF --------- //
+
3900 }else{
+
3901 getline(inputOBJ, line);
+
3902 }
+
3903 }
+
3904
+
3905 vec3 scl = scale;
+
3906 if( scl.x==0 && scl.y==0 && scl.z>0 ) {
+
3907 scl = make_vec3( scale.z / (boxmax - boxmin), scale.z / (boxmax - boxmin), scale.z / (boxmax - boxmin) );
+
3908 }else {
+
3909
+
3910 if( scl.x==0 && (scl.y!=0 || scl.z!=0) ) {
+
3911 std::cout << "WARNING (Context::loadOBJ): Scaling factor given for x-direction is zero. Setting scaling factor to 1"<< std::endl;
+
3912 }
+
3913 if( scl.y==0 && (scl.x!=0 || scl.z!=0) ) {
+
3914 std::cout << "WARNING (Context::loadOBJ): Scaling factor given for y-direction is zero. Setting scaling factor to 1" << std::endl;
+
3915 }
+
3916 if( scl.z==0 && (scl.x!=0 || scl.y!=0) ) {
+
3917 std::cout << "WARNING (Context::loadOBJ): Scaling factor given for z-direction is zero. Setting scaling factor to 1" << std::endl;
+
3918 }
+
3919
+
3920 if (scl.x == 0) {
+
3921 scl.x = 1;
+
3922 }
+
3923 if (scl.y == 0) {
+
3924 scl.y = 1;
+
3925 }
+
3926 if (scl.z == 0) {
+
3927 scl.z = 1;
+
3928 }
+
3929
+
3930 }
3931
-
3932 if( materials.find(materialname)!=materials.end() ) {
+
3932 for( auto iter = face_inds.begin(); iter != face_inds.end(); ++iter){
3933
-
3934 OBJmaterial mat = materials.at(materialname);
+
3934 std::string materialname = iter->first;
3935
-
3936 texture = mat.texture;
-
3937 color = mat.color;
-
3938 textureColorIsOverridden = mat.textureColorIsOverridden;
+
3936 std::string texture;
+
3937 RGBcolor color = default_color;
+
3938 bool textureColorIsOverridden = false;
3939
-
3940 }
+
3940 if( materials.find(materialname)!=materials.end() ) {
3941
-
3942 for( size_t i=0; i<face_inds.at(materialname).size(); i++ ){
+
3942 OBJmaterial mat = materials.at(materialname);
3943
-
3944 for( uint t=2; t<face_inds.at(materialname).at(i).size(); t++ ){
-
3945
-
3946 vec3 v0 = vertices.at(face_inds.at(materialname).at(i).at(0)-1);
-
3947 vec3 v1 = vertices.at(face_inds.at(materialname).at(i).at(t-1)-1);
-
3948 vec3 v2 = vertices.at(face_inds.at(materialname).at(i).at(t)-1);
+
3944 texture = mat.texture;
+
3945 color = mat.color;
+
3946 textureColorIsOverridden = mat.textureColorIsOverridden;
+
3947
+
3948 }
3949
-
3950 if( (v0-v1).magnitude()==0 || (v0-v2).magnitude()==0 || (v1-v2).magnitude()==0 ){
-
3951 continue;
-
3952 }
+
3950 for( size_t i=0; i<face_inds.at(materialname).size(); i++ ){
+
3951
+
3952 for( uint t=2; t<face_inds.at(materialname).at(i).size(); t++ ){
3953
-
3954 if( strcmp(upaxis,"YUP")==0 ){
-
3955 v0 = rotatePointAboutLine(v0,make_vec3(0,0,0),make_vec3(1,0,0),0.5*M_PI);
-
3956 v1 = rotatePointAboutLine(v1,make_vec3(0,0,0),make_vec3(1,0,0),0.5*M_PI);
-
3957 v2 = rotatePointAboutLine(v2,make_vec3(0,0,0),make_vec3(1,0,0),0.5*M_PI);
-
3958 }
-
3959
-
3960 v0 = rotatePoint(v0,rotation);
-
3961 v1 = rotatePoint(v1,rotation);
-
3962 v2 = rotatePoint(v2,rotation);
-
3963
-
3964 uint ID;
-
3965 if( !texture.empty() && !texture_inds.at(materialname).at(i).empty() ){//has texture
-
3966
-
3967 if( t<texture_inds.at(materialname).at(i).size() ){
-
3968 int iuv0 = texture_inds.at(materialname).at(i).at(0)-1;
-
3969 int iuv1 = texture_inds.at(materialname).at(i).at(t-1)-1;
-
3970 int iuv2 = texture_inds.at(materialname).at(i).at(t)-1;
+
3954 vec3 v0 = vertices.at(face_inds.at(materialname).at(i).at(0)-1);
+
3955 vec3 v1 = vertices.at(face_inds.at(materialname).at(i).at(t-1)-1);
+
3956 vec3 v2 = vertices.at(face_inds.at(materialname).at(i).at(t)-1);
+
3957
+
3958 if( (v0-v1).magnitude()==0 || (v0-v2).magnitude()==0 || (v1-v2).magnitude()==0 ){
+
3959 continue;
+
3960 }
+
3961
+
3962 if( strcmp(upaxis,"YUP")==0 ){
+
3963 v0 = rotatePointAboutLine(v0,make_vec3(0,0,0),make_vec3(1,0,0),0.5*M_PI);
+
3964 v1 = rotatePointAboutLine(v1,make_vec3(0,0,0),make_vec3(1,0,0),0.5*M_PI);
+
3965 v2 = rotatePointAboutLine(v2,make_vec3(0,0,0),make_vec3(1,0,0),0.5*M_PI);
+
3966 }
+
3967
+
3968 v0 = rotatePoint(v0,rotation);
+
3969 v1 = rotatePoint(v1,rotation);
+
3970 v2 = rotatePoint(v2,rotation);
3971
-
3972 ID = addTriangle( origin+v0*scl.x, origin+v1*scl.y, origin+v2*scl.z, texture.c_str(), texture_uv.at(iuv0), texture_uv.at(iuv1), texture_uv.at(iuv2) );
-
3973
-
3974 if( textureColorIsOverridden ){
-
3975 setPrimitiveColor( ID, color );
- -
3977 }
-
3978
-
3979 }
-
3980 }else{
-
3981 ID = addTriangle( origin+v0*scl.x, origin+v1*scl.y, origin+v2*scl.z, color );
-
3982 }
-
3983
-
3984 std::string object = objects.at(face_inds.at(materialname).at(i).at(0)-1);
-
3985
-
3986 if( object!="none" && doesPrimitiveExist(ID) ){
-
3987 setPrimitiveData(ID,"object_label",object);
-
3988 }
-
3989
-
3990 UUID.push_back(ID);
+
3972 uint ID;
+
3973 if( !texture.empty() && !texture_inds.at(materialname).at(i).empty() ){//has texture
+
3974
+
3975 if( t<texture_inds.at(materialname).at(i).size() ){
+
3976 int iuv0 = texture_inds.at(materialname).at(i).at(0)-1;
+
3977 int iuv1 = texture_inds.at(materialname).at(i).at(t-1)-1;
+
3978 int iuv2 = texture_inds.at(materialname).at(i).at(t)-1;
+
3979
+
3980 ID = addTriangle( origin+v0*scl.x, origin+v1*scl.y, origin+v2*scl.z, texture.c_str(), texture_uv.at(iuv0), texture_uv.at(iuv1), texture_uv.at(iuv2) );
+
3981
+
3982 if( textureColorIsOverridden ){
+
3983 setPrimitiveColor( ID, color );
+ +
3985 }
+
3986
+
3987 }
+
3988 }else{
+
3989 ID = addTriangle( origin+v0*scl.x, origin+v1*scl.y, origin+v2*scl.z, color );
+
3990 }
3991
-
3992 }
-
3993 }
-
3994 }
-
3995
-
3996 if( !silent ) {
-
3997 std::cout << "done." << std::endl;
-
3998 }
+
3992 std::string object = objects.at(face_inds.at(materialname).at(i).at(0)-1);
+
3993
+
3994 if( object!="none" && doesPrimitiveExist(ID) ){
+
3995 setPrimitiveData(ID,"object_label",object);
+
3996 }
+
3997
+
3998 UUID.push_back(ID);
3999
-
4000 return UUID;
-
4001
-
4002}
-
+
4000 }
+
4001 }
+
4002 }
4003
-
4004std::map<std::string, Context::OBJmaterial> Context::loadMTL(const std::string &filebase, const std::string &material_file ){
-
4005
-
4006 std::ifstream inputMTL;
+
4004 if( !silent ) {
+
4005 std::cout << "done." << std::endl;
+
4006 }
4007
-
4008 std::string file = material_file;
+
4008 return UUID;
4009
-
4010 //first look for mtl file using path given in obj file
-
4011 inputMTL.open(file.c_str());
-
4012 if( !inputMTL.is_open() ){
-
4013 //if that doesn't work, try looking in the same directory where obj file is located
-
4014 file = filebase+file;
-
4015 file.erase( remove( file.begin(), file.end(), ' ' ), file.end() );
-
4016 for( size_t i=file.size()-1; i>=0; i-- ){
-
4017 if( strcmp(&file.at(i),"l")==0 ){
-
4018 break;
-
4019 }else{
-
4020 file.erase(file.begin()+(int)i);
-
4021 }
-
4022 }
-
4023 if( file.empty() ){
-
4024 helios_runtime_error("ERROR (Context::loadMTL): Material file does not have correct file extension (.mtl).");
-
4025 }
-
4026 inputMTL.open( file.c_str() );
-
4027 if( !inputMTL.is_open() ){
-
4028 helios_runtime_error("ERROR (Context::loadMTL): Material file " + std::string(file) + " given in .obj file cannot be found.");
-
4029 }
-
4030 }
-
4031
-
4032 std::map<std::string, OBJmaterial> materials;
-
4033
-
4034 std::string line;
-
4035
-
4036 inputMTL>>line;
-
4037
-
4038 while( inputMTL.good() ){
+
4010}
+
+
4011
+
4012std::map<std::string, Context::OBJmaterial> Context::loadMTL(const std::string &filebase, const std::string &material_file ){
+
4013
+
4014 std::ifstream inputMTL;
+
4015
+
4016 std::string file = material_file;
+
4017
+
4018 //first look for mtl file using path given in obj file
+
4019 inputMTL.open(file.c_str());
+
4020 if( !inputMTL.is_open() ){
+
4021 //if that doesn't work, try looking in the same directory where obj file is located
+
4022 file = filebase+file;
+
4023 file.erase( remove( file.begin(), file.end(), ' ' ), file.end() );
+
4024 for( size_t i=file.size()-1; i>=0; i-- ){
+
4025 if( strcmp(&file.at(i),"l")==0 ){
+
4026 break;
+
4027 }else{
+
4028 file.erase(file.begin()+(int)i);
+
4029 }
+
4030 }
+
4031 if( file.empty() ){
+
4032 helios_runtime_error("ERROR (Context::loadMTL): Material file does not have correct file extension (.mtl).");
+
4033 }
+
4034 inputMTL.open( file.c_str() );
+
4035 if( !inputMTL.is_open() ){
+
4036 helios_runtime_error("ERROR (Context::loadMTL): Material file " + std::string(file) + " given in .obj file cannot be found.");
+
4037 }
+
4038 }
4039
-
4040 if( strcmp("#",line.c_str())==0 ){ //comments
-
4041 getline(inputMTL, line);
-
4042 inputMTL>>line;
-
4043 }else if( line=="newmtl" ){ //material library
-
4044 getline(inputMTL, line);
-
4045 std::string material_name = trim_whitespace(line);
-
4046 OBJmaterial mat(RGB::red,"",0);
-
4047 materials.emplace( material_name,mat );
-
4048
-
4049 std::string map_Kd, map_d;
-
4050
-
4051 while( line!="newmtl" && inputMTL.good() ){
-
4052
-
4053 if( line=="map_a" ){
-
4054 getline(inputMTL, line);
-
4055 }else if( line=="map_Ka" ){
-
4056 getline(inputMTL, line);
-
4057 }else if( line=="map_Kd" || line=="map_d" ){
-
4058 std::string maptype = line;
-
4059 getline(inputMTL, line);
-
4060 line = trim_whitespace(line);
-
4061 std::istringstream stream(line);
-
4062 std::string tmp;
-
4063 while( stream.good() ){
-
4064 stream >> tmp;
-
4065 std::string ext = getFileExtension(tmp);
-
4066 if( ext==".png" || ext==".PNG" || ext==".jpg" || ext==".JPG" || ext==".jpeg" || ext==".JPEG" ){
-
4067
-
4068 std::string texturefile = tmp;
-
4069 std::ifstream tfile;
-
4070
-
4071 //first look for texture file using path given in mtl file
-
4072 tfile.open(texturefile.c_str());
-
4073 if( !tfile.is_open() ){
-
4074 //if that doesn't work, try looking in the same directory where obj file is located
-
4075 tfile.close();
-
4076 texturefile = filebase+texturefile;
-
4077 tfile.open( texturefile.c_str() );
-
4078 if( !tfile.is_open() ){
-
4079 std::cerr << "WARNING (Context::loadOBJ): Texture file " << texturefile << " given in .mtl file cannot be found." << std::endl;
-
4080 }
-
4081 }
-
4082 tfile.close();
-
4083
-
4084 materials.at(material_name).texture = texturefile;
-
4085
-
4086 if( maptype=="map_d" ) {
-
4087 map_d = texturefile;
-
4088 }else{
-
4089 map_Kd = texturefile;
-
4090 }
-
4091 }
-
4092 }
+
4040 std::map<std::string, OBJmaterial> materials;
+
4041
+
4042 std::string line;
+
4043
+
4044 inputMTL>>line;
+
4045
+
4046 while( inputMTL.good() ){
+
4047
+
4048 if( strcmp("#",line.c_str())==0 ){ //comments
+
4049 getline(inputMTL, line);
+
4050 inputMTL>>line;
+
4051 }else if( line=="newmtl" ){ //material library
+
4052 getline(inputMTL, line);
+
4053 std::string material_name = trim_whitespace(line);
+
4054 OBJmaterial mat(RGB::red,"",0);
+
4055 materials.emplace( material_name,mat );
+
4056
+
4057 std::string map_Kd, map_d;
+
4058
+
4059 while( line!="newmtl" && inputMTL.good() ){
+
4060
+
4061 if( line=="map_a" ){
+
4062 getline(inputMTL, line);
+
4063 }else if( line=="map_Ka" ){
+
4064 getline(inputMTL, line);
+
4065 }else if( line=="map_Kd" || line=="map_d" ){
+
4066 std::string maptype = line;
+
4067 getline(inputMTL, line);
+
4068 line = trim_whitespace(line);
+
4069 std::istringstream stream(line);
+
4070 std::string tmp;
+
4071 while( stream.good() ){
+
4072 stream >> tmp;
+
4073 std::string ext = getFileExtension(tmp);
+
4074 if( ext==".png" || ext==".PNG" || ext==".jpg" || ext==".JPG" || ext==".jpeg" || ext==".JPEG" ){
+
4075
+
4076 std::string texturefile = tmp;
+
4077 std::ifstream tfile;
+
4078
+
4079 //first look for texture file using path given in mtl file
+
4080 tfile.open(texturefile.c_str());
+
4081 if( !tfile.is_open() ){
+
4082 //if that doesn't work, try looking in the same directory where obj file is located
+
4083 tfile.close();
+
4084 texturefile = filebase+texturefile;
+
4085 tfile.open( texturefile.c_str() );
+
4086 if( !tfile.is_open() ){
+
4087 std::cerr << "WARNING (Context::loadOBJ): Texture file " << texturefile << " given in .mtl file cannot be found." << std::endl;
+
4088 }
+
4089 }
+
4090 tfile.close();
+
4091
+
4092 materials.at(material_name).texture = texturefile;
4093
-
4094 }else if( line=="map_Ks" ){
-
4095 getline(inputMTL, line);
-
4096
-
4097 }else if( line=="Kd" ){
-
4098 getline(inputMTL, line);
-
4099 std::string color_str = trim_whitespace(line );
-
4100 RGBAcolor color = string2RGBcolor(color_str.c_str());
-
4101 materials.at(material_name).color = make_RGBcolor(color.r,color.g,color.b);
-
4102 }else{
+
4094 if( maptype=="map_d" ) {
+
4095 map_d = texturefile;
+
4096 }else{
+
4097 map_Kd = texturefile;
+
4098 }
+
4099 }
+
4100 }
+
4101
+
4102 }else if( line=="map_Ks" ){
4103 getline(inputMTL, line);
-
4104 }
-
4105
-
4106 inputMTL>>line;
-
4107 }
-
4108
-
4109 if( map_Kd.empty() && !map_d.empty() ){
-
4110 materials.at(material_name).textureColorIsOverridden=true;
-
4111 }
-
4112
-
4113 }else{
-
4114 getline(inputMTL, line);
-
4115 inputMTL>>line;
-
4116 }
-
4117 }
-
4118
-
4119 return materials;
+
4104
+
4105 }else if( line=="Kd" ){
+
4106 getline(inputMTL, line);
+
4107 std::string color_str = trim_whitespace(line );
+
4108 RGBAcolor color = string2RGBcolor(color_str.c_str());
+
4109 materials.at(material_name).color = make_RGBcolor(color.r,color.g,color.b);
+
4110 }else{
+
4111 getline(inputMTL, line);
+
4112 }
+
4113
+
4114 inputMTL>>line;
+
4115 }
+
4116
+
4117 if( map_Kd.empty() && !map_d.empty() ){
+
4118 materials.at(material_name).textureColorIsOverridden=true;
+
4119 }
4120
-
4121}
-
4122
-
-
4123void Context::writeOBJ( const std::string &filename ) const {
-
4124 writeOBJ(filename, getAllUUIDs(),{});
-
4125}
-
+
4121 }else{
+
4122 getline(inputMTL, line);
+
4123 inputMTL>>line;
+
4124 }
+
4125 }
4126
-
-
4127void Context::writeOBJ( const std::string &filename, const std::vector<uint> &UUIDs ) const {
-
4128 writeOBJ(filename,UUIDs,{});
+
4127 return materials;
+
4128
4129}
-
4130
-
4131void Context::writeOBJ( const std::string &filename, const std::vector<uint> &UUIDs, const std::vector<std::string> &primitive_dat_fields ) const{
-
4132
-
4133 //To-Do list for OBJ writer
-
4134 // - it would make more sense to write patches as quads rather than two triangles
-
4135
-
4136 if( UUIDs.empty() ){
-
4137 std::cout << "WARNING (Context::writeOBJ): No primitives found to write - OBJ file will not be written." << std::endl;
-
4138 return;
-
4139 }else if( filename.empty() ){
-
4140 std::cout << "WARNING (Context::writeOBJ): Filename was empty - OBJ file will not be written." << std::endl;
-
4141 return;
-
4142 }
+
4131void Context::writeOBJ( const std::string &filename ) const {
+
4132 writeOBJ(filename, getAllUUIDs(),{});
+
4133}
+
+
4134
+
+
4135void Context::writeOBJ( const std::string &filename, const std::vector<uint> &UUIDs ) const {
+
4136 writeOBJ(filename,UUIDs,{});
+
4137}
+
+
4138
+
+
4139void Context::writeOBJ( const std::string &filename, const std::vector<uint> &UUIDs, const std::vector<std::string> &primitive_dat_fields ) const{
+
4140
+
4141 //To-Do list for OBJ writer
+
4142 // - it would make more sense to write patches as quads rather than two triangles
4143
-
4144 std::string objfilename = filename;
-
4145 std::string mtlfilename = filename;
-
4146
-
4147 auto file_extension = getFileExtension(filename);
-
4148 auto file_stem = getFileStem(filename);
-
4149 auto file_path = getFilePath(filename);
-
4150
-
4151 std::string fn = filename;
-
4152 if( file_extension != ".obj" && file_extension != ".OBJ" ) { // append obj to file name
-
4153 objfilename.append(".obj");
-
4154 mtlfilename.append(".mtl");
-
4155 }else{
-
4156 if( !file_path.empty() ){
-
4157 mtlfilename = file_path + "/" + file_stem + ".mtl";
-
4158 }else{
-
4159 mtlfilename = file_stem + ".mtl";
-
4160 }
-
4161 }
-
4162
-
4163 if( !std::filesystem::exists(file_path) ){
-
4164 if( !std::filesystem::create_directory(file_path) ){
-
4165 std::cout << "failed. Directory " << file_path << " does not exist and it could not be created - OBJ file will not be written." << std::endl;
-
4166 return;
-
4167 }
-
4168 }
-
4169
-
4170 std::cout << "Writing OBJ file " << objfilename << "..." << std::flush;
-
4171
-
4172 std::vector<OBJmaterial> materials;
-
4173
-
4174 bool uuidexistswarning = false;
-
4175 bool voxelwarning = false;
-
4176
-
4177 std::vector<vec3> verts;
-
4178 std::vector<vec2> uv;
-
4179 std::map< uint, std::vector<int3> > faces;
-
4180 std::map< uint, std::vector<int3> > uv_inds;
-
4181 size_t vertex_count = 1; //OBJ files start indices at 1
-
4182 size_t uv_count = 1;
-
4183 std::map<uint,std::vector<uint> > UUIDs_write;
+
4144 if( UUIDs.empty() ){
+
4145 std::cout << "WARNING (Context::writeOBJ): No primitives found to write - OBJ file will not be written." << std::endl;
+
4146 return;
+
4147 }else if( filename.empty() ){
+
4148 std::cout << "WARNING (Context::writeOBJ): Filename was empty - OBJ file will not be written." << std::endl;
+
4149 return;
+
4150 }
+
4151
+
4152 std::string objfilename = filename;
+
4153 std::string mtlfilename = filename;
+
4154
+
4155 auto file_extension = getFileExtension(filename);
+
4156 auto file_stem = getFileStem(filename);
+
4157 auto file_path = getFilePath(filename);
+
4158
+
4159 std::string fn = filename;
+
4160 if( file_extension != ".obj" && file_extension != ".OBJ" ) { // append obj to file name
+
4161 objfilename.append(".obj");
+
4162 mtlfilename.append(".mtl");
+
4163 }else{
+
4164 if( !file_path.empty() ){
+
4165 mtlfilename = file_path + "/" + file_stem + ".mtl";
+
4166 }else{
+
4167 mtlfilename = file_stem + ".mtl";
+
4168 }
+
4169 }
+
4170
+
4171 if( !file_path.empty() && !std::filesystem::exists(file_path) ){
+
4172 if( !std::filesystem::create_directory(file_path) ){
+
4173 std::cout << "failed. Directory " << file_path << " does not exist and it could not be created - OBJ file will not be written." << std::endl;
+
4174 return;
+
4175 }
+
4176 }
+
4177
+
4178 std::cout << "Writing OBJ file " << objfilename << "..." << std::flush;
+
4179
+
4180 std::vector<OBJmaterial> materials;
+
4181
+
4182 bool uuidexistswarning = false;
+
4183 bool voxelwarning = false;
4184
-
4185 for ( size_t p : UUIDs ) {
-
4186
-
4187 if( !doesPrimitiveExist(p) ){
-
4188 uuidexistswarning = true;
-
4189 continue;
-
4190 }else if( getPrimitivePointer_private(p)->getType()==PRIMITIVE_TYPE_VOXEL ){
-
4191 voxelwarning = true;
-
4192 continue;
-
4193 }
+
4185 std::vector<vec3> verts;
+
4186 std::vector<vec2> uv;
+
4187 std::map< uint, std::vector<int3> > faces;
+
4188 std::map< uint, std::vector<int3> > uv_inds;
+
4189 size_t vertex_count = 1; //OBJ files start indices at 1
+
4190 size_t uv_count = 1;
+
4191 std::map<uint,std::vector<uint> > UUIDs_write;
+
4192
+
4193 for ( size_t p : UUIDs ) {
4194
-
4195 std::vector < vec3 > vertices = getPrimitivePointer_private(p)->getVertices();
-
4196 PrimitiveType type = getPrimitivePointer_private(p)->getType();
-
4197 RGBcolor C = getPrimitivePointer_private(p)->getColor();
-
4198 std::string texturefile = getPrimitivePointer_private(p)->getTextureFile();
-
4199
-
4200 bool material_exists=false;
-
4201 uint material_ID = 99999;
+
4195 if( !doesPrimitiveExist(p) ){
+
4196 uuidexistswarning = true;
+
4197 continue;
+
4198 }else if( getPrimitivePointer_private(p)->getType()==PRIMITIVE_TYPE_VOXEL ){
+
4199 voxelwarning = true;
+
4200 continue;
+
4201 }
4202
-
4203 for( auto & material : materials) {
-
4204
-
4205 if( material.texture==texturefile && material.color==C && material.textureColorIsOverridden==getPrimitivePointer_private(p)->isTextureColorOverridden() ){
-
4206 material_exists=true;
-
4207 material_ID = material.materialID;
-
4208 break;
-
4209 }
+
4203 std::vector < vec3 > vertices = getPrimitivePointer_private(p)->getVertices();
+
4204 PrimitiveType type = getPrimitivePointer_private(p)->getType();
+
4205 RGBcolor C = getPrimitivePointer_private(p)->getColor();
+
4206 std::string texturefile = getPrimitivePointer_private(p)->getTextureFile();
+
4207
+
4208 bool material_exists=false;
+
4209 uint material_ID = 99999;
4210
-
4211 }
+
4211 for( auto & material : materials) {
4212
-
4213 if( !material_exists ){
-
4214 OBJmaterial mat(C,texturefile, materials.size() );
-
4215 materials.emplace_back(mat);
-
4216 material_ID = mat.materialID;
- -
4218 materials.back().textureHasTransparency=true;
-
4219 }
- -
4221 materials.back().textureColorIsOverridden=true;
-
4222 }
-
4223 }
-
4224
-
4225 if( !primitive_dat_fields.empty() ) {
-
4226 UUIDs_write[material_ID].push_back(p);
-
4227 }
-
4228
-
4229 if (type == PRIMITIVE_TYPE_TRIANGLE) {
-
4230
-
4231 faces[material_ID].push_back(make_int3( (int)vertex_count, (int)vertex_count + 1, (int)vertex_count + 2));
-
4232 for (int i = 0; i < 3; i++) {
-
4233 verts.push_back(vertices.at(i));
-
4234 vertex_count++;
-
4235 }
+
4213 if( material.texture==texturefile && material.color==C && material.textureColorIsOverridden==getPrimitivePointer_private(p)->isTextureColorOverridden() ){
+
4214 material_exists=true;
+
4215 material_ID = material.materialID;
+
4216 break;
+
4217 }
+
4218
+
4219 }
+
4220
+
4221 if( !material_exists ){
+
4222 OBJmaterial mat(C,texturefile, materials.size() );
+
4223 materials.emplace_back(mat);
+
4224 material_ID = mat.materialID;
+ +
4226 materials.back().textureHasTransparency=true;
+
4227 }
+ +
4229 materials.back().textureColorIsOverridden=true;
+
4230 }
+
4231 }
+
4232
+
4233 if( !primitive_dat_fields.empty() ) {
+
4234 UUIDs_write[material_ID].push_back(p);
+
4235 }
4236
-
4237 std::vector < vec2 > uv_v = getTrianglePointer_private(p)->getTextureUV();
-
4238 if (getTrianglePointer_private(p)->hasTexture() ) {
-
4239 uv_inds[material_ID].push_back(make_int3( (int)uv_count, (int)uv_count + 1, (int)uv_count + 2));
-
4240 for (int i = 0; i < 3; i++) {
-
4241 uv.push_back( uv_v.at(i) );
-
4242 uv_count++;
-
4243 }
-
4244 }
-
4245 else {
-
4246 uv_inds[material_ID].push_back(make_int3(-1, -1, -1));
-
4247 }
-
4248
-
4249 } else if (type == PRIMITIVE_TYPE_PATCH) {
-
4250
-
4251 faces[material_ID].push_back(make_int3( (int)vertex_count, (int)vertex_count + 1, (int)vertex_count + 2));
-
4252 faces[material_ID].push_back(make_int3( (int)vertex_count, (int)vertex_count + 2, (int)vertex_count + 3));
-
4253 for (int i = 0; i < 4; i++) {
-
4254 verts.push_back(vertices.at(i));
-
4255 vertex_count++;
-
4256 }
-
4257 std::vector < vec2 > uv_v;
-
4258 uv_v = getPatchPointer_private(p)->getTextureUV();
-
4259
-
4260 if (getPatchPointer_private(p)->hasTexture() ) {
-
4261 uv_inds[material_ID].push_back(make_int3( (int)uv_count, (int)uv_count + 1, (int)uv_count + 2));
-
4262 uv_inds[material_ID].push_back(make_int3( (int)uv_count, (int)uv_count + 2, (int)uv_count + 3));
-
4263 if (uv_v.empty()) { //default (u,v)
-
4264 uv.push_back( make_vec2(0, 1) );
-
4265 uv.push_back( make_vec2(1, 1) );
-
4266 uv.push_back( make_vec2(1, 0) );
-
4267 uv.push_back( make_vec2(0, 0) );
-
4268 uv_count += 4;
-
4269 } else { //custom (u,v)
-
4270 for (int i = 0; i < 4; i++) {
-
4271 uv.push_back( uv_v.at(i) );
-
4272 uv_count++;
-
4273 }
-
4274 }
-
4275 } else {
-
4276 uv_inds[material_ID].push_back(make_int3(-1, -1, -1));
-
4277 uv_inds[material_ID].push_back(make_int3(-1, -1, -1));
-
4278 }
-
4279
-
4280 }
-
4281 }
-
4282
-
4283 // assert(verts.size() == faces.size());
-
4284 assert(uv_inds.size() == faces.size());
-
4285 for( int i=0; i<faces.size(); i++ ){
-
4286 assert( uv_inds.at(i).size() == faces.at(i).size() );
-
4287 }
-
4288
-
4289 //copy material textures to new directory and edit old file paths
-
4290 std::string texture_dir = std::string(file_path);
-
4291 for (int mat = 0; mat < materials.size(); mat++) {
-
4292 std::string texture = materials.at(mat).texture;
-
4293 if( !texture.empty() && std::filesystem::exists(texture) ) {
-
4294 auto file = std::filesystem::path(texture).filename();
-
4295 std::filesystem::copy_file( texture, texture_dir + file.string(), std::filesystem::copy_options::overwrite_existing );
-
4296 materials.at(mat).texture = file.string();
-
4297 }
-
4298 }
-
4299
-
4300 std::ofstream objfstream;
-
4301 objfstream.open(objfilename);
-
4302 std::ofstream mtlfstream;
-
4303 mtlfstream.open(mtlfilename);
-
4304
-
4305 objfstream << "# Helios auto-generated OBJ File" << std::endl;
-
4306 objfstream << "# baileylab.ucdavis.edu/software/helios" << std::endl;
-
4307 objfstream << "mtllib " << mtlfilename << std::endl;
-
4308
-
4309 for( auto &vert : verts) {
-
4310 objfstream << "v " << vert.x << " " << vert.y << " " << vert.z << std::endl;
-
4311 }
-
4312 for( auto &v : uv){
-
4313 objfstream << "vt " << v.x << " " << v.y << std::endl;
-
4314 }
-
4315
-
4316 for( int mat=0; mat<materials.size(); mat++ ) {
-
4317
-
4318 assert(materials.at(mat).materialID==mat);
-
4319
-
4320 objfstream << "usemtl material" << mat << std::endl;
-
4321
-
4322 for (int f = 0; f < faces.at(mat).size(); f++) {
+
4237 if (type == PRIMITIVE_TYPE_TRIANGLE) {
+
4238
+
4239 faces[material_ID].push_back(make_int3( (int)vertex_count, (int)vertex_count + 1, (int)vertex_count + 2));
+
4240 for (int i = 0; i < 3; i++) {
+
4241 verts.push_back(vertices.at(i));
+
4242 vertex_count++;
+
4243 }
+
4244
+
4245 std::vector < vec2 > uv_v = getTrianglePointer_private(p)->getTextureUV();
+
4246 if (getTrianglePointer_private(p)->hasTexture() ) {
+
4247 uv_inds[material_ID].push_back(make_int3( (int)uv_count, (int)uv_count + 1, (int)uv_count + 2));
+
4248 for (int i = 0; i < 3; i++) {
+
4249 uv.push_back( uv_v.at(i) );
+
4250 uv_count++;
+
4251 }
+
4252 }
+
4253 else {
+
4254 uv_inds[material_ID].push_back(make_int3(-1, -1, -1));
+
4255 }
+
4256
+
4257 } else if (type == PRIMITIVE_TYPE_PATCH) {
+
4258
+
4259 faces[material_ID].push_back(make_int3( (int)vertex_count, (int)vertex_count + 1, (int)vertex_count + 2));
+
4260 faces[material_ID].push_back(make_int3( (int)vertex_count, (int)vertex_count + 2, (int)vertex_count + 3));
+
4261 for (int i = 0; i < 4; i++) {
+
4262 verts.push_back(vertices.at(i));
+
4263 vertex_count++;
+
4264 }
+
4265 std::vector < vec2 > uv_v;
+
4266 uv_v = getPatchPointer_private(p)->getTextureUV();
+
4267
+
4268 if (getPatchPointer_private(p)->hasTexture() ) {
+
4269 uv_inds[material_ID].push_back(make_int3( (int)uv_count, (int)uv_count + 1, (int)uv_count + 2));
+
4270 uv_inds[material_ID].push_back(make_int3( (int)uv_count, (int)uv_count + 2, (int)uv_count + 3));
+
4271 if (uv_v.empty()) { //default (u,v)
+
4272 uv.push_back( make_vec2(0, 1) );
+
4273 uv.push_back( make_vec2(1, 1) );
+
4274 uv.push_back( make_vec2(1, 0) );
+
4275 uv.push_back( make_vec2(0, 0) );
+
4276 uv_count += 4;
+
4277 } else { //custom (u,v)
+
4278 for (int i = 0; i < 4; i++) {
+
4279 uv.push_back( uv_v.at(i) );
+
4280 uv_count++;
+
4281 }
+
4282 }
+
4283 } else {
+
4284 uv_inds[material_ID].push_back(make_int3(-1, -1, -1));
+
4285 uv_inds[material_ID].push_back(make_int3(-1, -1, -1));
+
4286 }
+
4287
+
4288 }
+
4289 }
+
4290
+
4291 // assert(verts.size() == faces.size());
+
4292 assert(uv_inds.size() == faces.size());
+
4293 for( int i=0; i<faces.size(); i++ ){
+
4294 assert( uv_inds.at(i).size() == faces.at(i).size() );
+
4295 }
+
4296
+
4297 //copy material textures to new directory and edit old file paths
+
4298 std::string texture_dir = std::string(file_path);
+
4299 for (int mat = 0; mat < materials.size(); mat++) {
+
4300 std::string texture = materials.at(mat).texture;
+
4301 if( !texture.empty() && std::filesystem::exists(texture) ) {
+
4302 auto file = std::filesystem::path(texture).filename();
+
4303 std::filesystem::copy_file( texture, texture_dir + file.string(), std::filesystem::copy_options::overwrite_existing );
+
4304 materials.at(mat).texture = file.string();
+
4305 }
+
4306 }
+
4307
+
4308 std::ofstream objfstream;
+
4309 objfstream.open(objfilename);
+
4310 std::ofstream mtlfstream;
+
4311 mtlfstream.open(mtlfilename);
+
4312
+
4313 objfstream << "# Helios auto-generated OBJ File" << std::endl;
+
4314 objfstream << "# baileylab.ucdavis.edu/software/helios" << std::endl;
+
4315 objfstream << "mtllib " << mtlfilename << std::endl;
+
4316
+
4317 for( auto &vert : verts) {
+
4318 objfstream << "v " << vert.x << " " << vert.y << " " << vert.z << std::endl;
+
4319 }
+
4320 for( auto &v : uv){
+
4321 objfstream << "vt " << v.x << " " << v.y << std::endl;
+
4322 }
4323
-
4324 if ( uv.size()==0 ) {
-
4325 objfstream << "f " << faces.at(mat).at(f).x << " "
-
4326 << faces.at(mat).at(f).y << " " << faces.at(mat).at(f).z
-
4327 << std::endl;
-
4328 }else if (uv_inds.at(mat).at(f).x < 0) {
-
4329 objfstream << "f " << faces.at(mat).at(f).x << "/1 " << faces.at(mat).at(f).y
-
4330 << "/1 " << faces.at(mat).at(f).z << "/1" << std::endl;
-
4331 } else {
-
4332 objfstream << "f " << faces.at(mat).at(f).x << "/"
-
4333 << uv_inds.at(mat).at(f).x << " " << faces.at(mat).at(f).y
-
4334 << "/" << uv_inds.at(mat).at(f).y << " "
-
4335 << faces.at(mat).at(f).z << "/" << uv_inds.at(mat).at(f).z
-
4336 << std::endl;
-
4337 }
-
4338 }
-
4339
-
4340 if( materials.at(mat).texture.empty() ) {
-
4341 RGBcolor current_color = materials.at(mat).color;
-
4342 mtlfstream << "newmtl material" << mat << std::endl;
-
4343 mtlfstream << "Ka " << current_color.r << " " << current_color.g << " " << current_color.b << std::endl;
-
4344 mtlfstream << "Kd " << current_color.r << " " << current_color.g << " " << current_color.b << std::endl;
-
4345 mtlfstream << "Ks 0.0 0.0 0.0" << std::endl;
-
4346 mtlfstream << "illum 2 " << std::endl;
-
4347 }else {
-
4348 std::string current_texture = materials.at(mat).texture;
-
4349 mtlfstream << "newmtl material" << mat << std::endl;
-
4350 if( materials.at(mat).textureColorIsOverridden ) {
-
4351 RGBcolor current_color = materials.at(mat).color;
-
4352 mtlfstream << "Ka " << current_color.r << " " << current_color.g << " " << current_color.b << std::endl;
-
4353 mtlfstream << "Kd " << current_color.r << " " << current_color.g << " " << current_color.b << std::endl;
-
4354 }else{
-
4355 mtlfstream << "map_Kd " << current_texture << std::endl;
-
4356 }
-
4357 if( materials.at(mat).textureHasTransparency ){
-
4358 mtlfstream << "map_d " << current_texture << std::endl;
-
4359 }
-
4360 mtlfstream << "Ks 0.0 0.0 0.0" << std::endl;
-
4361 mtlfstream << "illum 2 " << std::endl;
-
4362 }
-
4363
-
4364 }
-
4365
-
4366 objfstream.close();
-
4367 mtlfstream.close();
-
4368
-
4369 if( !primitive_dat_fields.empty() ){
-
4370
-
4371 bool dataexistswarning = false;
-
4372 bool datatypewarning = false;
+
4324 for( int mat=0; mat<materials.size(); mat++ ) {
+
4325
+
4326 assert(materials.at(mat).materialID==mat);
+
4327
+
4328 objfstream << "usemtl material" << mat << std::endl;
+
4329
+
4330 for (int f = 0; f < faces.at(mat).size(); f++) {
+
4331
+
4332 if ( uv.size()==0 ) {
+
4333 objfstream << "f " << faces.at(mat).at(f).x << " "
+
4334 << faces.at(mat).at(f).y << " " << faces.at(mat).at(f).z
+
4335 << std::endl;
+
4336 }else if (uv_inds.at(mat).at(f).x < 0) {
+
4337 objfstream << "f " << faces.at(mat).at(f).x << "/1 " << faces.at(mat).at(f).y
+
4338 << "/1 " << faces.at(mat).at(f).z << "/1" << std::endl;
+
4339 } else {
+
4340 objfstream << "f " << faces.at(mat).at(f).x << "/"
+
4341 << uv_inds.at(mat).at(f).x << " " << faces.at(mat).at(f).y
+
4342 << "/" << uv_inds.at(mat).at(f).y << " "
+
4343 << faces.at(mat).at(f).z << "/" << uv_inds.at(mat).at(f).z
+
4344 << std::endl;
+
4345 }
+
4346 }
+
4347
+
4348 if( materials.at(mat).texture.empty() ) {
+
4349 RGBcolor current_color = materials.at(mat).color;
+
4350 mtlfstream << "newmtl material" << mat << std::endl;
+
4351 mtlfstream << "Ka " << current_color.r << " " << current_color.g << " " << current_color.b << std::endl;
+
4352 mtlfstream << "Kd " << current_color.r << " " << current_color.g << " " << current_color.b << std::endl;
+
4353 mtlfstream << "Ks 0.0 0.0 0.0" << std::endl;
+
4354 mtlfstream << "illum 2 " << std::endl;
+
4355 }else {
+
4356 std::string current_texture = materials.at(mat).texture;
+
4357 mtlfstream << "newmtl material" << mat << std::endl;
+
4358 if( materials.at(mat).textureColorIsOverridden ) {
+
4359 RGBcolor current_color = materials.at(mat).color;
+
4360 mtlfstream << "Ka " << current_color.r << " " << current_color.g << " " << current_color.b << std::endl;
+
4361 mtlfstream << "Kd " << current_color.r << " " << current_color.g << " " << current_color.b << std::endl;
+
4362 }else{
+
4363 mtlfstream << "map_Kd " << current_texture << std::endl;
+
4364 }
+
4365 if( materials.at(mat).textureHasTransparency ){
+
4366 mtlfstream << "map_d " << current_texture << std::endl;
+
4367 }
+
4368 mtlfstream << "Ks 0.0 0.0 0.0" << std::endl;
+
4369 mtlfstream << "illum 2 " << std::endl;
+
4370 }
+
4371
+
4372 }
4373
-
4374
-
4375 for( std::string label : primitive_dat_fields ){
+
4374 objfstream.close();
+
4375 mtlfstream.close();
4376
-
4377 std::string datfilename = file_path + file_stem + "_" + std::string(label) + ".dat";
-
4378 std::ofstream datout(datfilename);
-
4379
-
4380 for( int mat=0; mat<materials.size(); mat++ ) {
-
4381 for (uint UUID : UUIDs_write.at(mat)) {
+
4377 if( !primitive_dat_fields.empty() ){
+
4378
+
4379 bool dataexistswarning = false;
+
4380 bool datatypewarning = false;
+
4381
4382
-
4383 if (!doesPrimitiveExist(UUID)) {
-
4384 uuidexistswarning = true;
-
4385 continue;
-
4386 }
+
4383 for( std::string label : primitive_dat_fields ){
+
4384
+
4385 std::string datfilename = file_path + file_stem + "_" + std::string(label) + ".dat";
+
4386 std::ofstream datout(datfilename);
4387
-
4388 // a patch is converted to 2 triangles, so need to write 2 data values for patches
-
4389 int Nprims = 1;
- -
4391 Nprims = 2;
-
4392 }
-
4393
-
4394 if (!doesPrimitiveDataExist(UUID, label.c_str())) {
-
4395 dataexistswarning = true;
-
4396 for (int i = 0; i < Nprims; i++) {
-
4397 datout << 0 << std::endl;
-
4398 }
-
4399 continue;
+
4388 for( int mat=0; mat<materials.size(); mat++ ) {
+
4389 for (uint UUID : UUIDs_write.at(mat)) {
+
4390
+
4391 if (!doesPrimitiveExist(UUID)) {
+
4392 uuidexistswarning = true;
+
4393 continue;
+
4394 }
+
4395
+
4396 // a patch is converted to 2 triangles, so need to write 2 data values for patches
+
4397 int Nprims = 1;
+ +
4399 Nprims = 2;
4400 }
4401
-
4402 HeliosDataType type = getPrimitiveDataType(UUID, label.c_str());
-
4403 if (type == HELIOS_TYPE_INT) {
-
4404 int data;
-
4405 getPrimitiveData(UUID, label.c_str(), data);
-
4406 for (int i = 0; i < Nprims; i++) {
-
4407 datout << data << std::endl;
-
4408 }
-
4409 } else if (type == HELIOS_TYPE_UINT) {
-
4410 uint data;
-
4411 getPrimitiveData(UUID, label.c_str(), data);
-
4412 for (int i = 0; i < Nprims; i++) {
-
4413 datout << data << std::endl;
-
4414 }
-
4415 } else if (type == HELIOS_TYPE_FLOAT) {
-
4416 float data;
-
4417 getPrimitiveData(UUID, label.c_str(), data);
-
4418 for (int i = 0; i < Nprims; i++) {
-
4419 datout << data << std::endl;
-
4420 }
-
4421 } else if (type == HELIOS_TYPE_DOUBLE) {
-
4422 double data;
-
4423 getPrimitiveData(UUID, label.c_str(), data);
-
4424 for (int i = 0; i < Nprims; i++) {
-
4425 datout << data << std::endl;
-
4426 }
-
4427 } else if (type == HELIOS_TYPE_STRING) {
-
4428 std::string data;
-
4429 getPrimitiveData(UUID, label.c_str(), data);
-
4430 for (int i = 0; i < Nprims; i++) {
-
4431 datout << data << std::endl;
-
4432 }
-
4433 } else {
-
4434 datatypewarning = true;
-
4435 for (int i = 0; i < Nprims; i++) {
-
4436 datout << 0 << std::endl;
-
4437 }
-
4438 }
-
4439 }
-
4440 }
-
4441
-
4442 datout.close();
-
4443
-
4444 }
-
4445
-
4446 if( uuidexistswarning ){
-
4447 std::cerr << "WARNING (Context::writeOBJ): Vector of UUIDs passed to writePrimitiveData() function contained UUIDs that do not exist, which were skipped." << std::endl;
-
4448 }
-
4449 if( dataexistswarning ){
-
4450 std::cerr << "WARNING (Context::writeOBJ): Primitive data requested did not exist for one or more primitives. A default value of 0 was written in these cases." << std::endl;
-
4451 }
-
4452 if( datatypewarning ){
-
4453 std::cerr << "WARNING (Context::writeOBJ): Only scalar primitive data types (uint, int, float, and double) are supported for this function. A column of 0's was written in these cases." << std::endl;
-
4454 }
-
4455 if( voxelwarning ){
-
4456 std::cerr << "WARNING (Context::writeOBJ): Writing voxels to OBJ file is not supported. Some voxels were ignored. Use boxes or box objects to represent rectangular prism geometry." << std::endl;
-
4457 }
-
4458
-
4459 }
-
4460
-
4461
-
4462 std::cout << "done." << std::endl;
-
4463}
-
-
4464
-
-
4465void Context::writePrimitiveData( std::string filename, const std::vector<std::string> &column_format, bool print_header ) const{
-
4466 writePrimitiveData(filename,column_format,getAllUUIDs(),print_header);
-
4467}
-
+
4402 if (!doesPrimitiveDataExist(UUID, label.c_str())) {
+
4403 dataexistswarning = true;
+
4404 for (int i = 0; i < Nprims; i++) {
+
4405 datout << 0 << std::endl;
+
4406 }
+
4407 continue;
+
4408 }
+
4409
+
4410 HeliosDataType type = getPrimitiveDataType(UUID, label.c_str());
+
4411 if (type == HELIOS_TYPE_INT) {
+
4412 int data;
+
4413 getPrimitiveData(UUID, label.c_str(), data);
+
4414 for (int i = 0; i < Nprims; i++) {
+
4415 datout << data << std::endl;
+
4416 }
+
4417 } else if (type == HELIOS_TYPE_UINT) {
+
4418 uint data;
+
4419 getPrimitiveData(UUID, label.c_str(), data);
+
4420 for (int i = 0; i < Nprims; i++) {
+
4421 datout << data << std::endl;
+
4422 }
+
4423 } else if (type == HELIOS_TYPE_FLOAT) {
+
4424 float data;
+
4425 getPrimitiveData(UUID, label.c_str(), data);
+
4426 for (int i = 0; i < Nprims; i++) {
+
4427 datout << data << std::endl;
+
4428 }
+
4429 } else if (type == HELIOS_TYPE_DOUBLE) {
+
4430 double data;
+
4431 getPrimitiveData(UUID, label.c_str(), data);
+
4432 for (int i = 0; i < Nprims; i++) {
+
4433 datout << data << std::endl;
+
4434 }
+
4435 } else if (type == HELIOS_TYPE_STRING) {
+
4436 std::string data;
+
4437 getPrimitiveData(UUID, label.c_str(), data);
+
4438 for (int i = 0; i < Nprims; i++) {
+
4439 datout << data << std::endl;
+
4440 }
+
4441 } else {
+
4442 datatypewarning = true;
+
4443 for (int i = 0; i < Nprims; i++) {
+
4444 datout << 0 << std::endl;
+
4445 }
+
4446 }
+
4447 }
+
4448 }
+
4449
+
4450 datout.close();
+
4451
+
4452 }
+
4453
+
4454 if( uuidexistswarning ){
+
4455 std::cerr << "WARNING (Context::writeOBJ): Vector of UUIDs passed to writePrimitiveData() function contained UUIDs that do not exist, which were skipped." << std::endl;
+
4456 }
+
4457 if( dataexistswarning ){
+
4458 std::cerr << "WARNING (Context::writeOBJ): Primitive data requested did not exist for one or more primitives. A default value of 0 was written in these cases." << std::endl;
+
4459 }
+
4460 if( datatypewarning ){
+
4461 std::cerr << "WARNING (Context::writeOBJ): Only scalar primitive data types (uint, int, float, and double) are supported for this function. A column of 0's was written in these cases." << std::endl;
+
4462 }
+
4463 if( voxelwarning ){
+
4464 std::cerr << "WARNING (Context::writeOBJ): Writing voxels to OBJ file is not supported. Some voxels were ignored. Use boxes or box objects to represent rectangular prism geometry." << std::endl;
+
4465 }
+
4466
+
4467 }
4468
-
-
4469void Context::writePrimitiveData( std::string filename, const std::vector<std::string> &column_format, const std::vector<uint> &UUIDs, bool print_header ) const{
-
4470
-
4471 std::ofstream file(filename);
+
4469
+
4470 std::cout << "done." << std::endl;
+
4471}
+
4472
-
4473 if( print_header ){
-
4474 for( const auto &label : column_format ) {
-
4475 file << label << " ";
-
4476 }
-
4477 file.seekp(-1, std::ios_base::end);
-
4478 file << "\n";
-
4479 }
+
+
4473void Context::writePrimitiveData( std::string filename, const std::vector<std::string> &column_format, bool print_header ) const{
+
4474 writePrimitiveData(filename,column_format,getAllUUIDs(),print_header);
+
4475}
+
+
4476
+
+
4477void Context::writePrimitiveData( std::string filename, const std::vector<std::string> &column_format, const std::vector<uint> &UUIDs, bool print_header ) const{
+
4478
+
4479 std::ofstream file(filename);
4480
-
4481 bool uuidexistswarning = false;
-
4482 bool dataexistswarning = false;
-
4483 bool datatypewarning = false;
-
4484
-
4485 for( uint UUID : UUIDs ){
-
4486 if( !doesPrimitiveExist(UUID) ){
-
4487 uuidexistswarning=true;
-
4488 continue;
-
4489 }
-
4490 for( const auto &label : column_format ) {
-
4491 if( label == "UUID" ){
-
4492 file << UUID << " ";
-
4493 continue;
-
4494 }
-
4495 if( !doesPrimitiveDataExist(UUID,label.c_str()) ){
-
4496 dataexistswarning=true;
-
4497 file << 0 << " ";
-
4498 continue;
-
4499 }
-
4500 HeliosDataType type = getPrimitiveDataType( UUID, label.c_str() );
-
4501 if( type == HELIOS_TYPE_INT ){
-
4502 int data;
-
4503 getPrimitiveData( UUID, label.c_str(), data );
-
4504 file << data << " ";
-
4505 }else if( type == HELIOS_TYPE_UINT ) {
-
4506 uint data;
-
4507 getPrimitiveData(UUID, label.c_str(), data);
-
4508 file << data << " ";
-
4509 }else if( type == HELIOS_TYPE_FLOAT ) {
-
4510 float data;
-
4511 getPrimitiveData(UUID, label.c_str(), data);
+
4481 if( print_header ){
+
4482 for( const auto &label : column_format ) {
+
4483 file << label << " ";
+
4484 }
+
4485 file.seekp(-1, std::ios_base::end);
+
4486 file << "\n";
+
4487 }
+
4488
+
4489 bool uuidexistswarning = false;
+
4490 bool dataexistswarning = false;
+
4491 bool datatypewarning = false;
+
4492
+
4493 for( uint UUID : UUIDs ){
+
4494 if( !doesPrimitiveExist(UUID) ){
+
4495 uuidexistswarning=true;
+
4496 continue;
+
4497 }
+
4498 for( const auto &label : column_format ) {
+
4499 if( label == "UUID" ){
+
4500 file << UUID << " ";
+
4501 continue;
+
4502 }
+
4503 if( !doesPrimitiveDataExist(UUID,label.c_str()) ){
+
4504 dataexistswarning=true;
+
4505 file << 0 << " ";
+
4506 continue;
+
4507 }
+
4508 HeliosDataType type = getPrimitiveDataType( UUID, label.c_str() );
+
4509 if( type == HELIOS_TYPE_INT ){
+
4510 int data;
+
4511 getPrimitiveData( UUID, label.c_str(), data );
4512 file << data << " ";
-
4513 }else if( type == HELIOS_TYPE_DOUBLE ) {
-
4514 double data;
+
4513 }else if( type == HELIOS_TYPE_UINT ) {
+
4514 uint data;
4515 getPrimitiveData(UUID, label.c_str(), data);
4516 file << data << " ";
-
4517 }else if( type == HELIOS_TYPE_STRING ) {
-
4518 std::string data;
+
4517 }else if( type == HELIOS_TYPE_FLOAT ) {
+
4518 float data;
4519 getPrimitiveData(UUID, label.c_str(), data);
4520 file << data << " ";
-
4521 }else{
-
4522 datatypewarning=true;
-
4523 file << 0 << " ";
-
4524 }
-
4525 }
-
4526 file.seekp(-1, std::ios_base::end);
-
4527 file << "\n";
-
4528 }
-
4529
-
4530 if( uuidexistswarning ){
-
4531 std::cerr << "WARNING (Context::writePrimitiveData): Vector of UUIDs passed to writePrimitiveData() function contained UUIDs that do not exist, which were skipped." << std::endl;
-
4532 }
-
4533 if( dataexistswarning ){
-
4534 std::cerr << "WARNING (Context::writePrimitiveData): Primitive data requested did not exist for one or more primitives. A default value of 0 was written in these cases." << std::endl;
-
4535 }
-
4536 if( datatypewarning ){
-
4537 std::cerr << "WARNING (Context::writePrimitiveData): Only scalar primitive data types (uint, int, float, and double) are supported for this function. A column of 0's was written in these cases." << std::endl;
-
4538 }
-
4539
-
4540 file.close();
-
4541
-
4542}
-
-
4543
-
-
4544void Context::loadTabularTimeseriesData( const std::string &data_file, const std::vector<std::string> &col_labels, const std::string &a_delimeter, const std::string &a_date_string_format, uint headerlines ){
-
4545
-
4546 std::ifstream datafile(data_file); //open the file
+
4521 }else if( type == HELIOS_TYPE_DOUBLE ) {
+
4522 double data;
+
4523 getPrimitiveData(UUID, label.c_str(), data);
+
4524 file << data << " ";
+
4525 }else if( type == HELIOS_TYPE_STRING ) {
+
4526 std::string data;
+
4527 getPrimitiveData(UUID, label.c_str(), data);
+
4528 file << data << " ";
+
4529 }else{
+
4530 datatypewarning=true;
+
4531 file << 0 << " ";
+
4532 }
+
4533 }
+
4534 file.seekp(-1, std::ios_base::end);
+
4535 file << "\n";
+
4536 }
+
4537
+
4538 if( uuidexistswarning ){
+
4539 std::cerr << "WARNING (Context::writePrimitiveData): Vector of UUIDs passed to writePrimitiveData() function contained UUIDs that do not exist, which were skipped." << std::endl;
+
4540 }
+
4541 if( dataexistswarning ){
+
4542 std::cerr << "WARNING (Context::writePrimitiveData): Primitive data requested did not exist for one or more primitives. A default value of 0 was written in these cases." << std::endl;
+
4543 }
+
4544 if( datatypewarning ){
+
4545 std::cerr << "WARNING (Context::writePrimitiveData): Only scalar primitive data types (uint, int, float, and double) are supported for this function. A column of 0's was written in these cases." << std::endl;
+
4546 }
4547
-
4548 if(!datafile.is_open()){ //check that file exists
-
4549 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Weather data file '" + data_file + "' does not exist.");
-
4550 }
+
4548 file.close();
+
4549
+
4550}
+
4551
-
4552 int yearcol=-1;
-
4553 int DOYcol=-1;
-
4554 int datestrcol=-1;
-
4555 int hourcol=-1;
-
4556 int minutecol=-1;
-
4557 int secondcol=-1;
-
4558 int timestrcol=-1;
-
4559 std::map<std::string,int> datacols;
-
4560
-
4561 size_t Ncolumns = 0;
-
4562
-
4563 size_t row = headerlines;
-
4564
-
4565 std::vector<std::string> column_labels = col_labels;
-
4566 std::string delimiter = a_delimeter;
-
4567 std::string date_string_format = a_date_string_format;
+
+
4552void Context::loadTabularTimeseriesData( const std::string &data_file, const std::vector<std::string> &col_labels, const std::string &a_delimeter, const std::string &a_date_string_format, uint headerlines ){
+
4553
+
4554 std::ifstream datafile(data_file); //open the file
+
4555
+
4556 if(!datafile.is_open()){ //check that file exists
+
4557 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Weather data file '" + data_file + "' does not exist.");
+
4558 }
+
4559
+
4560 int yearcol=-1;
+
4561 int DOYcol=-1;
+
4562 int datestrcol=-1;
+
4563 int hourcol=-1;
+
4564 int minutecol=-1;
+
4565 int secondcol=-1;
+
4566 int timestrcol=-1;
+
4567 std::map<std::string,int> datacols;
4568
-
4569 // pre-defined labels for CIMIS weather data files
-
4570 if( col_labels.size()==1 && ( col_labels.front()=="CIMIS" || col_labels.front()=="cimis" ) ) {
-
4571 column_labels = {"", "", "", "date", "hour", "DOY", "ETo", "", "precipitation", "",
-
4572 "net_radiation", "", "vapor_pressure", "", "air_temperature", "",
-
4573 "air_humidity", "", "dew_point", "", "wind_speed", "", "wind_direction",
-
4574 "", "soil_temperature", ""};
-
4575 headerlines = 1;
-
4576 delimiter = ",";
-
4577 date_string_format = "MMDDYYYY";
-
4578
-
4579 }
-
4580
-
4581 //If user specified column labels as an argument, parse them
-
4582 if( !column_labels.empty() ) {
-
4583
-
4584 int col = 0;
-
4585 for (auto &label: column_labels) {
+
4569 size_t Ncolumns = 0;
+
4570
+
4571 size_t row = headerlines;
+
4572
+
4573 std::vector<std::string> column_labels = col_labels;
+
4574 std::string delimiter = a_delimeter;
+
4575 std::string date_string_format = a_date_string_format;
+
4576
+
4577 // pre-defined labels for CIMIS weather data files
+
4578 if( col_labels.size()==1 && ( col_labels.front()=="CIMIS" || col_labels.front()=="cimis" ) ) {
+
4579 column_labels = {"", "", "", "date", "hour", "DOY", "ETo", "", "precipitation", "",
+
4580 "net_radiation", "", "vapor_pressure", "", "air_temperature", "",
+
4581 "air_humidity", "", "dew_point", "", "wind_speed", "", "wind_direction",
+
4582 "", "soil_temperature", ""};
+
4583 headerlines = 1;
+
4584 delimiter = ",";
+
4585 date_string_format = "MMDDYYYY";
4586
-
4587 if (label == "year" || label == "Year") {
-
4588 yearcol = col;
-
4589 } else if (label == "DOY" || label == "Jul" ) {
-
4590 DOYcol = col;
-
4591 } else if (label == "date" || label == "Date") {
-
4592 datestrcol = col;
-
4593 } else if (label == "hour" || label == "Hour") {
-
4594 hourcol = col;
-
4595 } else if (label == "minute" || label == "Minute") {
-
4596 minutecol = col;
-
4597 } else if (label == "second" || label == "Second") {
-
4598 secondcol = col;
-
4599 }else if ( !label.empty() ){
-
4600 if( datacols.find(label)==datacols.end() ) {
-
4601 datacols[label] = col;
-
4602 }else{
-
4603 datacols[label+"_dup"] = col;
-
4604 }
-
4605 }
-
4606
-
4607 col++;
-
4608 }
-
4609
-
4610 Ncolumns = column_labels.size();
-
4611
-
4612 // If column labels were not provided, read the first line of the text file and parse it for labels
-
4613 }else{
+
4587 }
+
4588
+
4589 //If user specified column labels as an argument, parse them
+
4590 if( !column_labels.empty() ) {
+
4591
+
4592 int col = 0;
+
4593 for (auto &label: column_labels) {
+
4594
+
4595 if (label == "year" || label == "Year") {
+
4596 yearcol = col;
+
4597 } else if (label == "DOY" || label == "Jul" ) {
+
4598 DOYcol = col;
+
4599 } else if (label == "date" || label == "Date") {
+
4600 datestrcol = col;
+
4601 } else if (label == "hour" || label == "Hour") {
+
4602 hourcol = col;
+
4603 } else if (label == "minute" || label == "Minute") {
+
4604 minutecol = col;
+
4605 } else if (label == "second" || label == "Second") {
+
4606 secondcol = col;
+
4607 }else if ( !label.empty() ){
+
4608 if( datacols.find(label)==datacols.end() ) {
+
4609 datacols[label] = col;
+
4610 }else{
+
4611 datacols[label+"_dup"] = col;
+
4612 }
+
4613 }
4614
-
4615 if( headerlines==0 ){
-
4616 std::cout << "WARNING (Context::loadTabularTimeseriesData): ""headerlines"" argument was specified as zero, and no column label information was given. Attempting to read the first line to see if it contains label information." << std::endl;
-
4617 headerlines++;
-
4618 }
+
4615 col++;
+
4616 }
+
4617
+
4618 Ncolumns = column_labels.size();
4619
-
4620 std::string line;
-
4621 if( std::getline(datafile, line) ){
+
4620 // If column labels were not provided, read the first line of the text file and parse it for labels
+
4621 }else{
4622
-
4623 std::vector<std::string> line_parsed = separate_string_by_delimiter( line, delimiter );
-
4624
-
4625 if( line_parsed.empty() ){
-
4626 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Attempted to parse first line of file for column labels, but it did not contain the specified delimiter.");
-
4627 }
-
4628
-
4629 Ncolumns = line_parsed.size();
+
4623 if( headerlines==0 ){
+
4624 std::cout << "WARNING (Context::loadTabularTimeseriesData): ""headerlines"" argument was specified as zero, and no column label information was given. Attempting to read the first line to see if it contains label information." << std::endl;
+
4625 headerlines++;
+
4626 }
+
4627
+
4628 std::string line;
+
4629 if( std::getline(datafile, line) ){
4630
-
4631 for( int col=0; col<Ncolumns; col++ ){
+
4631 std::vector<std::string> line_parsed = separate_string_by_delimiter( line, delimiter );
4632
-
4633 std::string label = line_parsed.at(col);
-
4634
-
4635 if (label == "year" || label == "Year") {
-
4636 yearcol = col;
-
4637 } else if (label == "DOY" || label == "Jul" ) {
-
4638 DOYcol = col;
-
4639 } else if (label == "date" || label == "Date") {
-
4640 datestrcol = col;
-
4641 } else if (label == "hour" || label == "Hour") {
-
4642 hourcol = col;
-
4643 } else if (label == "minute" || label == "Minute") {
-
4644 minutecol = col;
-
4645 } else if (label == "second" || label == "Second") {
-
4646 secondcol = col;
-
4647 }else if ( !label.empty() ) {
-
4648 if( datacols.find(label)==datacols.end() ) {
-
4649 datacols[label] = col;
-
4650 }else{
-
4651 datacols[label+"_dup"] = col;
-
4652 }
-
4653 }
-
4654
-
4655 }
-
4656
-
4657 headerlines --;
-
4658
-
4659 }else{
-
4660 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Attempted to parse first line of file for column labels, but read failed.");
-
4661 }
+
4633 if( line_parsed.empty() ){
+
4634 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Attempted to parse first line of file for column labels, but it did not contain the specified delimiter.");
+
4635 }
+
4636
+
4637 Ncolumns = line_parsed.size();
+
4638
+
4639 for( int col=0; col<Ncolumns; col++ ){
+
4640
+
4641 std::string label = line_parsed.at(col);
+
4642
+
4643 if (label == "year" || label == "Year") {
+
4644 yearcol = col;
+
4645 } else if (label == "DOY" || label == "Jul" ) {
+
4646 DOYcol = col;
+
4647 } else if (label == "date" || label == "Date") {
+
4648 datestrcol = col;
+
4649 } else if (label == "hour" || label == "Hour") {
+
4650 hourcol = col;
+
4651 } else if (label == "minute" || label == "Minute") {
+
4652 minutecol = col;
+
4653 } else if (label == "second" || label == "Second") {
+
4654 secondcol = col;
+
4655 }else if ( !label.empty() ) {
+
4656 if( datacols.find(label)==datacols.end() ) {
+
4657 datacols[label] = col;
+
4658 }else{
+
4659 datacols[label+"_dup"] = col;
+
4660 }
+
4661 }
4662
-
4663 if( yearcol==-1 && DOYcol==-1 && datestrcol==-1 ){
-
4664 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Attempted to parse first line of file for column labels, but could not find valid label information.");
-
4665 }
+
4663 }
+
4664
+
4665 headerlines --;
4666
-
4667 }
-
4668
-
4669 if( datestrcol<0 && (yearcol<0 || DOYcol<0) ){
-
4670 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): The date must be specified by either a column labeled ""date"", or by two columns labeled ""year"" and ""DOY"".");
-
4671 }else if( hourcol<0 ){
-
4672 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): At a minimum, the time must be specified by a column labeled ""hour""." );
-
4673 }else if( datacols.empty() ){
-
4674 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): No columns were found containing data variables (e.g., temperature, humidity, wind speed).");
+
4667 }else{
+
4668 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Attempted to parse first line of file for column labels, but read failed.");
+
4669 }
+
4670
+
4671 if( yearcol==-1 && DOYcol==-1 && datestrcol==-1 ){
+
4672 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Attempted to parse first line of file for column labels, but could not find valid label information.");
+
4673 }
+
4674
4675 }
4676
-
4677 std::string line;
-
4678
-
4679 //skip header lines
-
4680 //note: if we read labels from the first header line above, we don't need to skip another line
-
4681 for (int i = 0; i < headerlines; i++) {
-
4682 std::getline(datafile, line);
+
4677 if( datestrcol<0 && (yearcol<0 || DOYcol<0) ){
+
4678 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): The date must be specified by either a column labeled ""date"", or by two columns labeled ""year"" and ""DOY"".");
+
4679 }else if( hourcol<0 ){
+
4680 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): At a minimum, the time must be specified by a column labeled ""hour""." );
+
4681 }else if( datacols.empty() ){
+
4682 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): No columns were found containing data variables (e.g., temperature, humidity, wind speed).");
4683 }
4684
-
4685 while ( std::getline(datafile, line) ) { //loop through file to read data
-
4686 row++;
-
4687
-
4688 if( trim_whitespace(line).empty() && row>1 ){
-
4689 break;
-
4690 }
-
4691
-
4692 //separate the line by delimiter
-
4693 std::vector<std::string> line_separated = separate_string_by_delimiter( line, delimiter );
-
4694
-
4695 if( line_separated.size()!=Ncolumns ){
-
4696 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Line " + std::to_string(row) + " had " + std::to_string(line_separated.size()) + " columns, but was expecting " + std::to_string(Ncolumns) );
-
4697 }
-
4698
-
4699 //compile date
-
4700 Date date;
-
4701 if( yearcol>=0 && DOYcol>=0 ){
-
4702 int DOY;
-
4703 parse_int(line_separated.at(DOYcol), DOY);
-
4704 if( DOY<1 || DOY>366 ){
-
4705 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Invalid date specified on line " + std::to_string(row) + ".");
-
4706 }
-
4707 int year;
-
4708 parse_int(line_separated.at( yearcol ), year);
-
4709 if( year<1000 ){
-
4710 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Invalid year specified on line " + std::to_string(row) + ".");
-
4711 }
-
4712 date = make_Date( DOY, year );
-
4713 }else if( datestrcol>=0 ){
-
4714 //parse date string. expecting format YYYY-MM-DD with delimiter '-' or '/'
-
4715 std::string datestr = line_separated.at(datestrcol);
-
4716
-
4717 //try parsing date string based on '-' delimiter
-
4718 std::vector<std::string> thisdatestr = separate_string_by_delimiter( datestr, "-" );
-
4719
-
4720 if( thisdatestr.size()!=3 ){
-
4721 //try parsing date string based on '/' delimiter
-
4722 thisdatestr = separate_string_by_delimiter( datestr, "/" );
-
4723 }
+
4685 std::string line;
+
4686
+
4687 //skip header lines
+
4688 //note: if we read labels from the first header line above, we don't need to skip another line
+
4689 for (int i = 0; i < headerlines; i++) {
+
4690 std::getline(datafile, line);
+
4691 }
+
4692
+
4693 while ( std::getline(datafile, line) ) { //loop through file to read data
+
4694 row++;
+
4695
+
4696 if( trim_whitespace(line).empty() && row>1 ){
+
4697 break;
+
4698 }
+
4699
+
4700 //separate the line by delimiter
+
4701 std::vector<std::string> line_separated = separate_string_by_delimiter( line, delimiter );
+
4702
+
4703 if( line_separated.size()!=Ncolumns ){
+
4704 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Line " + std::to_string(row) + " had " + std::to_string(line_separated.size()) + " columns, but was expecting " + std::to_string(Ncolumns) );
+
4705 }
+
4706
+
4707 //compile date
+
4708 Date date;
+
4709 if( yearcol>=0 && DOYcol>=0 ){
+
4710 int DOY;
+
4711 parse_int(line_separated.at(DOYcol), DOY);
+
4712 if( DOY<1 || DOY>366 ){
+
4713 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Invalid date specified on line " + std::to_string(row) + ".");
+
4714 }
+
4715 int year;
+
4716 parse_int(line_separated.at( yearcol ), year);
+
4717 if( year<1000 ){
+
4718 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Invalid year specified on line " + std::to_string(row) + ".");
+
4719 }
+
4720 date = make_Date( DOY, year );
+
4721 }else if( datestrcol>=0 ){
+
4722 //parse date string. expecting format YYYY-MM-DD with delimiter '-' or '/'
+
4723 std::string datestr = line_separated.at(datestrcol);
4724
-
4725 if( thisdatestr.size()!=3 ){
-
4726 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Could not parse date string on line " + std::to_string(row) + ". It should be in the format YYYY-MM-DD, delimited by either ""-"" or ""/""." );
-
4727 }
-
4728
-
4729 //convert parsed date strings into a vector of integers
-
4730 std::vector<int> thisdate(3);
-
4731 for( int i=0; i<3; i++ ){
-
4732 if( !parse_int( thisdatestr.at(i), thisdate.at(i) ) ){
-
4733 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Could not parse date string on line " + std::to_string(row) + ". It should be in the format YYYY-MM-DD, delimited by either ""-"" or ""/""." );
-
4734 }
+
4725 //try parsing date string based on '-' delimiter
+
4726 std::vector<std::string> thisdatestr = separate_string_by_delimiter( datestr, "-" );
+
4727
+
4728 if( thisdatestr.size()!=3 ){
+
4729 //try parsing date string based on '/' delimiter
+
4730 thisdatestr = separate_string_by_delimiter( datestr, "/" );
+
4731 }
+
4732
+
4733 if( thisdatestr.size()!=3 ){
+
4734 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Could not parse date string on line " + std::to_string(row) + ". It should be in the format YYYY-MM-DD, delimited by either ""-"" or ""/""." );
4735 }
4736
-
4737 //figure out ordering of values
-
4738 int year;
-
4739 int month;
-
4740 int day;
-
4741 if( date_string_format=="YYYYMMDD" ){
-
4742 year = thisdate.at(0);
-
4743 month = thisdate.at(1);
-
4744 day = thisdate.at(2);
-
4745 }else if( date_string_format=="YYYYDDMM" ){
-
4746 year = thisdate.at(0);
-
4747 month = thisdate.at(2);
-
4748 day = thisdate.at(1);
-
4749 }else if( date_string_format=="DDMMYYYY" ){
-
4750 year = thisdate.at(2);
+
4737 //convert parsed date strings into a vector of integers
+
4738 std::vector<int> thisdate(3);
+
4739 for( int i=0; i<3; i++ ){
+
4740 if( !parse_int( thisdatestr.at(i), thisdate.at(i) ) ){
+
4741 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Could not parse date string on line " + std::to_string(row) + ". It should be in the format YYYY-MM-DD, delimited by either ""-"" or ""/""." );
+
4742 }
+
4743 }
+
4744
+
4745 //figure out ordering of values
+
4746 int year;
+
4747 int month;
+
4748 int day;
+
4749 if( date_string_format=="YYYYMMDD" ){
+
4750 year = thisdate.at(0);
4751 month = thisdate.at(1);
-
4752 day = thisdate.at(0);
-
4753 }else if( date_string_format=="MMDDYYYY" ){
-
4754 year = thisdate.at(2);
-
4755 month = thisdate.at(0);
+
4752 day = thisdate.at(2);
+
4753 }else if( date_string_format=="YYYYDDMM" ){
+
4754 year = thisdate.at(0);
+
4755 month = thisdate.at(2);
4756 day = thisdate.at(1);
-
4757 }else{
-
4758 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Invalid date string format: " + date_string_format + ". Must be one of ""YYYYMMDD"", ""YYYYDDMM"", ""DDMMYYYY"", or ""MMDDYYYY"". Check that the date string does not include a delimiter (i.e., should be MMDDYYYY not MM/DD/YYYY).");
-
4759 }
-
4760
-
4761 if( year<1000 || month<1 || month>12 || day<1 || day>31 ){
-
4762 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Could not parse date string on line " + std::to_string(row) + ". It should be in the format YYYY-MM-DD, delimited by either ""-"" or ""/""." );
-
4763 }
-
4764
-
4765 date = make_Date( day, month, year );
-
4766 }else{
-
4767 assert(1); //shouldn't be here
-
4768 }
-
4769
-
4770 //compile time
-
4771 Time time;
-
4772 int hour = 0;
-
4773 int minute = 0;
-
4774 int second = 0;
-
4775
-
4776 if( !parse_int( line_separated.at(hourcol), hour ) ){
-
4777 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Could not parse hour string on line " + std::to_string(row) + "." );
-
4778 }
-
4779 if( hour>24 && minutecol<0 && secondcol<0 ){
-
4780 int hr_min = hour;
-
4781 hour = std::floor( hr_min/100 );
-
4782 minute = hr_min - hour*100;
-
4783 }
-
4784 if( hour==24 ){
-
4785 hour = 0;
-
4786 date.incrementDay();
-
4787 }
-
4788 if( minutecol>=0 ){
-
4789 if( !parse_int( line_separated.at(minutecol), minute ) ){
-
4790 minute = 0;
-
4791 std::cout << "WARNING (Context::loadTabularTimeseriesData): Could not parse minute string on line " << row << ". Setting minute equal to 0." << std::endl;
-
4792 }
-
4793 }
-
4794 if( secondcol>=0 ){
-
4795 if( !parse_int( line_separated.at(secondcol), second ) ){
-
4796 second = 0;
-
4797 std::cout << "WARNING (Context::loadTabularTimeseriesData): Could not parse second string on line " << row << ". Setting second equal to 0." << std::endl;
-
4798 }
-
4799 }
-
4800 time = make_Time( hour, minute, second );
-
4801
-
4802 //compile data values
-
4803 for( auto &dat : datacols ){
-
4804
-
4805 std::string label = dat.first;
-
4806 int col = dat.second;
-
4807
-
4808 float dataval;
-
4809 if( !parse_float( line_separated.at(col), dataval ) ){
-
4810 std::cout << "WARNING (Context::loadTabularTimeseriesData): Failed to parse data value as ""float"" on line " << row << ", column "<<col+1 << ". Skipping this value..." << std::endl;
-
4811 continue;
-
4812 }
-
4813
-
4814 if( label=="air_humidity" && col_labels.size()==1 && ( col_labels.front()=="CIMIS" || col_labels.front()=="cimis" ) ) {
-
4815 dataval = dataval/100.f;
-
4816 }
-
4817
-
4818 addTimeseriesData( label.c_str(), dataval, date, time );
-
4819
-
4820 }
+
4757 }else if( date_string_format=="DDMMYYYY" ){
+
4758 year = thisdate.at(2);
+
4759 month = thisdate.at(1);
+
4760 day = thisdate.at(0);
+
4761 }else if( date_string_format=="MMDDYYYY" ){
+
4762 year = thisdate.at(2);
+
4763 month = thisdate.at(0);
+
4764 day = thisdate.at(1);
+
4765 }else{
+
4766 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Invalid date string format: " + date_string_format + ". Must be one of ""YYYYMMDD"", ""YYYYDDMM"", ""DDMMYYYY"", or ""MMDDYYYY"". Check that the date string does not include a delimiter (i.e., should be MMDDYYYY not MM/DD/YYYY).");
+
4767 }
+
4768
+
4769 if( year<1000 || month<1 || month>12 || day<1 || day>31 ){
+
4770 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Could not parse date string on line " + std::to_string(row) + ". It should be in the format YYYY-MM-DD, delimited by either ""-"" or ""/""." );
+
4771 }
+
4772
+
4773 date = make_Date( day, month, year );
+
4774 }else{
+
4775 assert(1); //shouldn't be here
+
4776 }
+
4777
+
4778 //compile time
+
4779 Time time;
+
4780 int hour = 0;
+
4781 int minute = 0;
+
4782 int second = 0;
+
4783
+
4784 if( !parse_int( line_separated.at(hourcol), hour ) ){
+
4785 helios_runtime_error("ERROR (Context::loadTabularTimeseriesData): Could not parse hour string on line " + std::to_string(row) + "." );
+
4786 }
+
4787 if( hour>24 && minutecol<0 && secondcol<0 ){
+
4788 int hr_min = hour;
+
4789 hour = std::floor( hr_min/100 );
+
4790 minute = hr_min - hour*100;
+
4791 }
+
4792 if( hour==24 ){
+
4793 hour = 0;
+
4794 date.incrementDay();
+
4795 }
+
4796 if( minutecol>=0 ){
+
4797 if( !parse_int( line_separated.at(minutecol), minute ) ){
+
4798 minute = 0;
+
4799 std::cout << "WARNING (Context::loadTabularTimeseriesData): Could not parse minute string on line " << row << ". Setting minute equal to 0." << std::endl;
+
4800 }
+
4801 }
+
4802 if( secondcol>=0 ){
+
4803 if( !parse_int( line_separated.at(secondcol), second ) ){
+
4804 second = 0;
+
4805 std::cout << "WARNING (Context::loadTabularTimeseriesData): Could not parse second string on line " << row << ". Setting second equal to 0." << std::endl;
+
4806 }
+
4807 }
+
4808 time = make_Time( hour, minute, second );
+
4809
+
4810 //compile data values
+
4811 for( auto &dat : datacols ){
+
4812
+
4813 std::string label = dat.first;
+
4814 int col = dat.second;
+
4815
+
4816 float dataval;
+
4817 if( !parse_float( line_separated.at(col), dataval ) ){
+
4818 std::cout << "WARNING (Context::loadTabularTimeseriesData): Failed to parse data value as ""float"" on line " << row << ", column "<<col+1 << ". Skipping this value..." << std::endl;
+
4819 continue;
+
4820 }
4821
-
4822 }
-
4823
-
4824 datafile.close();
+
4822 if( label=="air_humidity" && col_labels.size()==1 && ( col_labels.front()=="CIMIS" || col_labels.front()=="cimis" ) ) {
+
4823 dataval = dataval/100.f;
+
4824 }
4825
-
4826}
+
4826 addTimeseriesData( label.c_str(), dataval, date, time );
+
4827
+
4828 }
+
4829
+
4830 }
+
4831
+
4832 datafile.close();
+
4833
+
4834}
HeliosDataType
Data types.
Definition Context.h:41
@@ -5046,11 +5054,11 @@
std::vector< helios::vec3 > getNodeCoordinates() const
Get the Cartesian coordinates of each of the cone object nodes.
Definition Context.cpp:4092
std::vector< float > getNodeRadii() const
Get the radius at each of the cone object nodes.
Definition Context.cpp:4121
void setPrimitiveColor(uint UUID, const helios::RGBcolor &color)
Method to set the diffuse color of a Primitive.
Definition Context.cpp:7083
-
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...
+
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...
std::vector< uint > loadXML(const char *filename, bool quiet=false)
Load inputs specified in an XML file.
Disk * getDiskObjectPointer(uint ObjID) const
Get a pointer to a Disk Compound Object.
Definition Context.cpp:3984
std::vector< uint > getUniquePrimitiveParentObjectIDs(const std::vector< uint > &UUIDs) const
Method to return unique parent object IDs for a vector of primitive UUIDs.
Definition Context.cpp:6966
-
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.
+
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:3916
void getPrimitiveData(uint UUID, const char *label, int &data) const
Get data associated with a primitive element.
void deletePrimitive(uint UUID)
Delete a single primitive from the context.
Definition Context.cpp:1526
@@ -5065,9 +5073,9 @@
float getPrimitiveSolidFraction(uint UUID) const
Get fraction of primitive surface area that is non-transparent.
Definition Context.cpp:7165
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:2887
-
void writeOBJ(const std::string &filename) const
Write geometry in the Context to a Wavefront file (.obj)
+
void writeOBJ(const std::string &filename) const
Write geometry in the Context to a Wavefront file (.obj)
helios::Time getTime() const
Get the simulation time.
Definition Context.cpp:1164
-
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...
+
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...
Sphere * getSphereObjectPointer(uint ObjID) const
Get a pointer to a Sphere Compound Object.
Definition Context.cpp:3390
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:7141
HeliosDataType getGlobalDataType(const char *label) const
Get the Helios data type of global data.
@@ -5077,11 +5085,11 @@
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1753
bool doesObjectExist(uint ObjID) const
Check whether Compound Object exists in the Context.
Definition Context.cpp:2565
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
-
void writePLY(const char *filename) const
Write geometry in the Context to a Stanford polygon file (.ply)
+
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:7161
Tube * getTubeObjectPointer(uint ObjID) const
Get a pointer to a Tube Compound Object.
Definition Context.cpp:3466
-
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 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 writeXML(const char *filename, bool quiet=false) const
Write Context geometry and data to XML file for all UUIDs in the context.
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
bool doesPrimitiveExist(uint UUID) const
Check if primitive exists for a given UUID.
Definition Context.cpp:1649
@@ -5130,12 +5138,14 @@
bool parse_float(const std::string &input_string, float &converted_float)
Convert a string into a float with error checking.
Definition global.cpp:763
bool parse_uint(const std::string &input_string, uint &converted_uint)
Convert a string into an unsigned integer with error checking.
Definition global.cpp:809
std::string getFileExtension(const std::string &filepath)
Parse a file string to get the extension.
Definition global.cpp:2993
+
bool validateOutputPath(std::string &output_directory, const std::vector< std::string > &allowable_file_extensions={})
Check whether output file and/or directory is valid. Add a trailing slash if it is a directory.
Definition global.cpp:3020
+
std::string getFileName(const std::string &filepath)
Parse a file string to get the filename including extension.
Definition global.cpp:3003
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
bool parse_int(const std::string &input_string, int &converted_int)
Convert a string into an integer with error checking.
Definition global.cpp:794
vec3 nullorigin
Default null vec3 that gives the origin (0,0,0)
Definition global.cpp:58
-
std::string getFileStem(const std::string &filepath)
Parse a file string to get the filename without extension.
Definition global.cpp:3019
+
std::string getFileStem(const std::string &filepath)
Parse a file string to get the filename without extension.
Definition global.cpp:2998
void makeIdentityMatrix(float(&T)[16])
Construct an identity matrix.
Definition global.cpp:555
-
std::string getFilePath(const std::string &filepath, bool trailingslash=true)
Parse a file string to get the path (i.e., portion of the string before the file name).
Definition global.cpp:3045
+
std::string getFilePath(const std::string &filepath, bool trailingslash=true)
Parse a file string to get the path (i.e., portion of the string before the file name).
Definition global.cpp:3008
SphericalCoord nullrotation
Default null SphericalCoord that applies no rotation.
Definition global.cpp:57
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:5200
uint addTubeObject(uint radial_subdivisions, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:4690
diff --git a/doc/html/_convert_p_l_y.html b/doc/html/_convert_p_l_y.html index 83d1b55db..34b6b4d2e 100644 --- a/doc/html/_convert_p_l_y.html +++ b/doc/html/_convert_p_l_y.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_dependent_software.html b/doc/html/_dependent_software.html index c565f0532..08bee0d68 100644 --- a/doc/html/_dependent_software.html +++ b/doc/html/_dependent_software.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_dummy.html b/doc/html/_dummy.html index a3c436d20..8d0f028ae 100644 --- a/doc/html/_dummy.html +++ b/doc/html/_dummy.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_dummy_model_8cpp.html b/doc/html/_dummy_model_8cpp.html index 9e44563aa..387bd4d4e 100644 --- a/doc/html/_dummy_model_8cpp.html +++ b/doc/html/_dummy_model_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_dummy_model_8cpp_source.html b/doc/html/_dummy_model_8cpp_source.html index 6ffdfb289..14f2e90f7 100644 --- a/doc/html/_dummy_model_8cpp_source.html +++ b/doc/html/_dummy_model_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_dummy_model_8h.html b/doc/html/_dummy_model_8h.html index 391ece2bc..199f73931 100644 --- a/doc/html/_dummy_model_8h.html +++ b/doc/html/_dummy_model_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_dummy_model_8h_source.html b/doc/html/_dummy_model_8h_source.html index 076830ff8..fcc1630a5 100644 --- a/doc/html/_dummy_model_8h_source.html +++ b/doc/html/_dummy_model_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_energy_balance_doc.html b/doc/html/_energy_balance_doc.html index 5b4e62323..29e605824 100644 --- a/doc/html/_energy_balance_doc.html +++ b/doc/html/_energy_balance_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_energy_balance_model_8cpp.html b/doc/html/_energy_balance_model_8cpp.html index 8ead9d96e..d87c1843c 100644 --- a/doc/html/_energy_balance_model_8cpp.html +++ b/doc/html/_energy_balance_model_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_energy_balance_model_8cpp_source.html b/doc/html/_energy_balance_model_8cpp_source.html index 918ac5c4a..ce882cfeb 100644 --- a/doc/html/_energy_balance_model_8cpp_source.html +++ b/doc/html/_energy_balance_model_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_energy_balance_model_8cu.html b/doc/html/_energy_balance_model_8cu.html index f11698dd5..fd1d1c247 100644 --- a/doc/html/_energy_balance_model_8cu.html +++ b/doc/html/_energy_balance_model_8cu.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_energy_balance_model_8cu_source.html b/doc/html/_energy_balance_model_8cu_source.html index a763c3236..6dcb92a16 100644 --- a/doc/html/_energy_balance_model_8cu_source.html +++ b/doc/html/_energy_balance_model_8cu_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_energy_balance_model_8h.html b/doc/html/_energy_balance_model_8h.html index 3b1cd2879..1a47bde59 100644 --- a/doc/html/_energy_balance_model_8h.html +++ b/doc/html/_energy_balance_model_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_energy_balance_model_8h_source.html b/doc/html/_energy_balance_model_8h_source.html index 6257f384a..0c4f6b1f3 100644 --- a/doc/html/_energy_balance_model_8h_source.html +++ b/doc/html/_energy_balance_model_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_i_o.html b/doc/html/_i_o.html index 4f5cfa955..dbd521285 100644 --- a/doc/html/_i_o.html +++ b/doc/html/_i_o.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -224,7 +224,7 @@

}
Stores the state associated with simulation.
Definition Context.h:1882
-
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.
+
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.
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:1884
@@ -269,7 +269,7 @@

context.loadPLY( "file.ply", origin, scale, rotation, color );
}
-
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...
+
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...
R-G-B color vector.
Vector of spherical coordinates (elevation,azimuth)
Vector of three elements of type 'float'.
@@ -310,7 +310,7 @@

context.loadOBJ("relative/path/to/someobjfile.obj", make_vec3(0,0,0), 0, nullrotation, RGB::red );
}
-
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...
+
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...

Writing PLY (Stanford Polygon) Files

The Context has analogous files for writing PLY files based on the geometry currently loaded in the Context. This is accomplished via the writePLY() command, as illustrated below.

@@ -326,7 +326,7 @@

context.writePLY( "file.ply" );
}
-
void writePLY(const char *filename) const
Write geometry in the Context to a Stanford polygon file (.ply)
+
void writePLY(const char *filename) const
Write geometry in the Context to a Stanford polygon file (.ply)
uint addPatch()
Add new default Patch geometric primitive, which is centered at the origin (0,0,0),...
Definition Context.cpp:1202

Writing OBJ (Wavefront) Files

@@ -344,7 +344,7 @@

context.writeOBJ( "file" );
}
-
void writeOBJ(const std::string &filename) const
Write geometry in the Context to a Wavefront file (.obj)
+
void writeOBJ(const std::string &filename) const
Write geometry in the Context to a Wavefront file (.obj)

Exporting Project to XML File Format

All geometry and global/primitive data loaded into the Context can be written to an XML file using the writeXML() function, which can be later read back in using the loadXML(). This functionality can be used to save progress during a simulation run, or to ensure that consistent geometry is always used across simulation runs, among other things.

@@ -397,7 +397,7 @@

context.writePrimitiveData( "file.txt", columns );
}
-
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 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.

By default, column header labels will not be written, but if the optional third argument is set as "true" the label of the primitive data for each column will be written to the first line of the file.

diff --git a/doc/html/_input_output_8cpp.html b/doc/html/_input_output_8cpp.html index cd4926022..cd3de254c 100644 --- a/doc/html/_input_output_8cpp.html +++ b/doc/html/_input_output_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_input_output_8cpp_source.html b/doc/html/_input_output_8cpp_source.html index 075e20541..e8f15d293 100644 --- a/doc/html/_input_output_8cpp_source.html +++ b/doc/html/_input_output_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -533,310 +533,317 @@
441 helios_runtime_error("ERROR (PlantArchitecture::writePlantStructureXML): Plant ID " + std::to_string(plantID) + " does not exist.");
442 }
443
-
444 //\todo Check the extension of 'filename' and add .xml if needed
-
445
-
446 std::ofstream output_xml(filename);
-
447
-
448 if( !output_xml.is_open() ){
-
449 helios_runtime_error("ERROR (PlantArchitecture::writePlantStructureXML): Could not open file " + filename + " for writing. Make sure the directory exists and is writable.");
-
450 }
-
451
-
452 output_xml << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
-
453 output_xml << "<helios>" << std::endl;
-
454 output_xml << "\t<plant_instance ID=\"" << plantID << "\">" << std::endl;
-
455
-
456 output_xml << "\t\t<base_position> " << plant_instances.at(plantID).base_position.x << " " << plant_instances.at(plantID).base_position.y << " " << plant_instances.at(plantID).base_position.z << " </base_position>" << std::endl;
-
457 output_xml << "\t\t<plant_age> " << plant_instances.at(plantID).current_age << " </plant_age>" << std::endl;
-
458
-
459 for( auto& shoot : plant_instances.at(plantID).shoot_tree ) {
+
444 std::string output_file = filename;
+
445 if( !validateOutputPath(output_file,{".xml",".XML"}) ){
+
446 helios_runtime_error("ERROR (PlantArchitecture::writePlantStructureXML): Could not open file " + filename + " for writing. Make sure the directory exists and is writable.");
+
447 }else if( getFileName(output_file).empty()){
+
448 helios_runtime_error("ERROR (PlantArchitecture::writePlantStructureXML): The output file given was a directory. This argument should be the path to a file not to a directory.");
+
449 }
+
450
+
451 std::ofstream output_xml(filename);
+
452
+
453 if( !output_xml.is_open() ){
+
454 helios_runtime_error("ERROR (PlantArchitecture::writePlantStructureXML): Could not open file " + filename + " for writing. Make sure the directory exists and is writable.");
+
455 }
+
456
+
457 output_xml << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
+
458 output_xml << "<helios>" << std::endl;
+
459 output_xml << "\t<plant_instance ID=\"" << plantID << "\">" << std::endl;
460
-
461 output_xml << "\t\t<shoot ID=\"" << shoot->ID << "\">" << std::endl;
-
462 output_xml << "\t\t\t<shoot_type_label> " << shoot->shoot_type_label << " </shoot_type_label>" << std::endl;
-
463 output_xml << "\t\t\t<parent_shoot_ID> " << shoot->parent_shoot_ID << " </parent_shoot_ID>" << std::endl;
-
464 output_xml << "\t\t\t<parent_node_index> " << shoot->parent_node_index << " </parent_node_index>" << std::endl;
-
465 output_xml << "\t\t\t<parent_petiole_index> " << shoot->parent_petiole_index << " </parent_petiole_index>" << std::endl;
-
466 output_xml << "\t\t\t<base_rotation> " << rad2deg(shoot->base_rotation.pitch) << " " << rad2deg(shoot->base_rotation.yaw) << " " << rad2deg(shoot->base_rotation.roll) << " </base_rotation>" << std::endl;
-
467
-
468 for (auto &phytomer: shoot->phytomers) {
-
469
-
470 output_xml << "\t\t\t<phytomer>" << std::endl;
-
471 output_xml << "\t\t\t\t<internode>" << std::endl;
-
472 output_xml << "\t\t\t\t\t<internode_length>" << phytomer->getInternodeLength() << "</internode_length>" << std::endl;
-
473 output_xml << "\t\t\t\t\t<internode_radius>" << phytomer->getInternodeRadius() << "</internode_radius>" << std::endl;
-
474 output_xml << "\t\t\t\t\t<internode_pitch>" << rad2deg(phytomer->internode_pitch) << "</internode_pitch>" << std::endl;
-
475 output_xml << "\t\t\t\t\t<internode_phyllotactic_angle>" << rad2deg(phytomer->internode_phyllotactic_angle) << "</internode_phyllotactic_angle>" << std::endl;
-
476
-
477 for (uint petiole = 0; petiole < phytomer->petiole_length.size(); petiole++) {
-
478
-
479 output_xml << "\t\t\t\t\t<petiole>" << std::endl;
-
480 output_xml << "\t\t\t\t\t\t<petiole_length>" << phytomer->petiole_length.at(petiole) << "</petiole_length>" << std::endl;
-
481 output_xml << "\t\t\t\t\t\t<petiole_radius>" << phytomer->petiole_radii.at(petiole).front() << "</petiole_radius>" << std::endl;
-
482 output_xml << "\t\t\t\t\t\t<petiole_pitch>" << rad2deg(phytomer->petiole_pitch) << "</petiole_pitch>" << std::endl;
-
483 output_xml << "\t\t\t\t\t\t<petiole_curvature>" << phytomer->petiole_curvature << "</petiole_curvature>" << std::endl;
-
484 if( phytomer->leaf_rotation.at(petiole).size()==1 ){ //not compound leaf
-
485 output_xml << "\t\t\t\t\t\t<leaflet_scale>" << 1.0 << "</leaflet_scale>" << std::endl;
-
486 }else {
-
487 float tip_ind = floor(float(phytomer->leaf_rotation.at(petiole).size() - 1) / 2.f);
-
488 output_xml << "\t\t\t\t\t\t<leaflet_scale>" << phytomer->leaf_size_max.at(petiole).at(int(tip_ind-1)) / max(phytomer->leaf_size_max.at(petiole)) << "</leaflet_scale>" << std::endl;
-
489 }
-
490
-
491 for( uint leaf=0; leaf < phytomer->leaf_rotation.at(petiole).size(); leaf++ ){
-
492 output_xml << "\t\t\t\t\t\t<leaf>" << std::endl;
-
493 output_xml << "\t\t\t\t\t\t\t<leaf_scale>" << phytomer->leaf_size_max.at(petiole).at(leaf)*phytomer->current_leaf_scale_factor << "</leaf_scale>" << std::endl;
-
494 output_xml << "\t\t\t\t\t\t\t<leaf_pitch>" << rad2deg(phytomer->leaf_rotation.at(petiole).at(leaf).pitch) << "</leaf_pitch>" << std::endl;
-
495 output_xml << "\t\t\t\t\t\t\t<leaf_yaw>" << rad2deg(phytomer->leaf_rotation.at(petiole).at(leaf).yaw) << "</leaf_yaw>" << std::endl;
-
496 output_xml << "\t\t\t\t\t\t\t<leaf_roll>" << rad2deg(phytomer->leaf_rotation.at(petiole).at(leaf).roll) << "</leaf_roll>" << std::endl;
-
497 output_xml << "\t\t\t\t\t\t</leaf>" << std::endl;
-
498 }
-
499
-
500 output_xml << "\t\t\t\t\t</petiole>" << std::endl;
-
501 }
-
502 output_xml << "\t\t\t\t</internode>" << std::endl;
-
503 output_xml << "\t\t\t</phytomer>" << std::endl;
-
504 }
-
505 output_xml << "\t\t</shoot>" << std::endl;
-
506 }
-
507 output_xml << "\t</plant_instance>" << std::endl;
-
508 output_xml << "</helios>" << std::endl;
-
509 output_xml.close();
-
510
-
511
-
512}
-
513
-
514std::vector<uint> PlantArchitecture::readPlantStructureXML( const std::string &filename, bool quiet){
+
461 output_xml << "\t\t<base_position> " << plant_instances.at(plantID).base_position.x << " " << plant_instances.at(plantID).base_position.y << " " << plant_instances.at(plantID).base_position.z << " </base_position>" << std::endl;
+
462 output_xml << "\t\t<plant_age> " << plant_instances.at(plantID).current_age << " </plant_age>" << std::endl;
+
463
+
464 for( auto& shoot : plant_instances.at(plantID).shoot_tree ) {
+
465
+
466 output_xml << "\t\t<shoot ID=\"" << shoot->ID << "\">" << std::endl;
+
467 output_xml << "\t\t\t<shoot_type_label> " << shoot->shoot_type_label << " </shoot_type_label>" << std::endl;
+
468 output_xml << "\t\t\t<parent_shoot_ID> " << shoot->parent_shoot_ID << " </parent_shoot_ID>" << std::endl;
+
469 output_xml << "\t\t\t<parent_node_index> " << shoot->parent_node_index << " </parent_node_index>" << std::endl;
+
470 output_xml << "\t\t\t<parent_petiole_index> " << shoot->parent_petiole_index << " </parent_petiole_index>" << std::endl;
+
471 output_xml << "\t\t\t<base_rotation> " << rad2deg(shoot->base_rotation.pitch) << " " << rad2deg(shoot->base_rotation.yaw) << " " << rad2deg(shoot->base_rotation.roll) << " </base_rotation>" << std::endl;
+
472
+
473 for (auto &phytomer: shoot->phytomers) {
+
474
+
475 output_xml << "\t\t\t<phytomer>" << std::endl;
+
476 output_xml << "\t\t\t\t<internode>" << std::endl;
+
477 output_xml << "\t\t\t\t\t<internode_length>" << phytomer->getInternodeLength() << "</internode_length>" << std::endl;
+
478 output_xml << "\t\t\t\t\t<internode_radius>" << phytomer->getInternodeRadius() << "</internode_radius>" << std::endl;
+
479 output_xml << "\t\t\t\t\t<internode_pitch>" << rad2deg(phytomer->internode_pitch) << "</internode_pitch>" << std::endl;
+
480 output_xml << "\t\t\t\t\t<internode_phyllotactic_angle>" << rad2deg(phytomer->internode_phyllotactic_angle) << "</internode_phyllotactic_angle>" << std::endl;
+
481
+
482 for (uint petiole = 0; petiole < phytomer->petiole_length.size(); petiole++) {
+
483
+
484 output_xml << "\t\t\t\t\t<petiole>" << std::endl;
+
485 output_xml << "\t\t\t\t\t\t<petiole_length>" << phytomer->petiole_length.at(petiole) << "</petiole_length>" << std::endl;
+
486 output_xml << "\t\t\t\t\t\t<petiole_radius>" << phytomer->petiole_radii.at(petiole).front() << "</petiole_radius>" << std::endl;
+
487 output_xml << "\t\t\t\t\t\t<petiole_pitch>" << rad2deg(phytomer->petiole_pitch) << "</petiole_pitch>" << std::endl;
+
488 output_xml << "\t\t\t\t\t\t<petiole_curvature>" << phytomer->petiole_curvature << "</petiole_curvature>" << std::endl;
+
489 if( phytomer->leaf_rotation.at(petiole).size()==1 ){ //not compound leaf
+
490 output_xml << "\t\t\t\t\t\t<leaflet_scale>" << 1.0 << "</leaflet_scale>" << std::endl;
+
491 }else {
+
492 float tip_ind = floor(float(phytomer->leaf_rotation.at(petiole).size() - 1) / 2.f);
+
493 output_xml << "\t\t\t\t\t\t<leaflet_scale>" << phytomer->leaf_size_max.at(petiole).at(int(tip_ind-1)) / max(phytomer->leaf_size_max.at(petiole)) << "</leaflet_scale>" << std::endl;
+
494 }
+
495
+
496 for( uint leaf=0; leaf < phytomer->leaf_rotation.at(petiole).size(); leaf++ ){
+
497 output_xml << "\t\t\t\t\t\t<leaf>" << std::endl;
+
498 output_xml << "\t\t\t\t\t\t\t<leaf_scale>" << phytomer->leaf_size_max.at(petiole).at(leaf)*phytomer->current_leaf_scale_factor << "</leaf_scale>" << std::endl;
+
499 output_xml << "\t\t\t\t\t\t\t<leaf_pitch>" << rad2deg(phytomer->leaf_rotation.at(petiole).at(leaf).pitch) << "</leaf_pitch>" << std::endl;
+
500 output_xml << "\t\t\t\t\t\t\t<leaf_yaw>" << rad2deg(phytomer->leaf_rotation.at(petiole).at(leaf).yaw) << "</leaf_yaw>" << std::endl;
+
501 output_xml << "\t\t\t\t\t\t\t<leaf_roll>" << rad2deg(phytomer->leaf_rotation.at(petiole).at(leaf).roll) << "</leaf_roll>" << std::endl;
+
502 output_xml << "\t\t\t\t\t\t</leaf>" << std::endl;
+
503 }
+
504
+
505 output_xml << "\t\t\t\t\t</petiole>" << std::endl;
+
506 }
+
507 output_xml << "\t\t\t\t</internode>" << std::endl;
+
508 output_xml << "\t\t\t</phytomer>" << std::endl;
+
509 }
+
510 output_xml << "\t\t</shoot>" << std::endl;
+
511 }
+
512 output_xml << "\t</plant_instance>" << std::endl;
+
513 output_xml << "</helios>" << std::endl;
+
514 output_xml.close();
515
-
516 if( !quiet ) {
-
517 std::cout << "Loading plant architecture XML file: " << filename << "..." << std::flush;
-
518 }
-
519
-
520 std::string fn = filename;
-
521 std::string ext = getFileExtension(filename);
-
522 if( ext != ".xml" && ext != ".XML" ) {
-
523 helios_runtime_error("failed.\n File " + fn + " is not XML format.");
-
524 }
-
525
-
526 std::vector<uint> plantIDs;
-
527
-
528 // Using "pugixml" parser. See pugixml.org
-
529 pugi::xml_document xmldoc;
+
516
+
517}
+
518
+
519std::vector<uint> PlantArchitecture::readPlantStructureXML( const std::string &filename, bool quiet){
+
520
+
521 if( !quiet ) {
+
522 std::cout << "Loading plant architecture XML file: " << filename << "..." << std::flush;
+
523 }
+
524
+
525 std::string fn = filename;
+
526 std::string ext = getFileExtension(filename);
+
527 if( ext != ".xml" && ext != ".XML" ) {
+
528 helios_runtime_error("failed.\n File " + fn + " is not XML format.");
+
529 }
530
-
531 //load file
-
532 pugi::xml_parse_result load_result = xmldoc.load_file(filename.c_str());
-
533
-
534 //error checking
-
535 if (!load_result){
-
536 helios_runtime_error("ERROR (Context::readPlantStructureXML): Could not parse " + std::string(filename) + ":\nError description: " + load_result.description() );
-
537 }
+
531 std::vector<uint> plantIDs;
+
532
+
533 // Using "pugixml" parser. See pugixml.org
+
534 pugi::xml_document xmldoc;
+
535
+
536 //load file
+
537 pugi::xml_parse_result load_result = xmldoc.load_file(filename.c_str());
538
-
539 pugi::xml_node helios = xmldoc.child("helios");
-
540
-
541 pugi::xml_node node;
-
542 std::string node_string;
+
539 //error checking
+
540 if (!load_result){
+
541 helios_runtime_error("ERROR (Context::readPlantStructureXML): Could not parse " + std::string(filename) + ":\nError description: " + load_result.description() );
+
542 }
543
-
544 if( helios.empty() ){
-
545 if( !quiet ) {
-
546 std::cout << "failed." << std::endl;
-
547 }
-
548 helios_runtime_error("ERROR (Context::readPlantStructureXML): XML file must have tag '<helios> ... </helios>' bounding all other tags.");
-
549 }
-
550
-
551 size_t phytomer_count = 0;
-
552
-
553 std::map<int,int> shoot_ID_mapping;
-
554
-
555 for (pugi::xml_node plant = helios.child("plant_instance"); plant; plant = plant.next_sibling("plant_instance")) {
-
556
-
557 int plantID = std::stoi(plant.attribute("ID").value());
-
558
-
559 // base position
-
560 node_string = "base_position";
-
561 vec3 base_position = parse_xml_tag_vec3(plant.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
562
-
563 // plant age
-
564 node_string = "plant_age";
-
565 float plant_age = parse_xml_tag_float(plant.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
566
-
567 plantID = addPlantInstance(base_position, plant_age);
-
568 plantIDs.push_back(plantID);
-
569
-
570 int current_shoot_ID;
+
544 pugi::xml_node helios = xmldoc.child("helios");
+
545
+
546 pugi::xml_node node;
+
547 std::string node_string;
+
548
+
549 if( helios.empty() ){
+
550 if( !quiet ) {
+
551 std::cout << "failed." << std::endl;
+
552 }
+
553 helios_runtime_error("ERROR (Context::readPlantStructureXML): XML file must have tag '<helios> ... </helios>' bounding all other tags.");
+
554 }
+
555
+
556 size_t phytomer_count = 0;
+
557
+
558 std::map<int,int> shoot_ID_mapping;
+
559
+
560 for (pugi::xml_node plant = helios.child("plant_instance"); plant; plant = plant.next_sibling("plant_instance")) {
+
561
+
562 int plantID = std::stoi(plant.attribute("ID").value());
+
563
+
564 // base position
+
565 node_string = "base_position";
+
566 vec3 base_position = parse_xml_tag_vec3(plant.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
567
+
568 // plant age
+
569 node_string = "plant_age";
+
570 float plant_age = parse_xml_tag_float(plant.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
571
-
572 for (pugi::xml_node shoot = plant.child("shoot"); shoot; shoot = shoot.next_sibling("shoot")) {
-
573
-
574 int shootID = std::stoi(shoot.attribute("ID").value());
-
575 bool base_shoot = true;
+
572 plantID = addPlantInstance(base_position, plant_age);
+
573 plantIDs.push_back(plantID);
+
574
+
575 int current_shoot_ID;
576
-
577 // shoot type
-
578 node_string = "shoot_type_label";
-
579 std::string shoot_type_label = parse_xml_tag_string(shoot.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
580
-
581 // parent shoot ID
-
582 node_string = "parent_shoot_ID";
-
583 int parent_shoot_ID = parse_xml_tag_int(shoot.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
584
-
585 // parent node index
-
586 node_string = "parent_node_index";
-
587 int parent_node_index = parse_xml_tag_int(shoot.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
588
-
589 // parent petiole index
-
590 node_string = "parent_petiole_index";
-
591 int parent_petiole_index = parse_xml_tag_int(shoot.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
592
-
593 // base rotation
-
594 node_string = "base_rotation";
-
595 vec3 base_rot = parse_xml_tag_vec3(shoot.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
596 AxisRotation base_rotation(deg2rad(base_rot.x), deg2rad(base_rot.y), deg2rad(base_rot.z));
+
577 for (pugi::xml_node shoot = plant.child("shoot"); shoot; shoot = shoot.next_sibling("shoot")) {
+
578
+
579 int shootID = std::stoi(shoot.attribute("ID").value());
+
580 bool base_shoot = true;
+
581
+
582 // shoot type
+
583 node_string = "shoot_type_label";
+
584 std::string shoot_type_label = parse_xml_tag_string(shoot.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
585
+
586 // parent shoot ID
+
587 node_string = "parent_shoot_ID";
+
588 int parent_shoot_ID = parse_xml_tag_int(shoot.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
589
+
590 // parent node index
+
591 node_string = "parent_node_index";
+
592 int parent_node_index = parse_xml_tag_int(shoot.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
593
+
594 // parent petiole index
+
595 node_string = "parent_petiole_index";
+
596 int parent_petiole_index = parse_xml_tag_int(shoot.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
597
-
598 for (pugi::xml_node phytomer = shoot.child("phytomer"); phytomer; phytomer = phytomer.next_sibling("phytomer")) {
-
599
-
600 pugi::xml_node internode = phytomer.child("internode");
-
601
-
602 // internode length
-
603 node_string = "internode_length";
-
604 float internode_length = parse_xml_tag_float(internode.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
605
-
606 // internode radius
-
607 node_string = "internode_radius";
-
608 float internode_radius = parse_xml_tag_float(internode.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
609
-
610 // internode pitch
-
611 node_string = "internode_pitch";
-
612 float internode_pitch = parse_xml_tag_float(internode.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
613
-
614 // internode phyllotactic angle
-
615 node_string = "internode_phyllotactic_angle";
-
616 float internode_phyllotactic_angle = parse_xml_tag_float(internode.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
617
-
618 float petiole_length;
-
619 float petiole_radius;
-
620 float petiole_pitch;
-
621 float petiole_curvature;
-
622 float leaflet_scale;
-
623 std::vector<std::vector<float>> leaf_scale; //first index is petiole within internode; second index is leaf within petiole
-
624 std::vector<std::vector<float>> leaf_pitch;
-
625 std::vector<std::vector<float>> leaf_yaw;
-
626 std::vector<std::vector<float>> leaf_roll;
-
627 for (pugi::xml_node petiole = internode.child("petiole"); petiole; petiole = petiole.next_sibling("petiole")) {
-
628
-
629 // petiole length
-
630 node_string = "petiole_length";
-
631 petiole_length = parse_xml_tag_float(petiole.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
632
-
633 // petiole radius
-
634 node_string = "petiole_radius";
-
635 petiole_radius = parse_xml_tag_float(petiole.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
636
-
637 // petiole pitch
-
638 node_string = "petiole_pitch";
-
639 petiole_pitch = parse_xml_tag_float(petiole.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
640
-
641 // petiole curvature
-
642 node_string = "petiole_curvature";
-
643 petiole_curvature = parse_xml_tag_float(petiole.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
644
-
645 // leaflet scale factor
-
646 node_string = "leaflet_scale";
-
647 leaflet_scale = parse_xml_tag_float(petiole.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
648
-
649 leaf_scale.resize(leaf_scale.size() + 1);
-
650 leaf_pitch.resize(leaf_pitch.size() + 1);
-
651 leaf_yaw.resize(leaf_yaw.size() + 1);
-
652 leaf_roll.resize(leaf_roll.size() + 1);
-
653 for (pugi::xml_node leaf = petiole.child("leaf"); leaf; leaf = leaf.next_sibling("leaf")) {
-
654
-
655 // leaf scale factor
-
656 node_string = "leaf_scale";
-
657 leaf_scale.back().push_back( parse_xml_tag_float(leaf.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML") );
-
658
-
659 // leaf pitch
-
660 node_string = "leaf_pitch";
-
661 leaf_pitch.back().push_back( parse_xml_tag_float(leaf.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML") );
-
662
-
663 // leaf yaw
-
664 node_string = "leaf_yaw";
-
665 leaf_yaw.back().push_back( parse_xml_tag_float(leaf.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML") );
-
666
-
667 // leaf roll
-
668 node_string = "leaf_roll";
-
669 leaf_roll.back().push_back( parse_xml_tag_float(leaf.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML") );
-
670
-
671 }
-
672 } //petioles
-
673
-
674 if( shoot_types.find(shoot_type_label)==shoot_types.end() ){
-
675 helios_runtime_error("ERROR (PlantArchitecture::readPlantStructureXML): Shoot type " + shoot_type_label + " not found in shoot types.");
-
676 }
-
677
+
598 // base rotation
+
599 node_string = "base_rotation";
+
600 vec3 base_rot = parse_xml_tag_vec3(shoot.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
601 AxisRotation base_rotation(deg2rad(base_rot.x), deg2rad(base_rot.y), deg2rad(base_rot.z));
+
602
+
603 for (pugi::xml_node phytomer = shoot.child("phytomer"); phytomer; phytomer = phytomer.next_sibling("phytomer")) {
+
604
+
605 pugi::xml_node internode = phytomer.child("internode");
+
606
+
607 // internode length
+
608 node_string = "internode_length";
+
609 float internode_length = parse_xml_tag_float(internode.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
610
+
611 // internode radius
+
612 node_string = "internode_radius";
+
613 float internode_radius = parse_xml_tag_float(internode.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
614
+
615 // internode pitch
+
616 node_string = "internode_pitch";
+
617 float internode_pitch = parse_xml_tag_float(internode.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
618
+
619 // internode phyllotactic angle
+
620 node_string = "internode_phyllotactic_angle";
+
621 float internode_phyllotactic_angle = parse_xml_tag_float(internode.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
622
+
623 float petiole_length;
+
624 float petiole_radius;
+
625 float petiole_pitch;
+
626 float petiole_curvature;
+
627 float leaflet_scale;
+
628 std::vector<std::vector<float>> leaf_scale; //first index is petiole within internode; second index is leaf within petiole
+
629 std::vector<std::vector<float>> leaf_pitch;
+
630 std::vector<std::vector<float>> leaf_yaw;
+
631 std::vector<std::vector<float>> leaf_roll;
+
632 for (pugi::xml_node petiole = internode.child("petiole"); petiole; petiole = petiole.next_sibling("petiole")) {
+
633
+
634 // petiole length
+
635 node_string = "petiole_length";
+
636 petiole_length = parse_xml_tag_float(petiole.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
637
+
638 // petiole radius
+
639 node_string = "petiole_radius";
+
640 petiole_radius = parse_xml_tag_float(petiole.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
641
+
642 // petiole pitch
+
643 node_string = "petiole_pitch";
+
644 petiole_pitch = parse_xml_tag_float(petiole.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
645
+
646 // petiole curvature
+
647 node_string = "petiole_curvature";
+
648 petiole_curvature = parse_xml_tag_float(petiole.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
649
+
650 // leaflet scale factor
+
651 node_string = "leaflet_scale";
+
652 leaflet_scale = parse_xml_tag_float(petiole.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
653
+
654 leaf_scale.resize(leaf_scale.size() + 1);
+
655 leaf_pitch.resize(leaf_pitch.size() + 1);
+
656 leaf_yaw.resize(leaf_yaw.size() + 1);
+
657 leaf_roll.resize(leaf_roll.size() + 1);
+
658 for (pugi::xml_node leaf = petiole.child("leaf"); leaf; leaf = leaf.next_sibling("leaf")) {
+
659
+
660 // leaf scale factor
+
661 node_string = "leaf_scale";
+
662 leaf_scale.back().push_back( parse_xml_tag_float(leaf.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML") );
+
663
+
664 // leaf pitch
+
665 node_string = "leaf_pitch";
+
666 leaf_pitch.back().push_back( parse_xml_tag_float(leaf.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML") );
+
667
+
668 // leaf yaw
+
669 node_string = "leaf_yaw";
+
670 leaf_yaw.back().push_back( parse_xml_tag_float(leaf.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML") );
+
671
+
672 // leaf roll
+
673 node_string = "leaf_roll";
+
674 leaf_roll.back().push_back( parse_xml_tag_float(leaf.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML") );
+
675
+
676 }
+
677 } //petioles
678
-
679 ShootParameters shoot_parameters = getCurrentShootParameters(shoot_type_label);
-
680
-
681 shoot_parameters.phytomer_parameters.phytomer_creation_function = nullptr;
+
679 if( shoot_types.find(shoot_type_label)==shoot_types.end() ){
+
680 helios_runtime_error("ERROR (PlantArchitecture::readPlantStructureXML): Shoot type " + shoot_type_label + " not found in shoot types.");
+
681 }
682
-
683 shoot_parameters.phytomer_parameters.internode.pitch = internode_pitch;
-
684 shoot_parameters.phytomer_parameters.internode.phyllotactic_angle = internode_phyllotactic_angle;
+
683
+
684 ShootParameters shoot_parameters = getCurrentShootParameters(shoot_type_label);
685
-
686 shoot_parameters.phytomer_parameters.petiole.length = petiole_length;
-
687 shoot_parameters.phytomer_parameters.petiole.radius = petiole_radius;
-
688 shoot_parameters.phytomer_parameters.petiole.pitch = petiole_pitch;
-
689 shoot_parameters.phytomer_parameters.petiole.curvature = petiole_curvature;
+
686 shoot_parameters.phytomer_parameters.phytomer_creation_function = nullptr;
+
687
+
688 shoot_parameters.phytomer_parameters.internode.pitch = internode_pitch;
+
689 shoot_parameters.phytomer_parameters.internode.phyllotactic_angle = internode_phyllotactic_angle;
690
-
691 float tip_ind = floor(float(leaf_scale.front().size() - 1) / 2.f);
-
692 shoot_parameters.phytomer_parameters.leaf.prototype_scale = leaf_scale.front().at(tip_ind);
-
693 shoot_parameters.phytomer_parameters.leaf.pitch = 0;
-
694 shoot_parameters.phytomer_parameters.leaf.yaw = 0;
-
695 shoot_parameters.phytomer_parameters.leaf.roll = 0;
-
696 shoot_parameters.phytomer_parameters.leaf.leaflet_scale = leaflet_scale;
-
697
-
698 std::string shoot_label = "shoot_" + std::to_string(phytomer_count);
-
699 defineShootType( shoot_label, shoot_parameters);
-
700
-
701 if( base_shoot ){
+
691 shoot_parameters.phytomer_parameters.petiole.length = petiole_length;
+
692 shoot_parameters.phytomer_parameters.petiole.radius = petiole_radius;
+
693 shoot_parameters.phytomer_parameters.petiole.pitch = petiole_pitch;
+
694 shoot_parameters.phytomer_parameters.petiole.curvature = petiole_curvature;
+
695
+
696 float tip_ind = floor(float(leaf_scale.front().size() - 1) / 2.f);
+
697 shoot_parameters.phytomer_parameters.leaf.prototype_scale = leaf_scale.front().at(tip_ind);
+
698 shoot_parameters.phytomer_parameters.leaf.pitch = 0;
+
699 shoot_parameters.phytomer_parameters.leaf.yaw = 0;
+
700 shoot_parameters.phytomer_parameters.leaf.roll = 0;
+
701 shoot_parameters.phytomer_parameters.leaf.leaflet_scale = leaflet_scale;
702
-
703 if( parent_shoot_ID<0 ) { //this is the first shoot of the plant
-
704 current_shoot_ID = addBaseStemShoot(plantID, 1, base_rotation, internode_radius, internode_length, 1.f, 1.f, 0, shoot_label);
-
705 shoot_ID_mapping[shootID] = current_shoot_ID;
-
706 }else{ //this is a child of an existing shoot
-
707 current_shoot_ID = addChildShoot(plantID, shoot_ID_mapping.at(parent_shoot_ID), parent_node_index, 1, base_rotation, internode_radius, internode_length, 1.f, 1.f, 0, shoot_label, parent_petiole_index);
-
708 shoot_ID_mapping[shootID] = current_shoot_ID;
-
709 }
-
710
-
711 base_shoot = false;
-
712 }else{
-
713 appendPhytomerToShoot(plantID, current_shoot_ID, shoot_parameters.phytomer_parameters, internode_radius, internode_length, 1, 1);
-
714 }
+
703 std::string shoot_label = "shoot_" + std::to_string(phytomer_count);
+
704 defineShootType( shoot_label, shoot_parameters);
+
705
+
706 if( base_shoot ){
+
707
+
708 if( parent_shoot_ID<0 ) { //this is the first shoot of the plant
+
709 current_shoot_ID = addBaseStemShoot(plantID, 1, base_rotation, internode_radius, internode_length, 1.f, 1.f, 0, shoot_label);
+
710 shoot_ID_mapping[shootID] = current_shoot_ID;
+
711 }else{ //this is a child of an existing shoot
+
712 current_shoot_ID = addChildShoot(plantID, shoot_ID_mapping.at(parent_shoot_ID), parent_node_index, 1, base_rotation, internode_radius, internode_length, 1.f, 1.f, 0, shoot_label, parent_petiole_index);
+
713 shoot_ID_mapping[shootID] = current_shoot_ID;
+
714 }
715
-
716 //rotate leaves
-
717 auto phytomer_ptr = plant_instances.at(plantID).shoot_tree.at(current_shoot_ID)->phytomers.back();
-
718 for( int petiole = 0; petiole<phytomer_ptr->leaf_rotation.size(); petiole++ ){
-
719 for( int leaf=0; leaf<phytomer_ptr->leaf_rotation.at(petiole).size(); leaf++ ){
-
720 phytomer_ptr->rotateLeaf(petiole, leaf, make_AxisRotation(deg2rad(leaf_pitch.at(petiole).at(leaf)), deg2rad(leaf_yaw.at(petiole).at(leaf)), deg2rad(-leaf_roll.at(petiole).at(leaf))));
-
721 }
-
722 }
-
723
-
724 phytomer_count++;
-
725 } //phytomers
-
726
-
727 } //shoots
+
716 base_shoot = false;
+
717 }else{
+
718 appendPhytomerToShoot(plantID, current_shoot_ID, shoot_parameters.phytomer_parameters, internode_radius, internode_length, 1, 1);
+
719 }
+
720
+
721 //rotate leaves
+
722 auto phytomer_ptr = plant_instances.at(plantID).shoot_tree.at(current_shoot_ID)->phytomers.back();
+
723 for( int petiole = 0; petiole<phytomer_ptr->leaf_rotation.size(); petiole++ ){
+
724 for( int leaf=0; leaf<phytomer_ptr->leaf_rotation.at(petiole).size(); leaf++ ){
+
725 phytomer_ptr->rotateLeaf(petiole, leaf, make_AxisRotation(deg2rad(leaf_pitch.at(petiole).at(leaf)), deg2rad(leaf_yaw.at(petiole).at(leaf)), deg2rad(-leaf_roll.at(petiole).at(leaf))));
+
726 }
+
727 }
728
-
729 } //plant instances
-
730
-
731 if( !quiet ) {
-
732 std::cout << "done." << std::endl;
-
733 }
-
734 return plantIDs;
+
729 phytomer_count++;
+
730 } //phytomers
+
731
+
732 } //shoots
+
733
+
734 } //plant instances
735
-
736}
+
736 if( !quiet ) {
+
737 std::cout << "done." << std::endl;
+
738 }
+
739 return plantIDs;
+
740
+
741}
-
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
-
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, float radius_taper, const std::string &shoot_type_label, uint petiole_index=0)
Manually add a child shoot at the axillary bud of a phytomer.
-
int appendPhytomerToShoot(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.
+
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
+
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, float radius_taper, const std::string &shoot_type_label, uint petiole_index=0)
Manually add a child shoot at the axillary bud of a phytomer.
+
int appendPhytomerToShoot(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.
std::map< std::string, ShootParameters > getCurrentShootParameters()
Get the shoot parameters structure for all shoot types in the current plant model.
-
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, float radius_taper, 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 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, float radius_taper, 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 ...
void defineShootType(const std::string &shoot_type_label, const ShootParameters &shoot_params)
Define a new shoot type based on a set of ShootParameters.
std::minstd_rand0 * getRandomGenerator()
Get the random number generator engine.
Definition Context.cpp:47
float parse_xml_tag_float(const pugi::xml_node &node, const std::string &tag, const std::string &calling_function)
Parse an XML tag containing a float value.
Definition global.cpp:872
vec3 parse_xml_tag_vec3(const pugi::xml_node &node, const std::string &tag, const std::string &calling_function)
Parse an XML tag containing a vec3 value (i.e., three space delimited floats)
Definition global.cpp:896
std::string getFileExtension(const std::string &filepath)
Parse a file string to get the extension.
Definition global.cpp:2993
+
bool validateOutputPath(std::string &output_directory, const std::vector< std::string > &allowable_file_extensions={})
Check whether output file and/or directory is valid. Add a trailing slash if it is a directory.
Definition global.cpp:3020
+
std::string getFileName(const std::string &filepath)
Parse a file string to get the filename including extension.
Definition global.cpp:3003
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
std::string parse_xml_tag_string(const pugi::xml_node &node, const std::string &tag, const std::string &calling_function)
Parse an XML tag containing a string.
Definition global.cpp:908
int parse_xml_tag_int(const pugi::xml_node &node, const std::string &tag, const std::string &calling_function)
Parse an XML tag containing an integer value.
Definition global.cpp:860
diff --git a/doc/html/_leaf_optics_8cpp.html b/doc/html/_leaf_optics_8cpp.html index 31b1bc05c..e6de9bc4e 100644 --- a/doc/html/_leaf_optics_8cpp.html +++ b/doc/html/_leaf_optics_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_leaf_optics_8cpp_source.html b/doc/html/_leaf_optics_8cpp_source.html index aefb528c4..8e19c6c5b 100644 --- a/doc/html/_leaf_optics_8cpp_source.html +++ b/doc/html/_leaf_optics_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_leaf_optics_8h.html b/doc/html/_leaf_optics_8h.html index 3dc43a23b..bd1e37027 100644 --- a/doc/html/_leaf_optics_8h.html +++ b/doc/html/_leaf_optics_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_leaf_optics_8h_source.html b/doc/html/_leaf_optics_8h_source.html index 6d61d4a93..4d1fff022 100644 --- a/doc/html/_leaf_optics_8h_source.html +++ b/doc/html/_leaf_optics_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_li_d_a_r_8cpp.html b/doc/html/_li_d_a_r_8cpp.html index 7d9fa358f..8b1921881 100644 --- a/doc/html/_li_d_a_r_8cpp.html +++ b/doc/html/_li_d_a_r_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_li_d_a_r_8cpp_source.html b/doc/html/_li_d_a_r_8cpp_source.html index 996a19a9f..cc3547e4f 100644 --- a/doc/html/_li_d_a_r_8cpp_source.html +++ b/doc/html/_li_d_a_r_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_li_d_a_r_8cu.html b/doc/html/_li_d_a_r_8cu.html index 2e4703fd4..906f65ad0 100644 --- a/doc/html/_li_d_a_r_8cu.html +++ b/doc/html/_li_d_a_r_8cu.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_li_d_a_r_8cu_source.html b/doc/html/_li_d_a_r_8cu_source.html index 0cd23c1b4..6112c1d7f 100644 --- a/doc/html/_li_d_a_r_8cu_source.html +++ b/doc/html/_li_d_a_r_8cu_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_li_d_a_r_8h.html b/doc/html/_li_d_a_r_8h.html index 7c77b998f..b2de21df7 100644 --- a/doc/html/_li_d_a_r_8h.html +++ b/doc/html/_li_d_a_r_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_li_d_a_r_8h_source.html b/doc/html/_li_d_a_r_8h_source.html index b52ae6f7b..3fe6bf127 100644 --- a/doc/html/_li_d_a_r_8h_source.html +++ b/doc/html/_li_d_a_r_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_li_d_a_r_doc.html b/doc/html/_li_d_a_r_doc.html index d704d8c51..33590485c 100644 --- a/doc/html/_li_d_a_r_doc.html +++ b/doc/html/_li_d_a_r_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_making_masks.html b/doc/html/_making_masks.html index 6b95427ff..571ac31cb 100644 --- a/doc/html/_making_masks.html +++ b/doc/html/_making_masks.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_overview.html b/doc/html/_overview.html index b5e74c54c..682695bf9 100644 --- a/doc/html/_overview.html +++ b/doc/html/_overview.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_p_c_g_p_u_timeout.html b/doc/html/_p_c_g_p_u_timeout.html index 7013bbb0e..733c85fde 100644 --- a/doc/html/_p_c_g_p_u_timeout.html +++ b/doc/html/_p_c_g_p_u_timeout.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_photosynthesis_doc.html b/doc/html/_photosynthesis_doc.html index f563e560a..9dcd815c3 100644 --- a/doc/html/_photosynthesis_doc.html +++ b/doc/html/_photosynthesis_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_photosynthesis_model_8cpp.html b/doc/html/_photosynthesis_model_8cpp.html index a564fd1f3..ba0c6b482 100644 --- a/doc/html/_photosynthesis_model_8cpp.html +++ b/doc/html/_photosynthesis_model_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_photosynthesis_model_8cpp_source.html b/doc/html/_photosynthesis_model_8cpp_source.html index 4f4136ed1..4a0e3b6b5 100644 --- a/doc/html/_photosynthesis_model_8cpp_source.html +++ b/doc/html/_photosynthesis_model_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_photosynthesis_model_8h.html b/doc/html/_photosynthesis_model_8h.html index 3a634450b..f05a47984 100644 --- a/doc/html/_photosynthesis_model_8h.html +++ b/doc/html/_photosynthesis_model_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_photosynthesis_model_8h_source.html b/doc/html/_photosynthesis_model_8h_source.html index 6f4ae5f26..21d0ae8d1 100644 --- a/doc/html/_photosynthesis_model_8h_source.html +++ b/doc/html/_photosynthesis_model_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_plant_architecture_8cpp.html b/doc/html/_plant_architecture_8cpp.html index b5ccb6b60..370ec1ccb 100644 --- a/doc/html/_plant_architecture_8cpp.html +++ b/doc/html/_plant_architecture_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -228,7 +228,7 @@

-

Definition at line 3064 of file PlantArchitecture.cpp.

+

Definition at line 3065 of file PlantArchitecture.cpp.

diff --git a/doc/html/_plant_architecture_8cpp_source.html b/doc/html/_plant_architecture_8cpp_source.html index d396d96f9..6d92a52e6 100644 --- a/doc/html/_plant_architecture_8cpp_source.html +++ b/doc/html/_plant_architecture_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -1058,2284 +1058,2285 @@
948 }
949
950 // create internode tube
-
951 float dt = 1.f / float(Ndiv_internode_length);
-
952 for(int inode_segment=1; inode_segment <= Ndiv_internode_length; inode_segment++ ){
-
953
-
954 //apply curvature and tortuosity
-
955 if( (fabs(parent_shoot->gravitropic_curvature) > 0 || parent_shoot_parameters.tortuosity.val() > 0 ) && shoot_index.x > 0 ) { //note: curvature is not applied to the first phytomer because if scaling is performed in the phytomer creation function it messes things up
-
956
-
957 float current_curvature_fact = 0.5f-internode_axis.z/2.f;
-
958 if( internode_axis.z<0 ){
-
959 current_curvature_fact *= 2.f;
-
960 }
-
961
-
962 parent_shoot->curvature_perturbation += - 0.5f*parent_shoot->curvature_perturbation*dt + 5*parent_shoot_parameters.tortuosity.val()*context_ptr->randn()*sqrt(dt);
-
963 float curvature_angle = deg2rad((parent_shoot->gravitropic_curvature*current_curvature_fact+parent_shoot->curvature_perturbation) * dr_internode_max);
-
964 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, shoot_bending_axis, curvature_angle);
-
965
-
966 parent_shoot->yaw_perturbation += - 0.5f*parent_shoot->yaw_perturbation*dt + 5*parent_shoot_parameters.tortuosity.val()*context_ptr->randn()*sqrt(dt);
-
967 float yaw_angle = deg2rad((parent_shoot->yaw_perturbation) * dr_internode_max);
-
968 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, make_vec3(0,0,1), yaw_angle);
-
969 }
-
970
-
971 phytomer_internode_vertices.at(inode_segment) = phytomer_internode_vertices.at(inode_segment - 1) + dr_internode * internode_axis;
-
972
-
973 phytomer_internode_radii.at(inode_segment) = internode_radius;
-
974 internode_colors.at(inode_segment) = phytomer_parameters.internode.color;
-
975
-
976 }
-
977
-
978 if( shoot_index.x==0 ) { //first phytomer on shoot
-
979 parent_shoot_ptr->shoot_internode_vertices.push_back(phytomer_internode_vertices);
-
980 parent_shoot_ptr->shoot_internode_radii.push_back(phytomer_internode_radii);
-
981 }else{ //if not the first phytomer on shoot, don't insert the first node because it's already defined on the previous phytomer
-
982 parent_shoot_ptr->shoot_internode_vertices.emplace_back(phytomer_internode_vertices.begin()+1,phytomer_internode_vertices.end());
-
983 parent_shoot_ptr->shoot_internode_radii.emplace_back(phytomer_internode_radii.begin()+1,phytomer_internode_radii.end());
-
984 }
-
985
-
986 //build internode context geometry
-
987 if( build_context_geometry_internode ) {
-
988
-
989 //calculate texture coordinates
-
990 float texture_repeat_length = 0.25f; //meters
-
991 float length=0; //shoot length prior to this phytomer
-
992 for(auto & phytomer : parent_shoot_ptr->phytomers){
-
993 length += phytomer->internode_length_max;
-
994 }
-
995 std::vector<float> uv_y(phytomer_internode_vertices.size());
-
996 float dy = internode_length_max/float(uv_y.size()-1);
-
997 for( int j=0; j<uv_y.size(); j++ ){
-
998 uv_y.at(j) = (length+j*dy)/texture_repeat_length - std::floor((length+j*dy)/texture_repeat_length);
-
999 }
-
1000
-
1001 if( !context_ptr->doesObjectExist(parent_shoot->internode_tube_objID) ){ //first internode on shoot
-
1002 if( !phytomer_parameters.internode.image_texture.empty() ){
-
1003 parent_shoot->internode_tube_objID = context_ptr->addTubeObject(Ndiv_internode_radius, phytomer_internode_vertices, phytomer_internode_radii, phytomer_parameters.internode.image_texture.c_str(), uv_y);
-
1004 }else {
-
1005 parent_shoot->internode_tube_objID = context_ptr->addTubeObject(Ndiv_internode_radius, phytomer_internode_vertices, phytomer_internode_radii, internode_colors);
-
1006 }
-
1007 }else{ //appending internode to shoot
-
1008 for (int inode_segment = 1; inode_segment <= Ndiv_internode_length; inode_segment++) {
-
1009 if( !phytomer_parameters.internode.image_texture.empty() ) {
-
1010 context_ptr->appendTubeSegment(parent_shoot->internode_tube_objID, phytomer_internode_vertices.at(inode_segment), phytomer_internode_radii.at(inode_segment), phytomer_parameters.internode.image_texture.c_str(), {uv_y.at(inode_segment-1), uv_y.at(inode_segment)});
-
1011 }else {
-
1012 context_ptr->appendTubeSegment(parent_shoot->internode_tube_objID, phytomer_internode_vertices.at(inode_segment), phytomer_internode_radii.at(inode_segment), internode_colors.at(inode_segment));
-
1013 }
-
1014 }
-
1015 }
-
1016 }
-
1017
-
1018 //--- create petiole ---//
-
1019
-
1020 vec3 petiole_axis = internode_axis;
-
1021
-
1022 //petiole pitch rotation
-
1023 petiole_pitch = deg2rad(phytomer_parameters.petiole.pitch.val());
-
1024 phytomer_parameters.petiole.pitch.resample();
-
1025 if( fabs(petiole_pitch)<deg2rad(5.f) ) {
-
1026 petiole_pitch = deg2rad(5.f);
-
1027 }
-
1028 petiole_axis = rotatePointAboutLine(petiole_axis, nullorigin, petiole_rotation_axis, std::abs(petiole_pitch) );
-
1029
-
1030 //petiole yaw rotation
-
1031 if( phytomer_index!=0 && internode_phyllotactic_angle!=0 ){ //not first phytomer along shoot
-
1032 petiole_axis = rotatePointAboutLine(petiole_axis, nullorigin, internode_axis, internode_phyllotactic_angle );
-
1033 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, internode_axis, internode_phyllotactic_angle );
-
1034 }
-
1035
-
1036 //petiole curvature
-
1037 petiole_curvature = phytomer_parameters.petiole.curvature.val();
-
1038 phytomer_parameters.petiole.curvature.resample();
-
1039
-
1040 for(int petiole=0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++ ) { //looping over petioles
-
1041
-
1042 vec3 petiole_rotation_axis_actual = petiole_rotation_axis;
-
1043 vec3 petiole_axis_actual = petiole_axis;
-
1044
-
1045 if( petiole > 0 ) {
-
1046 float budrot = float(petiole) * 2.f * M_PI / float(phytomer_parameters.petiole.petioles_per_internode);
-
1047 petiole_axis_actual = rotatePointAboutLine(petiole_axis_actual, nullorigin, internode_axis, budrot );
-
1048 petiole_rotation_axis_actual = rotatePointAboutLine(petiole_rotation_axis_actual, nullorigin, internode_axis, budrot );
-
1049 }
-
1050
-
1051 petiole_vertices.at(petiole).at(0) = phytomer_internode_vertices.back();
-
1052
-
1053 for (int j = 1; j <= Ndiv_petiole_length; j++) {
-
1054
-
1055 if( fabs(petiole_curvature)>0 ) {
-
1056 petiole_axis_actual = rotatePointAboutLine(petiole_axis_actual, nullorigin, petiole_rotation_axis_actual, -deg2rad(petiole_curvature * dr_petiole_max.at(petiole)));
-
1057 }
-
1058
-
1059 petiole_vertices.at(petiole).at(j) = petiole_vertices.at(petiole).at(j - 1) + dr_petiole.at(petiole) * petiole_axis_actual;
-
1060
-
1061 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) );
-
1062 petiole_colors.at(j) = phytomer_parameters.petiole.color;
-
1063
-
1064 }
-
1065
-
1066 if( build_context_geometry_petiole && petiole_radii.at(petiole).front() > 0.f ) {
-
1067 petiole_objIDs.at(petiole) = makeTubeFromCones(Ndiv_petiole_radius, petiole_vertices.at(petiole), petiole_radii.at(petiole), petiole_colors, context_ptr);
-
1068 }
-
1069
-
1070 //--- create buds ---//
-
1071
-
1072 std::vector<VegetativeBud> vegetative_buds_new;
-
1073 vegetative_buds_new.resize( phytomer_parameters.internode.max_vegetative_buds_per_petiole.val() );
-
1074 phytomer_parameters.internode.max_vegetative_buds_per_petiole.resample();
-
1075
-
1076 axillary_vegetative_buds.push_back(vegetative_buds_new);
-
1077
-
1078 std::vector<FloralBud> floral_buds_new;
-
1079 floral_buds_new.resize( phytomer_parameters.internode.max_floral_buds_per_petiole.val() );
-
1080 phytomer_parameters.internode.max_floral_buds_per_petiole.resample();
-
1081
-
1082 uint index = 0;
-
1083 for( auto &fbud : floral_buds_new ){
-
1084 fbud.bud_index = index;
-
1085 fbud.parent_index = petiole;
-
1086 float pitch_adjustment = fbud.bud_index * 0.1f * M_PI / float(axillary_vegetative_buds.size());
-
1087 float yaw_adjustment = -0.25f * M_PI + fbud.bud_index * 0.5f * M_PI / float(axillary_vegetative_buds.size());
-
1088 fbud.base_rotation = make_AxisRotation(pitch_adjustment, yaw_adjustment, 0);
-
1089 fbud.base_position = phytomer_internode_vertices.back();
-
1090 fbud.bending_axis = shoot_bending_axis;
-
1091 index++;
-
1092 }
-
1093
-
1094 floral_buds.push_back(floral_buds_new);
-
1095
-
1096 //--- create leaves ---//
-
1097
-
1098 if(phytomer_parameters.leaf.prototype_function == nullptr ){
-
1099 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Leaf prototype function was not defined for shoot type " + parent_shoot->shoot_type_label + ".");
-
1100 }
-
1101
-
1102 vec3 petiole_tip_axis = getPetioleAxisVector(1.f, petiole);
-
1103
-
1104 vec3 leaf_rotation_axis = cross(internode_axis, petiole_tip_axis );
-
1105
-
1106 // Create unique leaf prototypes for each shoot type so we can simply copy them for each leaf
-
1107 if( phytomer_parameters.leaf.unique_prototypes>0 && plantarchitecture_ptr->unique_leaf_prototype_objIDs.find(parent_shoot->shoot_type_label) == plantarchitecture_ptr->unique_leaf_prototype_objIDs.end() ) {
-
1108 plantarchitecture_ptr->unique_leaf_prototype_objIDs[parent_shoot->shoot_type_label].resize(phytomer_parameters.leaf.unique_prototypes);
-
1109 for( int prototype = 0; prototype < phytomer_parameters.leaf.unique_prototypes; prototype++ ) {
-
1110 for (int leaf = 0; leaf < leaves_per_petiole; leaf++) {
-
1111 float ind_from_tip = float(leaf) - float(leaves_per_petiole - 1) / 2.f;
-
1112 uint objID_leaf = phytomer_parameters.leaf.prototype_function(context_ptr, phytomer_parameters.leaf.subdivisions, ind_from_tip);
-
1113 plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(parent_shoot->shoot_type_label).at(prototype).push_back(objID_leaf);
-
1114 std::vector<uint> petiolule_UUIDs = context_ptr->filterPrimitivesByData( context_ptr->getObjectPrimitiveUUIDs(objID_leaf), "object_label", "petiolule" );
-
1115 context_ptr->setPrimitiveColor( petiolule_UUIDs, phytomer_parameters.petiole.color );
-
1116 context_ptr->hideObject({objID_leaf});
-
1117 }
-
1118 }
-
1119 }
-
1120
-
1121 for(int leaf=0; leaf < leaves_per_petiole; leaf++ ){
-
1122
-
1123 float ind_from_tip = float(leaf)-float(leaves_per_petiole-1)/2.f;
-
1124
-
1125 uint objID_leaf;
-
1126 if( phytomer_parameters.leaf.unique_prototypes>0 ) { //copy the existing prototype
-
1127 int prototype = context_ptr->randu(0, phytomer_parameters.leaf.unique_prototypes - 1);
-
1128 objID_leaf = context_ptr->copyObject(plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(parent_shoot->shoot_type_label).at(prototype).at(leaf));
-
1129 }else{ //load a new prototype
-
1130 objID_leaf = phytomer_parameters.leaf.prototype_function(context_ptr, phytomer_parameters.leaf.subdivisions, ind_from_tip);
-
1131 }
-
1132
-
1133 // -- leaf scaling -- //
-
1134
-
1135 if( leaves_per_petiole>0 && phytomer_parameters.leaf.leaflet_scale.val()!=1.f && ind_from_tip!=0 ){
-
1136 leaf_size_max.at(petiole).at(leaf) = powf(phytomer_parameters.leaf.leaflet_scale.val(),fabs(ind_from_tip))*phytomer_parameters.leaf.prototype_scale.val();
-
1137 }else{
-
1138 leaf_size_max.at(petiole).at(leaf) = phytomer_parameters.leaf.prototype_scale.val();
-
1139 }
-
1140 vec3 leaf_scale = leaf_scale_factor_fraction * leaf_size_max.at(petiole).at(leaf) * make_vec3(1,1,1);
-
1141
-
1142 context_ptr->scaleObject( objID_leaf, leaf_scale );
-
1143
-
1144 float compound_rotation = 0;
-
1145 if( leaves_per_petiole>1 ) {
-
1146 if (phytomer_parameters.leaf.leaflet_offset.val() == 0) {
-
1147 float dphi = M_PI / (floor(0.5 * float(leaves_per_petiole - 1)) + 1);
-
1148 compound_rotation = -float(M_PI) + dphi * (leaf + 0.5f);
-
1149 } else {
-
1150 if( leaf == float(leaves_per_petiole-1)/2.f ){ //tip leaf
-
1151 compound_rotation = 0;
-
1152 }else if( leaf < float(leaves_per_petiole-1)/2.f ) {
-
1153 compound_rotation = -0.5*M_PI;
-
1154 }else{
-
1155 compound_rotation = 0.5*M_PI;
-
1156 }
-
1157 }
-
1158 }
-
1159
-
1160 // -- leaf rotations -- //
-
1161
-
1162 //leaf roll rotation
-
1163 float roll_rot = 0;
-
1164 if( leaves_per_petiole==1 ){
-
1165 int sign = (shoot_index.x%2==0) ? 1 : -1;
-
1166 roll_rot = (acos_safe(internode_axis.z)-deg2rad(phytomer_parameters.leaf.roll.val()))*sign;
-
1167 } else if( ind_from_tip!= 0){
-
1168 roll_rot = (asin_safe(petiole_tip_axis.z)+deg2rad(phytomer_parameters.leaf.roll.val()))*compound_rotation/std::fabs(compound_rotation);
-
1169 }
-
1170 leaf_rotation.at(petiole).at(leaf).roll = deg2rad(phytomer_parameters.leaf.roll.val());
-
1171 phytomer_parameters.leaf.roll.resample();
-
1172 context_ptr->rotateObject(objID_leaf, roll_rot, "x" );
-
1173
-
1174 //leaf pitch rotation
-
1175 leaf_rotation.at(petiole).at(leaf).pitch = deg2rad(phytomer_parameters.leaf.pitch.val());
-
1176 float pitch_rot = leaf_rotation.at(petiole).at(leaf).pitch;
-
1177 phytomer_parameters.leaf.pitch.resample();
-
1178 if( ind_from_tip==0 ){
-
1179 pitch_rot += asin_safe(petiole_tip_axis.z);
-
1180 }
-
1181 context_ptr->rotateObject(objID_leaf, -pitch_rot , "y" );
-
1182
-
1183 //leaf yaw rotation
-
1184 if( ind_from_tip!=0 ){
-
1185 float sign = -compound_rotation/fabs(compound_rotation);
-
1186 leaf_rotation.at(petiole).at(leaf).yaw = sign*deg2rad(phytomer_parameters.leaf.yaw.val());
-
1187 float yaw_rot = leaf_rotation.at(petiole).at(leaf).yaw;
-
1188 phytomer_parameters.leaf.yaw.resample();
-
1189 context_ptr->rotateObject( objID_leaf, yaw_rot, "z" );
-
1190 }else{
-
1191 leaf_rotation.at(petiole).at(leaf).yaw = 0;
-
1192 }
-
1193
-
1194 //rotate leaf to azimuth of petiole
-
1195 context_ptr->rotateObject( objID_leaf, -std::atan2(petiole_tip_axis.y, petiole_tip_axis.x)+compound_rotation, "z" );
-
1196
+
951 for(int inode_segment=1; inode_segment <= Ndiv_internode_length; inode_segment++ ){
+
952
+
953 //apply curvature and tortuosity
+
954 if( (fabs(parent_shoot->gravitropic_curvature) > 0 || parent_shoot_parameters.tortuosity.val() > 0 ) && shoot_index.x > 0 ) { //note: curvature is not applied to the first phytomer because if scaling is performed in the phytomer creation function it messes things up
+
955
+
956 float current_curvature_fact = 0.5f-internode_axis.z/2.f;
+
957 if( internode_axis.z<0 ){
+
958 current_curvature_fact *= 2.f;
+
959 }
+
960
+
961 float dt = dr_internode_max / float(Ndiv_internode_length);
+
962
+
963 parent_shoot->curvature_perturbation += - 0.5f*parent_shoot->curvature_perturbation*dt + parent_shoot_parameters.tortuosity.val()*context_ptr->randn()*sqrt(dt);
+
964 float curvature_angle = deg2rad((parent_shoot->gravitropic_curvature*current_curvature_fact * dr_internode_max + parent_shoot->curvature_perturbation));
+
965 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, shoot_bending_axis, curvature_angle);
+
966
+
967 parent_shoot->yaw_perturbation += - 0.5f*parent_shoot->yaw_perturbation*dt + parent_shoot_parameters.tortuosity.val()*context_ptr->randn()*sqrt(dt);
+
968 float yaw_angle = deg2rad((parent_shoot->yaw_perturbation));
+
969 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, make_vec3(0,0,1), yaw_angle);
+
970 }
+
971
+
972 phytomer_internode_vertices.at(inode_segment) = phytomer_internode_vertices.at(inode_segment - 1) + dr_internode * internode_axis;
+
973
+
974 phytomer_internode_radii.at(inode_segment) = internode_radius;
+
975 internode_colors.at(inode_segment) = phytomer_parameters.internode.color;
+
976
+
977 }
+
978
+
979 if( shoot_index.x==0 ) { //first phytomer on shoot
+
980 parent_shoot_ptr->shoot_internode_vertices.push_back(phytomer_internode_vertices);
+
981 parent_shoot_ptr->shoot_internode_radii.push_back(phytomer_internode_radii);
+
982 }else{ //if not the first phytomer on shoot, don't insert the first node because it's already defined on the previous phytomer
+
983 parent_shoot_ptr->shoot_internode_vertices.emplace_back(phytomer_internode_vertices.begin()+1,phytomer_internode_vertices.end());
+
984 parent_shoot_ptr->shoot_internode_radii.emplace_back(phytomer_internode_radii.begin()+1,phytomer_internode_radii.end());
+
985 }
+
986
+
987 //build internode context geometry
+
988 if( build_context_geometry_internode ) {
+
989
+
990 //calculate texture coordinates
+
991 float texture_repeat_length = 0.25f; //meters
+
992 float length=0; //shoot length prior to this phytomer
+
993 for(auto & phytomer : parent_shoot_ptr->phytomers){
+
994 length += phytomer->internode_length_max;
+
995 }
+
996 std::vector<float> uv_y(phytomer_internode_vertices.size());
+
997 float dy = internode_length_max/float(uv_y.size()-1);
+
998 for( int j=0; j<uv_y.size(); j++ ){
+
999 uv_y.at(j) = (length+j*dy)/texture_repeat_length - std::floor((length+j*dy)/texture_repeat_length);
+
1000 }
+
1001
+
1002 if( !context_ptr->doesObjectExist(parent_shoot->internode_tube_objID) ){ //first internode on shoot
+
1003 if( !phytomer_parameters.internode.image_texture.empty() ){
+
1004 parent_shoot->internode_tube_objID = context_ptr->addTubeObject(Ndiv_internode_radius, phytomer_internode_vertices, phytomer_internode_radii, phytomer_parameters.internode.image_texture.c_str(), uv_y);
+
1005 }else {
+
1006 parent_shoot->internode_tube_objID = context_ptr->addTubeObject(Ndiv_internode_radius, phytomer_internode_vertices, phytomer_internode_radii, internode_colors);
+
1007 }
+
1008 }else{ //appending internode to shoot
+
1009 for (int inode_segment = 1; inode_segment <= Ndiv_internode_length; inode_segment++) {
+
1010 if( !phytomer_parameters.internode.image_texture.empty() ) {
+
1011 context_ptr->appendTubeSegment(parent_shoot->internode_tube_objID, phytomer_internode_vertices.at(inode_segment), phytomer_internode_radii.at(inode_segment), phytomer_parameters.internode.image_texture.c_str(), {uv_y.at(inode_segment-1), uv_y.at(inode_segment)});
+
1012 }else {
+
1013 context_ptr->appendTubeSegment(parent_shoot->internode_tube_objID, phytomer_internode_vertices.at(inode_segment), phytomer_internode_radii.at(inode_segment), internode_colors.at(inode_segment));
+
1014 }
+
1015 }
+
1016 }
+
1017 }
+
1018
+
1019 //--- create petiole ---//
+
1020
+
1021 vec3 petiole_axis = internode_axis;
+
1022
+
1023 //petiole pitch rotation
+
1024 petiole_pitch = deg2rad(phytomer_parameters.petiole.pitch.val());
+
1025 phytomer_parameters.petiole.pitch.resample();
+
1026 if( fabs(petiole_pitch)<deg2rad(5.f) ) {
+
1027 petiole_pitch = deg2rad(5.f);
+
1028 }
+
1029 petiole_axis = rotatePointAboutLine(petiole_axis, nullorigin, petiole_rotation_axis, std::abs(petiole_pitch) );
+
1030
+
1031 //petiole yaw rotation
+
1032 if( phytomer_index!=0 && internode_phyllotactic_angle!=0 ){ //not first phytomer along shoot
+
1033 petiole_axis = rotatePointAboutLine(petiole_axis, nullorigin, internode_axis, internode_phyllotactic_angle );
+
1034 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, internode_axis, internode_phyllotactic_angle );
+
1035 }
+
1036
+
1037 //petiole curvature
+
1038 petiole_curvature = phytomer_parameters.petiole.curvature.val();
+
1039 phytomer_parameters.petiole.curvature.resample();
+
1040
+
1041 for(int petiole=0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++ ) { //looping over petioles
+
1042
+
1043 vec3 petiole_rotation_axis_actual = petiole_rotation_axis;
+
1044 vec3 petiole_axis_actual = petiole_axis;
+
1045
+
1046 if( petiole > 0 ) {
+
1047 float budrot = float(petiole) * 2.f * M_PI / float(phytomer_parameters.petiole.petioles_per_internode);
+
1048 petiole_axis_actual = rotatePointAboutLine(petiole_axis_actual, nullorigin, internode_axis, budrot );
+
1049 petiole_rotation_axis_actual = rotatePointAboutLine(petiole_rotation_axis_actual, nullorigin, internode_axis, budrot );
+
1050 }
+
1051
+
1052 petiole_vertices.at(petiole).at(0) = phytomer_internode_vertices.back();
+
1053
+
1054 for (int j = 1; j <= Ndiv_petiole_length; j++) {
+
1055
+
1056 if( fabs(petiole_curvature)>0 ) {
+
1057 petiole_axis_actual = rotatePointAboutLine(petiole_axis_actual, nullorigin, petiole_rotation_axis_actual, -deg2rad(petiole_curvature * dr_petiole_max.at(petiole)));
+
1058 }
+
1059
+
1060 petiole_vertices.at(petiole).at(j) = petiole_vertices.at(petiole).at(j - 1) + dr_petiole.at(petiole) * petiole_axis_actual;
+
1061
+
1062 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) );
+
1063 petiole_colors.at(j) = phytomer_parameters.petiole.color;
+
1064
+
1065 }
+
1066
+
1067 if( build_context_geometry_petiole && petiole_radii.at(petiole).front() > 0.f ) {
+
1068 petiole_objIDs.at(petiole) = makeTubeFromCones(Ndiv_petiole_radius, petiole_vertices.at(petiole), petiole_radii.at(petiole), petiole_colors, context_ptr);
+
1069 }
+
1070
+
1071 //--- create buds ---//
+
1072
+
1073 std::vector<VegetativeBud> vegetative_buds_new;
+
1074 vegetative_buds_new.resize( phytomer_parameters.internode.max_vegetative_buds_per_petiole.val() );
+
1075 phytomer_parameters.internode.max_vegetative_buds_per_petiole.resample();
+
1076
+
1077 axillary_vegetative_buds.push_back(vegetative_buds_new);
+
1078
+
1079 std::vector<FloralBud> floral_buds_new;
+
1080 floral_buds_new.resize( phytomer_parameters.internode.max_floral_buds_per_petiole.val() );
+
1081 phytomer_parameters.internode.max_floral_buds_per_petiole.resample();
+
1082
+
1083 uint index = 0;
+
1084 for( auto &fbud : floral_buds_new ){
+
1085 fbud.bud_index = index;
+
1086 fbud.parent_index = petiole;
+
1087 float pitch_adjustment = fbud.bud_index * 0.1f * M_PI / float(axillary_vegetative_buds.size());
+
1088 float yaw_adjustment = -0.25f * M_PI + fbud.bud_index * 0.5f * M_PI / float(axillary_vegetative_buds.size());
+
1089 fbud.base_rotation = make_AxisRotation(pitch_adjustment, yaw_adjustment, 0);
+
1090 fbud.base_position = phytomer_internode_vertices.back();
+
1091 fbud.bending_axis = shoot_bending_axis;
+
1092 index++;
+
1093 }
+
1094
+
1095 floral_buds.push_back(floral_buds_new);
+
1096
+
1097 //--- create leaves ---//
+
1098
+
1099 if(phytomer_parameters.leaf.prototype_function == nullptr ){
+
1100 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Leaf prototype function was not defined for shoot type " + parent_shoot->shoot_type_label + ".");
+
1101 }
+
1102
+
1103 vec3 petiole_tip_axis = getPetioleAxisVector(1.f, petiole);
+
1104
+
1105 vec3 leaf_rotation_axis = cross(internode_axis, petiole_tip_axis );
+
1106
+
1107 // Create unique leaf prototypes for each shoot type so we can simply copy them for each leaf
+
1108 if( phytomer_parameters.leaf.unique_prototypes>0 && plantarchitecture_ptr->unique_leaf_prototype_objIDs.find(parent_shoot->shoot_type_label) == plantarchitecture_ptr->unique_leaf_prototype_objIDs.end() ) {
+
1109 plantarchitecture_ptr->unique_leaf_prototype_objIDs[parent_shoot->shoot_type_label].resize(phytomer_parameters.leaf.unique_prototypes);
+
1110 for( int prototype = 0; prototype < phytomer_parameters.leaf.unique_prototypes; prototype++ ) {
+
1111 for (int leaf = 0; leaf < leaves_per_petiole; leaf++) {
+
1112 float ind_from_tip = float(leaf) - float(leaves_per_petiole - 1) / 2.f;
+
1113 uint objID_leaf = phytomer_parameters.leaf.prototype_function(context_ptr, phytomer_parameters.leaf.subdivisions, ind_from_tip);
+
1114 plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(parent_shoot->shoot_type_label).at(prototype).push_back(objID_leaf);
+
1115 std::vector<uint> petiolule_UUIDs = context_ptr->filterPrimitivesByData( context_ptr->getObjectPrimitiveUUIDs(objID_leaf), "object_label", "petiolule" );
+
1116 context_ptr->setPrimitiveColor( petiolule_UUIDs, phytomer_parameters.petiole.color );
+
1117 context_ptr->hideObject({objID_leaf});
+
1118 }
+
1119 }
+
1120 }
+
1121
+
1122 for(int leaf=0; leaf < leaves_per_petiole; leaf++ ){
+
1123
+
1124 float ind_from_tip = float(leaf)-float(leaves_per_petiole-1)/2.f;
+
1125
+
1126 uint objID_leaf;
+
1127 if( phytomer_parameters.leaf.unique_prototypes>0 ) { //copy the existing prototype
+
1128 int prototype = context_ptr->randu(0, phytomer_parameters.leaf.unique_prototypes - 1);
+
1129 objID_leaf = context_ptr->copyObject(plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(parent_shoot->shoot_type_label).at(prototype).at(leaf));
+
1130 }else{ //load a new prototype
+
1131 objID_leaf = phytomer_parameters.leaf.prototype_function(context_ptr, phytomer_parameters.leaf.subdivisions, ind_from_tip);
+
1132 }
+
1133
+
1134 // -- leaf scaling -- //
+
1135
+
1136 if( leaves_per_petiole>0 && phytomer_parameters.leaf.leaflet_scale.val()!=1.f && ind_from_tip!=0 ){
+
1137 leaf_size_max.at(petiole).at(leaf) = powf(phytomer_parameters.leaf.leaflet_scale.val(),fabs(ind_from_tip))*phytomer_parameters.leaf.prototype_scale.val();
+
1138 }else{
+
1139 leaf_size_max.at(petiole).at(leaf) = phytomer_parameters.leaf.prototype_scale.val();
+
1140 }
+
1141 vec3 leaf_scale = leaf_scale_factor_fraction * leaf_size_max.at(petiole).at(leaf) * make_vec3(1,1,1);
+
1142
+
1143 context_ptr->scaleObject( objID_leaf, leaf_scale );
+
1144
+
1145 float compound_rotation = 0;
+
1146 if( leaves_per_petiole>1 ) {
+
1147 if (phytomer_parameters.leaf.leaflet_offset.val() == 0) {
+
1148 float dphi = M_PI / (floor(0.5 * float(leaves_per_petiole - 1)) + 1);
+
1149 compound_rotation = -float(M_PI) + dphi * (leaf + 0.5f);
+
1150 } else {
+
1151 if( leaf == float(leaves_per_petiole-1)/2.f ){ //tip leaf
+
1152 compound_rotation = 0;
+
1153 }else if( leaf < float(leaves_per_petiole-1)/2.f ) {
+
1154 compound_rotation = -0.5*M_PI;
+
1155 }else{
+
1156 compound_rotation = 0.5*M_PI;
+
1157 }
+
1158 }
+
1159 }
+
1160
+
1161 // -- leaf rotations -- //
+
1162
+
1163 //leaf roll rotation
+
1164 float roll_rot = 0;
+
1165 if( leaves_per_petiole==1 ){
+
1166 int sign = (shoot_index.x%2==0) ? 1 : -1;
+
1167 roll_rot = (acos_safe(internode_axis.z)-deg2rad(phytomer_parameters.leaf.roll.val()))*sign;
+
1168 } else if( ind_from_tip!= 0){
+
1169 roll_rot = (asin_safe(petiole_tip_axis.z)+deg2rad(phytomer_parameters.leaf.roll.val()))*compound_rotation/std::fabs(compound_rotation);
+
1170 }
+
1171 leaf_rotation.at(petiole).at(leaf).roll = deg2rad(phytomer_parameters.leaf.roll.val());
+
1172 phytomer_parameters.leaf.roll.resample();
+
1173 context_ptr->rotateObject(objID_leaf, roll_rot, "x" );
+
1174
+
1175 //leaf pitch rotation
+
1176 leaf_rotation.at(petiole).at(leaf).pitch = deg2rad(phytomer_parameters.leaf.pitch.val());
+
1177 float pitch_rot = leaf_rotation.at(petiole).at(leaf).pitch;
+
1178 phytomer_parameters.leaf.pitch.resample();
+
1179 if( ind_from_tip==0 ){
+
1180 pitch_rot += asin_safe(petiole_tip_axis.z);
+
1181 }
+
1182 context_ptr->rotateObject(objID_leaf, -pitch_rot , "y" );
+
1183
+
1184 //leaf yaw rotation
+
1185 if( ind_from_tip!=0 ){
+
1186 float sign = -compound_rotation/fabs(compound_rotation);
+
1187 leaf_rotation.at(petiole).at(leaf).yaw = sign*deg2rad(phytomer_parameters.leaf.yaw.val());
+
1188 float yaw_rot = leaf_rotation.at(petiole).at(leaf).yaw;
+
1189 phytomer_parameters.leaf.yaw.resample();
+
1190 context_ptr->rotateObject( objID_leaf, yaw_rot, "z" );
+
1191 }else{
+
1192 leaf_rotation.at(petiole).at(leaf).yaw = 0;
+
1193 }
+
1194
+
1195 //rotate leaf to azimuth of petiole
+
1196 context_ptr->rotateObject( objID_leaf, -std::atan2(petiole_tip_axis.y, petiole_tip_axis.x)+compound_rotation, "z" );
1197
-
1198 // -- leaf translation -- //
-
1199
-
1200 vec3 leaf_base = petiole_vertices.at(petiole).back();
-
1201 if( leaves_per_petiole>1 && phytomer_parameters.leaf.leaflet_offset.val()>0 ){
-
1202 if( ind_from_tip != 0 ) {
-
1203 float offset = (fabs(ind_from_tip) - 0.5f) * phytomer_parameters.leaf.leaflet_offset.val() * phytomer_parameters.petiole.length.val();
-
1204 leaf_base = interpolateTube(petiole_vertices.at(petiole), 1.f - offset / phytomer_parameters.petiole.length.val() );
-
1205 }
-
1206 }
-
1207
-
1208 context_ptr->translateObject( objID_leaf, leaf_base );
-
1209
-
1210 leaf_objIDs.at(petiole).push_back(objID_leaf );
-
1211 leaf_bases.at(petiole).push_back(leaf_base );
-
1212
-
1213 }
-
1214 phytomer_parameters.leaf.prototype_scale.resample();
-
1215
-
1216 if( petiole_axis_actual==make_vec3(0,0,1) ) {
-
1217 inflorescence_bending_axis = make_vec3(1, 0, 0);
-
1218 }else{
-
1219 inflorescence_bending_axis = cross(make_vec3(0, 0, 1), petiole_axis_actual);
-
1220 }
-
1221
-
1222 }
-
1223
-
1224}
-
1225
-
1226void Phytomer::updateInflorescence(FloralBud &fbud) {
-
1227
-
1228 bool build_context_geometry_peduncle = plantarchitecture_ptr->build_context_geometry_peduncle;
-
1229
-
1230 uint Ndiv_peduncle_length = std::max(uint(1), phytomer_parameters.peduncle.length_segments);
-
1231 uint Ndiv_peduncle_radius = std::max(uint(3), phytomer_parameters.peduncle.radial_subdivisions);
-
1232 if( phytomer_parameters.peduncle.length_segments==0 || phytomer_parameters.peduncle.radial_subdivisions<3 ){
-
1233 build_context_geometry_peduncle = false;
-
1234 }
-
1235
-
1236 float dr_peduncle = phytomer_parameters.peduncle.length.val() / float(Ndiv_peduncle_length);
-
1237 phytomer_parameters.peduncle.length.resample();
-
1238
-
1239 std::vector<vec3> peduncle_vertices(phytomer_parameters.peduncle.length_segments + 1);
-
1240 peduncle_vertices.at(0) = fbud.base_position;
-
1241 std::vector<float> peduncle_radii(phytomer_parameters.peduncle.length_segments + 1);
-
1242 peduncle_radii.at(0) = phytomer_parameters.peduncle.radius.val();
-
1243 std::vector<RGBcolor> peduncle_colors(phytomer_parameters.peduncle.length_segments + 1);
-
1244 peduncle_colors.at(0) = phytomer_parameters.peduncle.color;
-
1245
-
1246 vec3 peduncle_axis = getAxisVector(1.f, getInternodeNodePositions() );
-
1247
-
1248 //peduncle pitch rotation
-
1249 if( phytomer_parameters.peduncle.pitch.val()!=0.f || fbud.base_rotation.pitch!=0.f ) {
-
1250 peduncle_axis = rotatePointAboutLine(peduncle_axis, nullorigin, inflorescence_bending_axis, deg2rad(phytomer_parameters.peduncle.pitch.val())+fbud.base_rotation.pitch );
-
1251 phytomer_parameters.peduncle.pitch.resample();
-
1252 }
-
1253
-
1254 //rotate peduncle to azimuth of petiole and apply peduncle base yaw rotation
-
1255 vec3 internode_axis = getAxisVector(1.f, getInternodeNodePositions() );
-
1256 vec3 parent_petiole_base_axis = getPetioleAxisVector(0.f, fbud.parent_index);
-
1257 float parent_petiole_azimuth = -std::atan2(parent_petiole_base_axis.y, parent_petiole_base_axis.x);
-
1258 float current_peduncle_azimuth = -std::atan2(peduncle_axis.y, peduncle_axis.x);
-
1259 peduncle_axis = rotatePointAboutLine( peduncle_axis, nullorigin, internode_axis, (current_peduncle_azimuth-parent_petiole_azimuth) + fbud.base_rotation.yaw );
-
1260
-
1261 float theta_base = fabs(cart2sphere(peduncle_axis).zenith);
-
1262
-
1263 for(int i=1; i<=phytomer_parameters.peduncle.length_segments; i++ ){
-
1264
-
1265 if( phytomer_parameters.peduncle.curvature.val()!=0.f ) {
-
1266 float theta_curvature = -deg2rad(phytomer_parameters.peduncle.curvature.val() * dr_peduncle);
-
1267 phytomer_parameters.peduncle.curvature.resample();
-
1268 if (fabs(theta_curvature) * float(i) < M_PI - theta_base) {
-
1269 peduncle_axis = rotatePointAboutLine(peduncle_axis, nullorigin, inflorescence_bending_axis, theta_curvature);
-
1270 } else {
-
1271 peduncle_axis = make_vec3(0, 0, -1);
-
1272 }
-
1273 }
-
1274
-
1275 peduncle_vertices.at(i) = peduncle_vertices.at(i - 1) + dr_peduncle * peduncle_axis;
-
1276
-
1277 peduncle_radii.at(i) = phytomer_parameters.peduncle.radius.val();
-
1278 peduncle_colors.at(i) = phytomer_parameters.peduncle.color;
-
1279
-
1280 }
-
1281 phytomer_parameters.peduncle.radius.resample();
-
1282
-
1283 if( build_context_geometry_peduncle) {
-
1284 fbud.peduncle_objIDs.push_back(context_ptr->addTubeObject(Ndiv_peduncle_radius, peduncle_vertices, peduncle_radii, peduncle_colors));
-
1285 }
-
1286
-
1287 // Create unique inflorescence prototypes for each shoot type so we can simply copy them for each leaf
-
1288 std::string parent_shoot_type_label = plantarchitecture_ptr->plant_instances.at(this->plantID).shoot_tree.at(parent_shoot_ID)->shoot_type_label;
-
1289 if( phytomer_parameters.inflorescence.unique_prototypes>0 ){
-
1290 //closed flowers
-
1291 if( phytomer_parameters.inflorescence.flower_prototype_function!= nullptr && plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.find(parent_shoot_type_label) == plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.end() ) {
-
1292 plantarchitecture_ptr->unique_closed_flower_prototype_objIDs[parent_shoot_type_label].resize(phytomer_parameters.inflorescence.unique_prototypes);
-
1293 for( int prototype = 0; prototype < phytomer_parameters.inflorescence.unique_prototypes; prototype++ ) {
-
1294 uint objID_flower = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, false);
-
1295 plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.at(parent_shoot_type_label).at(prototype) = objID_flower;
-
1296 context_ptr->hideObject({objID_flower});
-
1297 }
-
1298 }
-
1299 //open flowers
-
1300 if( phytomer_parameters.inflorescence.flower_prototype_function!= nullptr && plantarchitecture_ptr->unique_open_flower_prototype_objIDs.find(parent_shoot_type_label) == plantarchitecture_ptr->unique_open_flower_prototype_objIDs.end() ) {
-
1301 plantarchitecture_ptr->unique_open_flower_prototype_objIDs[parent_shoot_type_label].resize(phytomer_parameters.inflorescence.unique_prototypes);
-
1302 for( int prototype = 0; prototype < phytomer_parameters.inflorescence.unique_prototypes; prototype++ ) {
-
1303 uint objID_flower = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, false);
-
1304 plantarchitecture_ptr->unique_open_flower_prototype_objIDs.at(parent_shoot_type_label).at(prototype) = objID_flower;
-
1305 context_ptr->hideObject({objID_flower});
-
1306 }
-
1307 }
-
1308 //fruit
-
1309 if( phytomer_parameters.inflorescence.fruit_prototype_function!= nullptr && plantarchitecture_ptr->unique_fruit_prototype_objIDs.find(parent_shoot_type_label) == plantarchitecture_ptr->unique_fruit_prototype_objIDs.end() ) {
-
1310 plantarchitecture_ptr->unique_fruit_prototype_objIDs[parent_shoot_type_label].resize(phytomer_parameters.inflorescence.unique_prototypes);
-
1311 for( int prototype = 0; prototype < phytomer_parameters.inflorescence.unique_prototypes; prototype++ ) {
-
1312 uint objID_fruit = phytomer_parameters.inflorescence.fruit_prototype_function(context_ptr, 1, false);
-
1313 plantarchitecture_ptr->unique_fruit_prototype_objIDs.at(parent_shoot_type_label).at(prototype) = objID_fruit;
-
1314 context_ptr->hideObject({objID_fruit});
-
1315 }
-
1316 }
-
1317 }
-
1318
-
1319 for(int fruit=0; fruit < phytomer_parameters.inflorescence.flowers_per_peduncle.val(); fruit++ ){
-
1320
-
1321 uint objID_fruit;
-
1322 helios::vec3 fruit_scale;
-
1323
-
1324 if(fbud.state == BUD_FRUITING ){
-
1325 if( phytomer_parameters.inflorescence.unique_prototypes>0 ) { //copy existing prototype
-
1326 int prototype = context_ptr->randu(0, int(phytomer_parameters.inflorescence.unique_prototypes - 1));
-
1327 objID_fruit = context_ptr->copyObject(plantarchitecture_ptr->unique_fruit_prototype_objIDs.at(parent_shoot_type_label).at(prototype));
-
1328 }else{ //load new prototype
-
1329 objID_fruit = phytomer_parameters.inflorescence.fruit_prototype_function(context_ptr, 1, fbud.time_counter);
-
1330 }
-
1331 fruit_scale = phytomer_parameters.inflorescence.fruit_prototype_scale.val()*make_vec3(1,1,1);
-
1332 phytomer_parameters.inflorescence.fruit_prototype_scale.resample();
-
1333 }else{
-
1334 bool flower_is_open;
-
1335 if(fbud.state == BUD_FLOWER_CLOSED ) {
-
1336 flower_is_open = false;
-
1337 if( phytomer_parameters.inflorescence.unique_prototypes>0 ) { //copy existing prototype
-
1338 int prototype = context_ptr->randu(0, int(phytomer_parameters.inflorescence.unique_prototypes - 1));
-
1339 objID_fruit = context_ptr->copyObject(plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.at(parent_shoot_type_label).at(prototype));
-
1340 }else{ //load new prototype
-
1341 objID_fruit = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, flower_is_open);
-
1342 }
-
1343 }else{
-
1344 flower_is_open = true;
-
1345 if( phytomer_parameters.inflorescence.unique_prototypes>0 ) { //copy existing prototype
-
1346 int prototype = context_ptr->randu(0, int(phytomer_parameters.inflorescence.unique_prototypes - 1));
-
1347 objID_fruit = context_ptr->copyObject(plantarchitecture_ptr->unique_open_flower_prototype_objIDs.at(parent_shoot_type_label).at(prototype));
-
1348 }else{ //load new prototype
-
1349 objID_fruit = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, flower_is_open);
-
1350 }
-
1351 }
-
1352 fruit_scale = phytomer_parameters.inflorescence.flower_prototype_scale.val()*make_vec3(1,1,1);
-
1353 phytomer_parameters.inflorescence.flower_prototype_scale.resample();
-
1354 }
-
1355
-
1356 float ind_from_tip = fabs(fruit - float(phytomer_parameters.inflorescence.flowers_per_peduncle.val() - 1) / float(phytomer_parameters.petiole.petioles_per_internode));
-
1357
-
1358 context_ptr->scaleObject( objID_fruit, fruit_scale );
-
1359
-
1360 //if we have more than one flower/fruit, we need to adjust the base position of the fruit
-
1361 vec3 fruit_base = peduncle_vertices.back();
-
1362 float frac = 1;
-
1363 if(phytomer_parameters.inflorescence.flowers_per_peduncle.val() > 1 && phytomer_parameters.inflorescence.flower_offset.val() > 0 ){
-
1364 if( ind_from_tip != 0 ) {
-
1365 float offset = offset = (ind_from_tip - 0.5f) * phytomer_parameters.inflorescence.flower_offset.val() * phytomer_parameters.peduncle.length.val();
-
1366 if( phytomer_parameters.peduncle.length.val()>0 ){
-
1367 frac = 1.f - offset / phytomer_parameters.peduncle.length.val();
-
1368 }
-
1369 fruit_base = interpolateTube(peduncle_vertices, frac);
-
1370 }
-
1371 }
-
1372
-
1373 //if we have more than one flower/fruit, we need to adjust the rotation about the peduncle
-
1374 float compound_rotation = 0;
-
1375 if(phytomer_parameters.inflorescence.flowers_per_peduncle.val() > 1 ) {
-
1376 if (phytomer_parameters.inflorescence.flower_offset.val() == 0) { //flowers/fruit are all at the tip, so just equally distribute them about the azimuth
-
1377 float dphi = M_PI / (floor(0.5 * float(phytomer_parameters.inflorescence.flowers_per_peduncle.val() - 1)) + 1);
-
1378 compound_rotation = -float(M_PI) + dphi * (fruit + 0.5f);
-
1379 } else {
-
1380 compound_rotation = deg2rad(phytomer_parameters.internode.phyllotactic_angle.val())*float(ind_from_tip) + 2.f*M_PI/float(phytomer_parameters.petiole.petioles_per_internode)*float(fruit);
-
1381 phytomer_parameters.internode.phyllotactic_angle.resample();
-
1382 }
-
1383 }
-
1384
-
1385 peduncle_axis = getAxisVector(frac, peduncle_vertices );
-
1386
-
1387 vec3 fruit_axis = peduncle_axis;
-
1388
-
1389 //roll rotation
-
1390 if( phytomer_parameters.inflorescence.roll.val()!=0.f ) {
-
1391 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.inflorescence.roll.val()), "x" );
-
1392 phytomer_parameters.inflorescence.roll.resample();
-
1393 }
-
1394
-
1395 //pitch rotation
-
1396 float pitch_inflorescence = -asin_safe(peduncle_axis.z) + deg2rad(phytomer_parameters.inflorescence.pitch.val());
-
1397 phytomer_parameters.inflorescence.pitch.resample();
-
1398 if(fbud.state == BUD_FRUITING ) { //gravity effect for fruit
-
1399 pitch_inflorescence = pitch_inflorescence + phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.val() * (0.5f * M_PI - pitch_inflorescence);
-
1400 }
-
1401 context_ptr->rotateObject(objID_fruit, pitch_inflorescence, "y");
-
1402 fruit_axis = rotatePointAboutLine(fruit_axis, nullorigin, make_vec3(1, 0, 0), pitch_inflorescence);
-
1403
-
1404 //rotate flower/fruit to azimuth of peduncle
-
1405 context_ptr->rotateObject(objID_fruit, -std::atan2(peduncle_axis.y, peduncle_axis.x), "z" );
-
1406 fruit_axis = rotatePointAboutLine( fruit_axis, nullorigin, make_vec3(0,0,1), -std::atan2(peduncle_axis.y, peduncle_axis.x) );
-
1407
-
1408 context_ptr->translateObject( objID_fruit, fruit_base );
-
1409
-
1410 //rotate flower/fruit about peduncle (roll)
-
1411 if( phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.val()!=0 && fbud.state == BUD_FRUITING ) {
-
1412 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation, fruit_base, make_vec3(0, 0, 1));
-
1413 }else{
-
1414 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation, fruit_base, peduncle_axis);
-
1415 fruit_axis = rotatePointAboutLine(fruit_axis, nullorigin, peduncle_axis, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation);
-
1416 }
-
1417 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.resample();
-
1418
-
1419 fbud.inflorescence_bases.push_back(fruit_base );
-
1420
-
1421 fbud.inflorescence_objIDs.push_back(objID_fruit );
-
1422
-
1423 }
-
1424 phytomer_parameters.inflorescence.flowers_per_peduncle.resample();
-
1425 phytomer_parameters.peduncle.roll.resample();
-
1426
-
1427 if( plantarchitecture_ptr->output_object_data.at("rank") ) {
-
1428 context_ptr->setObjectData(fbud.peduncle_objIDs, "rank", rank );
-
1429 context_ptr->setObjectData(fbud.inflorescence_objIDs, "rank", rank );
-
1430 }
-
1431
-
1432 if( plantarchitecture_ptr->output_object_data.at("peduncleID") ) {
-
1433 for (uint objID: fbud.peduncle_objIDs) {
-
1434 context_ptr->setObjectData(objID, "peduncleID", (int) objID);
-
1435 }
-
1436 }
-
1437 for( uint objID : fbud.inflorescence_objIDs ) {
-
1438 if( fbud.state == BUD_FLOWER_CLOSED && plantarchitecture_ptr->output_object_data.at("closedflowerID") ) {
-
1439 context_ptr->setObjectData( objID, "closedflowerID", (int) objID);
-
1440 }else if( fbud.state == BUD_FLOWER_OPEN && plantarchitecture_ptr->output_object_data.at("openflowerID") ) {
-
1441 context_ptr->clearObjectData( objID, "closedflowerID" );
-
1442 context_ptr->setObjectData( objID, "openflowerID", (int) objID);
-
1443 }else if( plantarchitecture_ptr->output_object_data.at("fruitID") ){
-
1444 context_ptr->setObjectData( objID, "fruitID", (int) objID);
-
1445 }
-
1446 }
-
1447
-
1448}
-
1449
-
1450void Phytomer::setPetioleBase( const helios::vec3 &base_position ){
-
1451
-
1452 vec3 old_base = petiole_vertices.front().front();
-
1453 vec3 shift = base_position - old_base;
-
1454
-
1455 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
-
1456 for (auto &vertex: petiole_vertices.at(petiole) ) {
-
1457 vertex += shift;
-
1458 }
-
1459 }
-
1460
-
1461 if( build_context_geometry_petiole ) {
-
1462 context_ptr->translateObject(flatten(petiole_objIDs), shift);
-
1463 }
-
1464 context_ptr->translateObject( flatten(leaf_objIDs), shift );
-
1465
-
1466 for( int petiole=0; petiole<leaf_bases.size(); petiole++ ) {
-
1467 for (auto &leaf_base: leaf_bases.at(petiole)) {
-
1468 leaf_base += shift;
-
1469 }
-
1470 for ( auto &fbud : floral_buds.at(petiole) ) {
-
1471 assert( !fbud.isterminal );
-
1472 fbud.base_position = petiole_vertices.at(petiole).front();
-
1473 context_ptr->translateObject( fbud.inflorescence_objIDs, shift);
-
1474 for( auto &base : fbud.inflorescence_bases ) {
-
1475 base += shift;
-
1476 }
-
1477 if( build_context_geometry_peduncle ) {
-
1478 context_ptr->translateObject( fbud.peduncle_objIDs, shift);
-
1479 }
-
1480 }
-
1481 }
-
1482
-
1483}
-
1484
-
1485void Phytomer::rotateLeaf( uint petiole_index, uint leaf_index, const AxisRotation &rotation ){
-
1486
-
1487 if( petiole_index>=leaf_objIDs.size() ){
-
1488 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Invalid petiole index.");
-
1489 }else if( leaf_index>=leaf_objIDs.at(petiole_index).size() ){
-
1490 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Invalid leaf index.");
-
1491 }
-
1492
-
1493 vec3 petiole_axis = getPetioleAxisVector(1.f, petiole_index); //note: this is not exactly correct because it should get the axis at the leaf position and not the tip
-
1494
-
1495 vec3 internode_axis = getInternodeAxisVector(1.f);
-
1496
-
1497 vec3 pitch_axis = -1*cross( internode_axis, petiole_axis );
-
1498
-
1499 int leaves_per_petiole = leaf_rotation.at(petiole_index).size();
-
1500 float yaw;
-
1501 float roll;
-
1502 float compound_rotation = 0;
-
1503 if( leaf_index == float(leaves_per_petiole-1)/2.f ){ //tip leaf
-
1504 roll = 0;
-
1505 yaw = 0;
-
1506 compound_rotation = 0;
-
1507 }else if( leaf_index < float(leaves_per_petiole-1)/2.f ) {
-
1508 yaw = -rotation.yaw;
-
1509 roll = -rotation.roll;
-
1510 compound_rotation = -0.5*M_PI;
-
1511 }else{
-
1512 yaw = -rotation.yaw;
-
1513 roll = rotation.roll;
-
1514 compound_rotation = 0.5*M_PI;
-
1515 }
-
1516
-
1517 //roll
-
1518 if( roll!=0.f ) {
-
1519 vec3 roll_axis = rotatePointAboutLine({petiole_axis.x, petiole_axis.y, 0}, nullorigin, {0, 0, 1}, leaf_rotation.at(petiole_index).at(leaf_index).yaw + compound_rotation);
-
1520 context_ptr->rotateObject(leaf_objIDs.at(petiole_index).at(leaf_index), roll, leaf_bases.at(petiole_index).at(leaf_index), roll_axis);
-
1521 leaf_rotation.at(petiole_index).at(leaf_index).roll += roll;
-
1522 }
-
1523
-
1524 //pitch
-
1525 if( rotation.pitch!=0 ) {
-
1526 pitch_axis = rotatePointAboutLine(pitch_axis, nullorigin, {0, 0, 1}, -compound_rotation);
-
1527 context_ptr->rotateObject(leaf_objIDs.at(petiole_index).at(leaf_index), rotation.pitch, leaf_bases.at(petiole_index).at(leaf_index), pitch_axis);
-
1528 leaf_rotation.at(petiole_index).at(leaf_index).pitch += rotation.pitch;
-
1529 }
-
1530
-
1531 //yaw
-
1532 if( yaw!=0.f ) {
-
1533 context_ptr->rotateObject(leaf_objIDs.at(petiole_index).at(leaf_index), yaw, leaf_bases.at(petiole_index).at(leaf_index), {0, 0, 1});
-
1534 leaf_rotation.at(petiole_index).at(leaf_index).yaw += yaw;
-
1535 }
-
1536
-
1537}
-
1538
-
1539void Phytomer::setInternodeLengthScaleFraction(float internode_scale_factor_fraction, bool update_context_geometry) {
-
1540
-
1541 assert(internode_scale_factor_fraction >= 0 && internode_scale_factor_fraction <= 1 );
-
1542
-
1543 if(internode_scale_factor_fraction == current_internode_scale_factor ){
-
1544 return;
-
1545 }
-
1546
-
1547 float delta_scale = internode_scale_factor_fraction / current_internode_scale_factor;
-
1548
-
1549 float current_internode_length = getInternodeLength();
-
1550 float internode_length = current_internode_length*delta_scale;
-
1551 current_internode_scale_factor = internode_scale_factor_fraction;
-
1552
-
1553 int p = shoot_index.x;
-
1554 int s_start = (p == 0) ? 1 : 0; //skip the first node at the base of the shoot
-
1555
-
1556 for (int s = s_start; s < parent_shoot_ptr->shoot_internode_vertices.at(p).size(); s++) { //looping over all segments within this phytomer internode
-
1557
-
1558 int p_minus = p;
-
1559 int s_minus = s-1;
-
1560 if( s_minus<0 ){
-
1561 p_minus--;
-
1562 s_minus = int(parent_shoot_ptr->shoot_internode_vertices.at(p_minus).size()-1);
-
1563 }
-
1564
-
1565 vec3 central_axis = (parent_shoot_ptr->shoot_internode_vertices.at(p).at(s) - parent_shoot_ptr->shoot_internode_vertices.at(p_minus).at(s_minus));
-
1566 float current_length = central_axis.magnitude();
-
1567 central_axis = central_axis / current_length;
-
1568 vec3 dL = central_axis * current_length * (delta_scale - 1);
-
1569
-
1570 //apply shift to all downstream nodes
-
1571 for (int p_downstream = p; p_downstream < parent_shoot_ptr->shoot_internode_vertices.size(); p_downstream++) {
-
1572 int sd_start = ( p_downstream==p ) ? s : 0;
-
1573 for (int s_downstream = sd_start; s_downstream < parent_shoot_ptr->shoot_internode_vertices.at(p_downstream).size(); s_downstream++) {
-
1574 parent_shoot_ptr->shoot_internode_vertices.at(p_downstream).at(s_downstream) += dL;
-
1575 }
-
1576
-
1577 }
-
1578
-
1579 }
-
1580
-
1581 parent_shoot_ptr->updateShootNodes(update_context_geometry);
-
1582
+
1198
+
1199 // -- leaf translation -- //
+
1200
+
1201 vec3 leaf_base = petiole_vertices.at(petiole).back();
+
1202 if( leaves_per_petiole>1 && phytomer_parameters.leaf.leaflet_offset.val()>0 ){
+
1203 if( ind_from_tip != 0 ) {
+
1204 float offset = (fabs(ind_from_tip) - 0.5f) * phytomer_parameters.leaf.leaflet_offset.val() * phytomer_parameters.petiole.length.val();
+
1205 leaf_base = interpolateTube(petiole_vertices.at(petiole), 1.f - offset / phytomer_parameters.petiole.length.val() );
+
1206 }
+
1207 }
+
1208
+
1209 context_ptr->translateObject( objID_leaf, leaf_base );
+
1210
+
1211 leaf_objIDs.at(petiole).push_back(objID_leaf );
+
1212 leaf_bases.at(petiole).push_back(leaf_base );
+
1213
+
1214 }
+
1215 phytomer_parameters.leaf.prototype_scale.resample();
+
1216
+
1217 if( petiole_axis_actual==make_vec3(0,0,1) ) {
+
1218 inflorescence_bending_axis = make_vec3(1, 0, 0);
+
1219 }else{
+
1220 inflorescence_bending_axis = cross(make_vec3(0, 0, 1), petiole_axis_actual);
+
1221 }
+
1222
+
1223 }
+
1224
+
1225}
+
1226
+
1227void Phytomer::updateInflorescence(FloralBud &fbud) {
+
1228
+
1229 bool build_context_geometry_peduncle = plantarchitecture_ptr->build_context_geometry_peduncle;
+
1230
+
1231 uint Ndiv_peduncle_length = std::max(uint(1), phytomer_parameters.peduncle.length_segments);
+
1232 uint Ndiv_peduncle_radius = std::max(uint(3), phytomer_parameters.peduncle.radial_subdivisions);
+
1233 if( phytomer_parameters.peduncle.length_segments==0 || phytomer_parameters.peduncle.radial_subdivisions<3 ){
+
1234 build_context_geometry_peduncle = false;
+
1235 }
+
1236
+
1237 float dr_peduncle = phytomer_parameters.peduncle.length.val() / float(Ndiv_peduncle_length);
+
1238 phytomer_parameters.peduncle.length.resample();
+
1239
+
1240 std::vector<vec3> peduncle_vertices(phytomer_parameters.peduncle.length_segments + 1);
+
1241 peduncle_vertices.at(0) = fbud.base_position;
+
1242 std::vector<float> peduncle_radii(phytomer_parameters.peduncle.length_segments + 1);
+
1243 peduncle_radii.at(0) = phytomer_parameters.peduncle.radius.val();
+
1244 std::vector<RGBcolor> peduncle_colors(phytomer_parameters.peduncle.length_segments + 1);
+
1245 peduncle_colors.at(0) = phytomer_parameters.peduncle.color;
+
1246
+
1247 vec3 peduncle_axis = getAxisVector(1.f, getInternodeNodePositions() );
+
1248
+
1249 //peduncle pitch rotation
+
1250 if( phytomer_parameters.peduncle.pitch.val()!=0.f || fbud.base_rotation.pitch!=0.f ) {
+
1251 peduncle_axis = rotatePointAboutLine(peduncle_axis, nullorigin, inflorescence_bending_axis, deg2rad(phytomer_parameters.peduncle.pitch.val())+fbud.base_rotation.pitch );
+
1252 phytomer_parameters.peduncle.pitch.resample();
+
1253 }
+
1254
+
1255 //rotate peduncle to azimuth of petiole and apply peduncle base yaw rotation
+
1256 vec3 internode_axis = getAxisVector(1.f, getInternodeNodePositions() );
+
1257 vec3 parent_petiole_base_axis = getPetioleAxisVector(0.f, fbud.parent_index);
+
1258 float parent_petiole_azimuth = -std::atan2(parent_petiole_base_axis.y, parent_petiole_base_axis.x);
+
1259 float current_peduncle_azimuth = -std::atan2(peduncle_axis.y, peduncle_axis.x);
+
1260 peduncle_axis = rotatePointAboutLine( peduncle_axis, nullorigin, internode_axis, (current_peduncle_azimuth-parent_petiole_azimuth) + fbud.base_rotation.yaw );
+
1261
+
1262 float theta_base = fabs(cart2sphere(peduncle_axis).zenith);
+
1263
+
1264 for(int i=1; i<=phytomer_parameters.peduncle.length_segments; i++ ){
+
1265
+
1266 if( phytomer_parameters.peduncle.curvature.val()!=0.f ) {
+
1267 float theta_curvature = -deg2rad(phytomer_parameters.peduncle.curvature.val() * dr_peduncle);
+
1268 phytomer_parameters.peduncle.curvature.resample();
+
1269 if (fabs(theta_curvature) * float(i) < M_PI - theta_base) {
+
1270 peduncle_axis = rotatePointAboutLine(peduncle_axis, nullorigin, inflorescence_bending_axis, theta_curvature);
+
1271 } else {
+
1272 peduncle_axis = make_vec3(0, 0, -1);
+
1273 }
+
1274 }
+
1275
+
1276 peduncle_vertices.at(i) = peduncle_vertices.at(i - 1) + dr_peduncle * peduncle_axis;
+
1277
+
1278 peduncle_radii.at(i) = phytomer_parameters.peduncle.radius.val();
+
1279 peduncle_colors.at(i) = phytomer_parameters.peduncle.color;
+
1280
+
1281 }
+
1282 phytomer_parameters.peduncle.radius.resample();
+
1283
+
1284 if( build_context_geometry_peduncle) {
+
1285 fbud.peduncle_objIDs.push_back(context_ptr->addTubeObject(Ndiv_peduncle_radius, peduncle_vertices, peduncle_radii, peduncle_colors));
+
1286 }
+
1287
+
1288 // Create unique inflorescence prototypes for each shoot type so we can simply copy them for each leaf
+
1289 std::string parent_shoot_type_label = plantarchitecture_ptr->plant_instances.at(this->plantID).shoot_tree.at(parent_shoot_ID)->shoot_type_label;
+
1290 if( phytomer_parameters.inflorescence.unique_prototypes>0 ){
+
1291 //closed flowers
+
1292 if( phytomer_parameters.inflorescence.flower_prototype_function!= nullptr && plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.find(parent_shoot_type_label) == plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.end() ) {
+
1293 plantarchitecture_ptr->unique_closed_flower_prototype_objIDs[parent_shoot_type_label].resize(phytomer_parameters.inflorescence.unique_prototypes);
+
1294 for( int prototype = 0; prototype < phytomer_parameters.inflorescence.unique_prototypes; prototype++ ) {
+
1295 uint objID_flower = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, false);
+
1296 plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.at(parent_shoot_type_label).at(prototype) = objID_flower;
+
1297 context_ptr->hideObject({objID_flower});
+
1298 }
+
1299 }
+
1300 //open flowers
+
1301 if( phytomer_parameters.inflorescence.flower_prototype_function!= nullptr && plantarchitecture_ptr->unique_open_flower_prototype_objIDs.find(parent_shoot_type_label) == plantarchitecture_ptr->unique_open_flower_prototype_objIDs.end() ) {
+
1302 plantarchitecture_ptr->unique_open_flower_prototype_objIDs[parent_shoot_type_label].resize(phytomer_parameters.inflorescence.unique_prototypes);
+
1303 for( int prototype = 0; prototype < phytomer_parameters.inflorescence.unique_prototypes; prototype++ ) {
+
1304 uint objID_flower = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, false);
+
1305 plantarchitecture_ptr->unique_open_flower_prototype_objIDs.at(parent_shoot_type_label).at(prototype) = objID_flower;
+
1306 context_ptr->hideObject({objID_flower});
+
1307 }
+
1308 }
+
1309 //fruit
+
1310 if( phytomer_parameters.inflorescence.fruit_prototype_function!= nullptr && plantarchitecture_ptr->unique_fruit_prototype_objIDs.find(parent_shoot_type_label) == plantarchitecture_ptr->unique_fruit_prototype_objIDs.end() ) {
+
1311 plantarchitecture_ptr->unique_fruit_prototype_objIDs[parent_shoot_type_label].resize(phytomer_parameters.inflorescence.unique_prototypes);
+
1312 for( int prototype = 0; prototype < phytomer_parameters.inflorescence.unique_prototypes; prototype++ ) {
+
1313 uint objID_fruit = phytomer_parameters.inflorescence.fruit_prototype_function(context_ptr, 1, false);
+
1314 plantarchitecture_ptr->unique_fruit_prototype_objIDs.at(parent_shoot_type_label).at(prototype) = objID_fruit;
+
1315 context_ptr->hideObject({objID_fruit});
+
1316 }
+
1317 }
+
1318 }
+
1319
+
1320 for(int fruit=0; fruit < phytomer_parameters.inflorescence.flowers_per_peduncle.val(); fruit++ ){
+
1321
+
1322 uint objID_fruit;
+
1323 helios::vec3 fruit_scale;
+
1324
+
1325 if(fbud.state == BUD_FRUITING ){
+
1326 if( phytomer_parameters.inflorescence.unique_prototypes>0 ) { //copy existing prototype
+
1327 int prototype = context_ptr->randu(0, int(phytomer_parameters.inflorescence.unique_prototypes - 1));
+
1328 objID_fruit = context_ptr->copyObject(plantarchitecture_ptr->unique_fruit_prototype_objIDs.at(parent_shoot_type_label).at(prototype));
+
1329 }else{ //load new prototype
+
1330 objID_fruit = phytomer_parameters.inflorescence.fruit_prototype_function(context_ptr, 1, fbud.time_counter);
+
1331 }
+
1332 fruit_scale = phytomer_parameters.inflorescence.fruit_prototype_scale.val()*make_vec3(1,1,1);
+
1333 phytomer_parameters.inflorescence.fruit_prototype_scale.resample();
+
1334 }else{
+
1335 bool flower_is_open;
+
1336 if(fbud.state == BUD_FLOWER_CLOSED ) {
+
1337 flower_is_open = false;
+
1338 if( phytomer_parameters.inflorescence.unique_prototypes>0 ) { //copy existing prototype
+
1339 int prototype = context_ptr->randu(0, int(phytomer_parameters.inflorescence.unique_prototypes - 1));
+
1340 objID_fruit = context_ptr->copyObject(plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.at(parent_shoot_type_label).at(prototype));
+
1341 }else{ //load new prototype
+
1342 objID_fruit = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, flower_is_open);
+
1343 }
+
1344 }else{
+
1345 flower_is_open = true;
+
1346 if( phytomer_parameters.inflorescence.unique_prototypes>0 ) { //copy existing prototype
+
1347 int prototype = context_ptr->randu(0, int(phytomer_parameters.inflorescence.unique_prototypes - 1));
+
1348 objID_fruit = context_ptr->copyObject(plantarchitecture_ptr->unique_open_flower_prototype_objIDs.at(parent_shoot_type_label).at(prototype));
+
1349 }else{ //load new prototype
+
1350 objID_fruit = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, flower_is_open);
+
1351 }
+
1352 }
+
1353 fruit_scale = phytomer_parameters.inflorescence.flower_prototype_scale.val()*make_vec3(1,1,1);
+
1354 phytomer_parameters.inflorescence.flower_prototype_scale.resample();
+
1355 }
+
1356
+
1357 float ind_from_tip = fabs(fruit - float(phytomer_parameters.inflorescence.flowers_per_peduncle.val() - 1) / float(phytomer_parameters.petiole.petioles_per_internode));
+
1358
+
1359 context_ptr->scaleObject( objID_fruit, fruit_scale );
+
1360
+
1361 //if we have more than one flower/fruit, we need to adjust the base position of the fruit
+
1362 vec3 fruit_base = peduncle_vertices.back();
+
1363 float frac = 1;
+
1364 if(phytomer_parameters.inflorescence.flowers_per_peduncle.val() > 1 && phytomer_parameters.inflorescence.flower_offset.val() > 0 ){
+
1365 if( ind_from_tip != 0 ) {
+
1366 float offset = offset = (ind_from_tip - 0.5f) * phytomer_parameters.inflorescence.flower_offset.val() * phytomer_parameters.peduncle.length.val();
+
1367 if( phytomer_parameters.peduncle.length.val()>0 ){
+
1368 frac = 1.f - offset / phytomer_parameters.peduncle.length.val();
+
1369 }
+
1370 fruit_base = interpolateTube(peduncle_vertices, frac);
+
1371 }
+
1372 }
+
1373
+
1374 //if we have more than one flower/fruit, we need to adjust the rotation about the peduncle
+
1375 float compound_rotation = 0;
+
1376 if(phytomer_parameters.inflorescence.flowers_per_peduncle.val() > 1 ) {
+
1377 if (phytomer_parameters.inflorescence.flower_offset.val() == 0) { //flowers/fruit are all at the tip, so just equally distribute them about the azimuth
+
1378 float dphi = M_PI / (floor(0.5 * float(phytomer_parameters.inflorescence.flowers_per_peduncle.val() - 1)) + 1);
+
1379 compound_rotation = -float(M_PI) + dphi * (fruit + 0.5f);
+
1380 } else {
+
1381 compound_rotation = deg2rad(phytomer_parameters.internode.phyllotactic_angle.val())*float(ind_from_tip) + 2.f*M_PI/float(phytomer_parameters.petiole.petioles_per_internode)*float(fruit);
+
1382 phytomer_parameters.internode.phyllotactic_angle.resample();
+
1383 }
+
1384 }
+
1385
+
1386 peduncle_axis = getAxisVector(frac, peduncle_vertices );
+
1387
+
1388 vec3 fruit_axis = peduncle_axis;
+
1389
+
1390 //roll rotation
+
1391 if( phytomer_parameters.inflorescence.roll.val()!=0.f ) {
+
1392 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.inflorescence.roll.val()), "x" );
+
1393 phytomer_parameters.inflorescence.roll.resample();
+
1394 }
+
1395
+
1396 //pitch rotation
+
1397 float pitch_inflorescence = -asin_safe(peduncle_axis.z) + deg2rad(phytomer_parameters.inflorescence.pitch.val());
+
1398 phytomer_parameters.inflorescence.pitch.resample();
+
1399 if(fbud.state == BUD_FRUITING ) { //gravity effect for fruit
+
1400 pitch_inflorescence = pitch_inflorescence + phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.val() * (0.5f * M_PI - pitch_inflorescence);
+
1401 }
+
1402 context_ptr->rotateObject(objID_fruit, pitch_inflorescence, "y");
+
1403 fruit_axis = rotatePointAboutLine(fruit_axis, nullorigin, make_vec3(1, 0, 0), pitch_inflorescence);
+
1404
+
1405 //rotate flower/fruit to azimuth of peduncle
+
1406 context_ptr->rotateObject(objID_fruit, -std::atan2(peduncle_axis.y, peduncle_axis.x), "z" );
+
1407 fruit_axis = rotatePointAboutLine( fruit_axis, nullorigin, make_vec3(0,0,1), -std::atan2(peduncle_axis.y, peduncle_axis.x) );
+
1408
+
1409 context_ptr->translateObject( objID_fruit, fruit_base );
+
1410
+
1411 //rotate flower/fruit about peduncle (roll)
+
1412 if( phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.val()!=0 && fbud.state == BUD_FRUITING ) {
+
1413 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation, fruit_base, make_vec3(0, 0, 1));
+
1414 }else{
+
1415 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation, fruit_base, peduncle_axis);
+
1416 fruit_axis = rotatePointAboutLine(fruit_axis, nullorigin, peduncle_axis, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation);
+
1417 }
+
1418 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.resample();
+
1419
+
1420 fbud.inflorescence_bases.push_back(fruit_base );
+
1421
+
1422 fbud.inflorescence_objIDs.push_back(objID_fruit );
+
1423
+
1424 }
+
1425 phytomer_parameters.inflorescence.flowers_per_peduncle.resample();
+
1426 phytomer_parameters.peduncle.roll.resample();
+
1427
+
1428 if( plantarchitecture_ptr->output_object_data.at("rank") ) {
+
1429 context_ptr->setObjectData(fbud.peduncle_objIDs, "rank", rank );
+
1430 context_ptr->setObjectData(fbud.inflorescence_objIDs, "rank", rank );
+
1431 }
+
1432
+
1433 if( plantarchitecture_ptr->output_object_data.at("peduncleID") ) {
+
1434 for (uint objID: fbud.peduncle_objIDs) {
+
1435 context_ptr->setObjectData(objID, "peduncleID", (int) objID);
+
1436 }
+
1437 }
+
1438 for( uint objID : fbud.inflorescence_objIDs ) {
+
1439 if( fbud.state == BUD_FLOWER_CLOSED && plantarchitecture_ptr->output_object_data.at("closedflowerID") ) {
+
1440 context_ptr->setObjectData( objID, "closedflowerID", (int) objID);
+
1441 }else if( fbud.state == BUD_FLOWER_OPEN && plantarchitecture_ptr->output_object_data.at("openflowerID") ) {
+
1442 context_ptr->clearObjectData( objID, "closedflowerID" );
+
1443 context_ptr->setObjectData( objID, "openflowerID", (int) objID);
+
1444 }else if( plantarchitecture_ptr->output_object_data.at("fruitID") ){
+
1445 context_ptr->setObjectData( objID, "fruitID", (int) objID);
+
1446 }
+
1447 }
+
1448
+
1449}
+
1450
+
1451void Phytomer::setPetioleBase( const helios::vec3 &base_position ){
+
1452
+
1453 vec3 old_base = petiole_vertices.front().front();
+
1454 vec3 shift = base_position - old_base;
+
1455
+
1456 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
+
1457 for (auto &vertex: petiole_vertices.at(petiole) ) {
+
1458 vertex += shift;
+
1459 }
+
1460 }
+
1461
+
1462 if( build_context_geometry_petiole ) {
+
1463 context_ptr->translateObject(flatten(petiole_objIDs), shift);
+
1464 }
+
1465 context_ptr->translateObject( flatten(leaf_objIDs), shift );
+
1466
+
1467 for( int petiole=0; petiole<leaf_bases.size(); petiole++ ) {
+
1468 for (auto &leaf_base: leaf_bases.at(petiole)) {
+
1469 leaf_base += shift;
+
1470 }
+
1471 for ( auto &fbud : floral_buds.at(petiole) ) {
+
1472 assert( !fbud.isterminal );
+
1473 fbud.base_position = petiole_vertices.at(petiole).front();
+
1474 context_ptr->translateObject( fbud.inflorescence_objIDs, shift);
+
1475 for( auto &base : fbud.inflorescence_bases ) {
+
1476 base += shift;
+
1477 }
+
1478 if( build_context_geometry_peduncle ) {
+
1479 context_ptr->translateObject( fbud.peduncle_objIDs, shift);
+
1480 }
+
1481 }
+
1482 }
+
1483
+
1484}
+
1485
+
1486void Phytomer::rotateLeaf( uint petiole_index, uint leaf_index, const AxisRotation &rotation ){
+
1487
+
1488 if( petiole_index>=leaf_objIDs.size() ){
+
1489 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Invalid petiole index.");
+
1490 }else if( leaf_index>=leaf_objIDs.at(petiole_index).size() ){
+
1491 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Invalid leaf index.");
+
1492 }
+
1493
+
1494 vec3 petiole_axis = getPetioleAxisVector(1.f, petiole_index); //note: this is not exactly correct because it should get the axis at the leaf position and not the tip
+
1495
+
1496 vec3 internode_axis = getInternodeAxisVector(1.f);
+
1497
+
1498 vec3 pitch_axis = -1*cross( internode_axis, petiole_axis );
+
1499
+
1500 int leaves_per_petiole = leaf_rotation.at(petiole_index).size();
+
1501 float yaw;
+
1502 float roll;
+
1503 float compound_rotation = 0;
+
1504 if( leaf_index == float(leaves_per_petiole-1)/2.f ){ //tip leaf
+
1505 roll = 0;
+
1506 yaw = 0;
+
1507 compound_rotation = 0;
+
1508 }else if( leaf_index < float(leaves_per_petiole-1)/2.f ) {
+
1509 yaw = -rotation.yaw;
+
1510 roll = -rotation.roll;
+
1511 compound_rotation = -0.5*M_PI;
+
1512 }else{
+
1513 yaw = -rotation.yaw;
+
1514 roll = rotation.roll;
+
1515 compound_rotation = 0.5*M_PI;
+
1516 }
+
1517
+
1518 //roll
+
1519 if( roll!=0.f ) {
+
1520 vec3 roll_axis = rotatePointAboutLine({petiole_axis.x, petiole_axis.y, 0}, nullorigin, {0, 0, 1}, leaf_rotation.at(petiole_index).at(leaf_index).yaw + compound_rotation);
+
1521 context_ptr->rotateObject(leaf_objIDs.at(petiole_index).at(leaf_index), roll, leaf_bases.at(petiole_index).at(leaf_index), roll_axis);
+
1522 leaf_rotation.at(petiole_index).at(leaf_index).roll += roll;
+
1523 }
+
1524
+
1525 //pitch
+
1526 if( rotation.pitch!=0 ) {
+
1527 pitch_axis = rotatePointAboutLine(pitch_axis, nullorigin, {0, 0, 1}, -compound_rotation);
+
1528 context_ptr->rotateObject(leaf_objIDs.at(petiole_index).at(leaf_index), rotation.pitch, leaf_bases.at(petiole_index).at(leaf_index), pitch_axis);
+
1529 leaf_rotation.at(petiole_index).at(leaf_index).pitch += rotation.pitch;
+
1530 }
+
1531
+
1532 //yaw
+
1533 if( yaw!=0.f ) {
+
1534 context_ptr->rotateObject(leaf_objIDs.at(petiole_index).at(leaf_index), yaw, leaf_bases.at(petiole_index).at(leaf_index), {0, 0, 1});
+
1535 leaf_rotation.at(petiole_index).at(leaf_index).yaw += yaw;
+
1536 }
+
1537
+
1538}
+
1539
+
1540void Phytomer::setInternodeLengthScaleFraction(float internode_scale_factor_fraction, bool update_context_geometry) {
+
1541
+
1542 assert(internode_scale_factor_fraction >= 0 && internode_scale_factor_fraction <= 1 );
+
1543
+
1544 if(internode_scale_factor_fraction == current_internode_scale_factor ){
+
1545 return;
+
1546 }
+
1547
+
1548 float delta_scale = internode_scale_factor_fraction / current_internode_scale_factor;
+
1549
+
1550 float current_internode_length = getInternodeLength();
+
1551 float internode_length = current_internode_length*delta_scale;
+
1552 current_internode_scale_factor = internode_scale_factor_fraction;
+
1553
+
1554 int p = shoot_index.x;
+
1555 int s_start = (p == 0) ? 1 : 0; //skip the first node at the base of the shoot
+
1556
+
1557 for (int s = s_start; s < parent_shoot_ptr->shoot_internode_vertices.at(p).size(); s++) { //looping over all segments within this phytomer internode
+
1558
+
1559 int p_minus = p;
+
1560 int s_minus = s-1;
+
1561 if( s_minus<0 ){
+
1562 p_minus--;
+
1563 s_minus = int(parent_shoot_ptr->shoot_internode_vertices.at(p_minus).size()-1);
+
1564 }
+
1565
+
1566 vec3 central_axis = (parent_shoot_ptr->shoot_internode_vertices.at(p).at(s) - parent_shoot_ptr->shoot_internode_vertices.at(p_minus).at(s_minus));
+
1567 float current_length = central_axis.magnitude();
+
1568 central_axis = central_axis / current_length;
+
1569 vec3 dL = central_axis * current_length * (delta_scale - 1);
+
1570
+
1571 //apply shift to all downstream nodes
+
1572 for (int p_downstream = p; p_downstream < parent_shoot_ptr->shoot_internode_vertices.size(); p_downstream++) {
+
1573 int sd_start = ( p_downstream==p ) ? s : 0;
+
1574 for (int s_downstream = sd_start; s_downstream < parent_shoot_ptr->shoot_internode_vertices.at(p_downstream).size(); s_downstream++) {
+
1575 parent_shoot_ptr->shoot_internode_vertices.at(p_downstream).at(s_downstream) += dL;
+
1576 }
+
1577
+
1578 }
+
1579
+
1580 }
+
1581
+
1582 parent_shoot_ptr->updateShootNodes(update_context_geometry);
1583
-
1584}
-
1585
-
-
1586void Phytomer::scaleInternodeMaxLength( float scale_factor ){
-
1587 this->internode_length_max *= scale_factor;
-
1588
-
1589 current_internode_scale_factor = current_internode_scale_factor/scale_factor;
-
1590
-
1591 if( current_internode_scale_factor>=1.f ){
-
1592 setInternodeLengthScaleFraction(1.f, true);
-
1593 current_internode_scale_factor = 1.f;
-
1594 }
-
1595}
+
1584
+
1585}
+
1586
+
+
1587void Phytomer::scaleInternodeMaxLength( float scale_factor ){
+
1588 this->internode_length_max *= scale_factor;
+
1589
+
1590 current_internode_scale_factor = current_internode_scale_factor/scale_factor;
+
1591
+
1592 if( current_internode_scale_factor>=1.f ){
+
1593 setInternodeLengthScaleFraction(1.f, true);
+
1594 current_internode_scale_factor = 1.f;
+
1595 }
+
1596}
-
1596
-
-
1597void Phytomer::setInternodeMaxLength( float internode_length_max_new ){
-
1598 float scale_factor = internode_length_max_new/this->internode_length_max;
-
1599 scaleInternodeMaxLength(scale_factor);
-
1600}
+
1597
+
+
1598void Phytomer::setInternodeMaxLength( float internode_length_max_new ){
+
1599 float scale_factor = internode_length_max_new/this->internode_length_max;
+
1600 scaleInternodeMaxLength(scale_factor);
+
1601}
-
1601
-
-
1602void Phytomer::setInternodeMaxRadius( float internode_radius_max_new ){
-
1603
-
1604 this->internode_radius_max = internode_radius_max_new;
-
1605
-
1606}
+
1602
+
+
1603void Phytomer::setInternodeMaxRadius( float internode_radius_max_new ){
+
1604
+
1605 this->internode_radius_max = internode_radius_max_new;
+
1606
+
1607}
-
1607
-
-
1608void Phytomer::setLeafScaleFraction(float leaf_scale_factor_fraction ){
-
1609
-
1610 assert(leaf_scale_factor_fraction >= 0 && leaf_scale_factor_fraction <= 1 );
-
1611
-
1612 if(leaf_scale_factor_fraction == current_leaf_scale_factor || (leaf_objIDs.empty() && petiole_objIDs.empty()) ){
-
1613 return;
-
1614 }
-
1615
-
1616 float delta_scale = leaf_scale_factor_fraction / current_leaf_scale_factor;
-
1617
-
1618 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
-
1619 petiole_length.at(petiole) *= delta_scale;
-
1620 }
-
1621 current_leaf_scale_factor = leaf_scale_factor_fraction;
-
1622
-
1623 assert(leaf_objIDs.size() == leaf_bases.size());
-
1624
-
1625 //scale the petiole
-
1626 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
-
1627
-
1628 if( !petiole_objIDs.empty() ) {
-
1629 int node = 0;
-
1630 vec3 old_tip = petiole_vertices.at(petiole).back();
-
1631 vec3 last_base = petiole_vertices.at(petiole).front();//looping over petioles
-
1632 for (uint objID: petiole_objIDs.at(petiole)) { //looping over cones/segments within petiole
-
1633 context_ptr->getConeObjectPointer(objID)->scaleLength(delta_scale);
-
1634 context_ptr->getConeObjectPointer(objID)->scaleGirth(delta_scale);
-
1635 petiole_radii.at(petiole).at(node) *= delta_scale;
-
1636 if (node > 0) {
-
1637 vec3 new_base = context_ptr->getConeObjectNode(objID, 0);
-
1638 context_ptr->translateObject(objID, last_base - new_base);
-
1639 } else {
-
1640 petiole_vertices.at(petiole).at(0) = context_ptr->getConeObjectNode(objID, 0);
-
1641 }
-
1642 last_base = context_ptr->getConeObjectNode(objID, 1);
-
1643 petiole_vertices.at(petiole).at(node + 1) = last_base;
-
1644 node++;
-
1645 }
-
1646 }else{
-
1647 for( int i=1; i<petiole_vertices.at(petiole).size(); i++ ) {
-
1648 vec3 axis_vector = petiole_vertices.at(petiole).at(i) - petiole_vertices.at(petiole).at(i-1);
-
1649 petiole_vertices.at(petiole).at(i) = petiole_vertices.at(petiole).at(i-1) + delta_scale*axis_vector;
-
1650 petiole_radii.at(petiole).at(i) *= delta_scale;
-
1651 }
-
1652 }
-
1653
-
1654 //scale and translate leaves
-
1655 assert(leaf_objIDs.at(petiole).size() == leaf_bases.at(petiole).size());
-
1656 for (int leaf = 0; leaf < leaf_objIDs.at(petiole).size(); leaf++) {
-
1657
-
1658 float ind_from_tip = float(leaf) - float(leaf_objIDs.at(petiole).size() - 1) / 2.f;
-
1659
-
1660 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), -1 * leaf_bases.at(petiole).at(leaf));
-
1661 context_ptr->scaleObject(leaf_objIDs.at(petiole).at(leaf), delta_scale * make_vec3(1, 1, 1));
-
1662 if (ind_from_tip == 0) {
-
1663 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), petiole_vertices.at(petiole).back());
-
1664 leaf_bases.at(petiole).at(leaf) = petiole_vertices.at(petiole).back();
-
1665 } else {
-
1666 float offset = (fabs(ind_from_tip) - 0.5f) * phytomer_parameters.leaf.leaflet_offset.val() * phytomer_parameters.petiole.length.val();
-
1667 vec3 leaf_base = interpolateTube(petiole_vertices.at(petiole), 1.f - offset / phytomer_parameters.petiole.length.val());
-
1668 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), leaf_base);
-
1669 leaf_bases.at(petiole).at(leaf) = leaf_base;
-
1670 }
-
1671
-
1672 }
-
1673
-
1674 }
-
1675
-
1676}
+
1608
+
+
1609void Phytomer::setLeafScaleFraction(float leaf_scale_factor_fraction ){
+
1610
+
1611 assert(leaf_scale_factor_fraction >= 0 && leaf_scale_factor_fraction <= 1 );
+
1612
+
1613 if(leaf_scale_factor_fraction == current_leaf_scale_factor || (leaf_objIDs.empty() && petiole_objIDs.empty()) ){
+
1614 return;
+
1615 }
+
1616
+
1617 float delta_scale = leaf_scale_factor_fraction / current_leaf_scale_factor;
+
1618
+
1619 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
+
1620 petiole_length.at(petiole) *= delta_scale;
+
1621 }
+
1622 current_leaf_scale_factor = leaf_scale_factor_fraction;
+
1623
+
1624 assert(leaf_objIDs.size() == leaf_bases.size());
+
1625
+
1626 //scale the petiole
+
1627 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
+
1628
+
1629 if( !petiole_objIDs.empty() ) {
+
1630 int node = 0;
+
1631 vec3 old_tip = petiole_vertices.at(petiole).back();
+
1632 vec3 last_base = petiole_vertices.at(petiole).front();//looping over petioles
+
1633 for (uint objID: petiole_objIDs.at(petiole)) { //looping over cones/segments within petiole
+
1634 context_ptr->getConeObjectPointer(objID)->scaleLength(delta_scale);
+
1635 context_ptr->getConeObjectPointer(objID)->scaleGirth(delta_scale);
+
1636 petiole_radii.at(petiole).at(node) *= delta_scale;
+
1637 if (node > 0) {
+
1638 vec3 new_base = context_ptr->getConeObjectNode(objID, 0);
+
1639 context_ptr->translateObject(objID, last_base - new_base);
+
1640 } else {
+
1641 petiole_vertices.at(petiole).at(0) = context_ptr->getConeObjectNode(objID, 0);
+
1642 }
+
1643 last_base = context_ptr->getConeObjectNode(objID, 1);
+
1644 petiole_vertices.at(petiole).at(node + 1) = last_base;
+
1645 node++;
+
1646 }
+
1647 }else{
+
1648 for( int i=1; i<petiole_vertices.at(petiole).size(); i++ ) {
+
1649 vec3 axis_vector = petiole_vertices.at(petiole).at(i) - petiole_vertices.at(petiole).at(i-1);
+
1650 petiole_vertices.at(petiole).at(i) = petiole_vertices.at(petiole).at(i-1) + delta_scale*axis_vector;
+
1651 petiole_radii.at(petiole).at(i) *= delta_scale;
+
1652 }
+
1653 }
+
1654
+
1655 //scale and translate leaves
+
1656 assert(leaf_objIDs.at(petiole).size() == leaf_bases.at(petiole).size());
+
1657 for (int leaf = 0; leaf < leaf_objIDs.at(petiole).size(); leaf++) {
+
1658
+
1659 float ind_from_tip = float(leaf) - float(leaf_objIDs.at(petiole).size() - 1) / 2.f;
+
1660
+
1661 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), -1 * leaf_bases.at(petiole).at(leaf));
+
1662 context_ptr->scaleObject(leaf_objIDs.at(petiole).at(leaf), delta_scale * make_vec3(1, 1, 1));
+
1663 if (ind_from_tip == 0) {
+
1664 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), petiole_vertices.at(petiole).back());
+
1665 leaf_bases.at(petiole).at(leaf) = petiole_vertices.at(petiole).back();
+
1666 } else {
+
1667 float offset = (fabs(ind_from_tip) - 0.5f) * phytomer_parameters.leaf.leaflet_offset.val() * phytomer_parameters.petiole.length.val();
+
1668 vec3 leaf_base = interpolateTube(petiole_vertices.at(petiole), 1.f - offset / phytomer_parameters.petiole.length.val());
+
1669 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), leaf_base);
+
1670 leaf_bases.at(petiole).at(leaf) = leaf_base;
+
1671 }
+
1672
+
1673 }
+
1674
+
1675 }
+
1676
+
1677}
-
1677
-
-
1678void Phytomer::setLeafPrototypeScale( float leaf_prototype_scale ){
-
1679
-
1680 float tip_ind = ceil(float(leaf_size_max.front().size()-1)/2.f);
-
1681 float scale_factor = leaf_prototype_scale/leaf_size_max.front().at(tip_ind);
-
1682 current_leaf_scale_factor = current_leaf_scale_factor*scale_factor;
-
1683
-
1684 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
-
1685 for (int leaf = 0; leaf < leaf_objIDs.at(petiole).size(); leaf++) {
-
1686 leaf_size_max.at(petiole).at(leaf)*=scale_factor;
-
1687 }
-
1688 }
-
1689
-
1690 //note: at time of phytomer creation, petiole curvature was based on the petiole length prior to this scaling. To stay consistent, we will scale the curvature appropriately.
-
1691 this->petiole_curvature /= scale_factor;
-
1692
-
1693 if( current_leaf_scale_factor>=1.f ){
- -
1695 current_leaf_scale_factor = 1.f;
-
1696 }
-
1697
-
1698}
+
1678
+
+
1679void Phytomer::setLeafPrototypeScale( float leaf_prototype_scale ){
+
1680
+
1681 float tip_ind = ceil(float(leaf_size_max.front().size()-1)/2.f);
+
1682 float scale_factor = leaf_prototype_scale/leaf_size_max.front().at(tip_ind);
+
1683 current_leaf_scale_factor = current_leaf_scale_factor*scale_factor;
+
1684
+
1685 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
+
1686 for (int leaf = 0; leaf < leaf_objIDs.at(petiole).size(); leaf++) {
+
1687 leaf_size_max.at(petiole).at(leaf)*=scale_factor;
+
1688 }
+
1689 }
+
1690
+
1691 //note: at time of phytomer creation, petiole curvature was based on the petiole length prior to this scaling. To stay consistent, we will scale the curvature appropriately.
+
1692 this->petiole_curvature /= scale_factor;
+
1693
+
1694 if( current_leaf_scale_factor>=1.f ){
+ +
1696 current_leaf_scale_factor = 1.f;
+
1697 }
+
1698
+
1699}
-
1699
-
1700void Phytomer::scaleLeafPrototypeScale( float scale_factor ){
-
1701
-
1702 if( scale_factor<0.f ) {
-
1703 scale_factor = 0;
-
1704 }
-
1705
-
1706 current_leaf_scale_factor = current_leaf_scale_factor/scale_factor;
-
1707
-
1708 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
-
1709 for (int leaf = 0; leaf < leaf_objIDs.at(petiole).size(); leaf++) {
-
1710 leaf_size_max.at(petiole).at(leaf) *= scale_factor;
-
1711 }
-
1712 }
-
1713
-
1714 //note: at time of phytomer creation, petiole curvature was based on the petiole length prior to this scaling. To stay consistent, we will scale the curvature appropriately.
-
1715 this->petiole_curvature /= scale_factor;
-
1716
-
1717 if( current_leaf_scale_factor>=1.f ){
- -
1719 current_leaf_scale_factor = 1.f;
-
1720 }
-
1721
-
1722}
-
1723
+
1700
+
1701void Phytomer::scaleLeafPrototypeScale( float scale_factor ){
+
1702
+
1703 if( scale_factor<0.f ) {
+
1704 scale_factor = 0;
+
1705 }
+
1706
+
1707 current_leaf_scale_factor = current_leaf_scale_factor/scale_factor;
+
1708
+
1709 for( int petiole=0; petiole<phytomer_parameters.petiole.petioles_per_internode; petiole++ ) {
+
1710 for (int leaf = 0; leaf < leaf_objIDs.at(petiole).size(); leaf++) {
+
1711 leaf_size_max.at(petiole).at(leaf) *= scale_factor;
+
1712 }
+
1713 }
+
1714
+
1715 //note: at time of phytomer creation, petiole curvature was based on the petiole length prior to this scaling. To stay consistent, we will scale the curvature appropriately.
+
1716 this->petiole_curvature /= scale_factor;
+
1717
+
1718 if( current_leaf_scale_factor>=1.f ){
+ +
1720 current_leaf_scale_factor = 1.f;
+
1721 }
+
1722
+
1723}
1724
-
1725void Phytomer::setInflorescenceScaleFraction(FloralBud &fbud, float inflorescence_scale_factor_fraction) {
-
1726
-
1727 assert(inflorescence_scale_factor_fraction >= 0 && inflorescence_scale_factor_fraction <= 1 );
-
1728
-
1729 if(inflorescence_scale_factor_fraction == fbud.current_fruit_scale_factor ){
-
1730 return;
-
1731 }
-
1732
-
1733 float delta_scale = inflorescence_scale_factor_fraction / fbud.current_fruit_scale_factor;
-
1734
-
1735 fbud.current_fruit_scale_factor = inflorescence_scale_factor_fraction;
-
1736
-
1737 //scale and translate flowers/fruit
-
1738 for( int inflorescence=0; inflorescence<fbud.inflorescence_objIDs.size(); inflorescence++ ) {
-
1739 context_ptr->scaleObjectAboutPoint(fbud.inflorescence_objIDs.at(inflorescence), delta_scale*make_vec3(1,1,1), fbud.inflorescence_bases.at(inflorescence));
-
1740 }
-
1741
-
1742}
-
1743
-
1744void Phytomer::removeLeaf(){
-
1745
-
1746 this->petiole_radii.resize(0);
-
1747// this->petiole_vertices.resize(0);
-
1748 this->petiole_colors.resize(0);
-
1749 this->petiole_length.resize(0);
-
1750 this->leaf_size_max.resize(0);
-
1751 this->leaf_rotation.resize(0);
-
1752 this->leaf_bases.resize(0);
-
1753
-
1754 context_ptr->deleteObject(flatten(leaf_objIDs));
-
1755 leaf_objIDs.resize(0);
-
1756 leaf_bases.resize(0);
-
1757
-
1758 if( build_context_geometry_petiole ) {
-
1759 context_ptr->deleteObject(flatten(petiole_objIDs));
-
1760 petiole_objIDs.resize(0);
-
1761 }
-
1762
-
1763}
-
1764
-
1765bool Phytomer::hasLeaf() const{
-
1766 return !leaf_bases.empty();
-
1767}
-
1768
-
1769float Phytomer::calculateDownstreamLeafArea() const{
-
1770 return parent_shoot_ptr->sumShootLeafArea( shoot_index.x );
-
1771}
-
1772
-
1773Shoot::Shoot(uint plant_ID, int shoot_ID, int parent_shoot_ID, uint parent_node, uint parent_petiole_index, uint rank, const helios::vec3 &shoot_base_position, const AxisRotation &shoot_base_rotation, uint current_node_number,
-
1774 float internode_length_shoot_initial, ShootParameters &shoot_params, std::string shoot_type_label, PlantArchitecture *plant_architecture_ptr) :
-
1775 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), base_position(shoot_base_position), base_rotation(shoot_base_rotation), current_node_number(current_node_number), internode_length_max_shoot_initial(internode_length_shoot_initial), shoot_parameters(shoot_params), shoot_type_label(std::move(shoot_type_label)), plantarchitecture_ptr(plant_architecture_ptr) {
-
1776 carbohydrate_pool_molC = 0;
-
1777 phyllochron_counter = 0;
-
1778 isdormant = true;
-
1779 gravitropic_curvature = shoot_params.gravitropic_curvature.val();
-
1780 context_ptr = plant_architecture_ptr->context_ptr;
-
1781
-
1782 if( parent_shoot_ID>=0 ) {
-
1783 plant_architecture_ptr->plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID)->childIDs[(int) parent_node_index].push_back(shoot_ID);
-
1784 }
-
1785
-
1786}
-
1787
-
1788void Shoot::buildShootPhytomers(float internode_radius, float internode_length, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper) {
-
1789
-
1790 for( int i=0; i<current_node_number; i++ ) { //loop over phytomers to build up the shoot
-
1791
-
1792 //Determine position of internode base
-
1793 vec3 internode_base_position;
-
1794 if( i==0 ){ //first phytomer on shoot
-
1795 internode_base_position = base_position;
-
1796 }else{ // not the first phytomer on the shoot
-
1797 internode_base_position = shoot_internode_vertices.back().back();
-
1798 }
-
1799
-
1800 float taper = 1.f;
-
1801 if( current_node_number>1 ){
-
1802 taper = 1.f-radius_taper*float(i)/float(current_node_number-1);
-
1803 }
-
1804
-
1805 //Adding the phytomer(s) to the shoot
-
1806 int pID = appendPhytomer(internode_radius * taper, internode_length, internode_length_scale_factor_fraction, leaf_scale_factor_fraction);
-
1807
-
1808 }
-
1809
-
1810}
-
1811
-
-
1812bool Shoot::sampleChildShootType(std::string &child_shoot_type_label) const{
-
1813
-
1814 auto shoot_ptr = this;
-
1815
-
1816 assert( shoot_ptr->shoot_parameters.child_shoot_type_labels.size() == shoot_ptr->shoot_parameters.child_shoot_type_probabilities.size() );
-
1817
-
1818 child_shoot_type_label = "";
-
1819
-
1820 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
-
1821 child_shoot_type_label = shoot_ptr->shoot_type_label;
-
1822 }else if( shoot_ptr->shoot_parameters.child_shoot_type_labels.size()==1 ){ //if only one child shoot types was specified, use it
-
1823 child_shoot_type_label = shoot_ptr->shoot_parameters.child_shoot_type_labels.at(0);
-
1824 }else{
-
1825 float randf = context_ptr->randu();
-
1826 int shoot_type_index = -1;
-
1827 float cumulative_probability = 0;
-
1828 for (int s = 0; s < shoot_ptr->shoot_parameters.child_shoot_type_labels.size(); s++) {
-
1829 cumulative_probability += shoot_ptr->shoot_parameters.child_shoot_type_probabilities.at(s);
-
1830 if (randf < cumulative_probability ) {
-
1831 shoot_type_index = s;
-
1832 break;
-
1833 }
-
1834 }
-
1835 if (shoot_type_index < 0) {
-
1836 shoot_type_index = shoot_ptr->shoot_parameters.child_shoot_type_labels.size() - 1;
-
1837 }
-
1838 child_shoot_type_label = shoot_ptr->shoot_type_label;
-
1839 if (shoot_type_index >= 0) {
-
1840 child_shoot_type_label = shoot_ptr->shoot_parameters.child_shoot_type_labels.at(shoot_type_index);
-
1841 }
-
1842 }
-
1843
-
1844 bool bud_break = true;
-
1845 if (context_ptr->randu() > plantarchitecture_ptr->shoot_types.at(shoot_ptr->shoot_type_label).vegetative_bud_break_probability.val() ) {
-
1846 bud_break = false;
-
1847 }
-
1848
+
1725
+
1726void Phytomer::setInflorescenceScaleFraction(FloralBud &fbud, float inflorescence_scale_factor_fraction) {
+
1727
+
1728 assert(inflorescence_scale_factor_fraction >= 0 && inflorescence_scale_factor_fraction <= 1 );
+
1729
+
1730 if(inflorescence_scale_factor_fraction == fbud.current_fruit_scale_factor ){
+
1731 return;
+
1732 }
+
1733
+
1734 float delta_scale = inflorescence_scale_factor_fraction / fbud.current_fruit_scale_factor;
+
1735
+
1736 fbud.current_fruit_scale_factor = inflorescence_scale_factor_fraction;
+
1737
+
1738 //scale and translate flowers/fruit
+
1739 for( int inflorescence=0; inflorescence<fbud.inflorescence_objIDs.size(); inflorescence++ ) {
+
1740 context_ptr->scaleObjectAboutPoint(fbud.inflorescence_objIDs.at(inflorescence), delta_scale*make_vec3(1,1,1), fbud.inflorescence_bases.at(inflorescence));
+
1741 }
+
1742
+
1743}
+
1744
+
1745void Phytomer::removeLeaf(){
+
1746
+
1747 this->petiole_radii.resize(0);
+
1748// this->petiole_vertices.resize(0);
+
1749 this->petiole_colors.resize(0);
+
1750 this->petiole_length.resize(0);
+
1751 this->leaf_size_max.resize(0);
+
1752 this->leaf_rotation.resize(0);
+
1753 this->leaf_bases.resize(0);
+
1754
+
1755 context_ptr->deleteObject(flatten(leaf_objIDs));
+
1756 leaf_objIDs.resize(0);
+
1757 leaf_bases.resize(0);
+
1758
+
1759 if( build_context_geometry_petiole ) {
+
1760 context_ptr->deleteObject(flatten(petiole_objIDs));
+
1761 petiole_objIDs.resize(0);
+
1762 }
+
1763
+
1764}
+
1765
+
1766bool Phytomer::hasLeaf() const{
+
1767 return !leaf_bases.empty();
+
1768}
+
1769
+
1770float Phytomer::calculateDownstreamLeafArea() const{
+
1771 return parent_shoot_ptr->sumShootLeafArea( shoot_index.x );
+
1772}
+
1773
+
1774Shoot::Shoot(uint plant_ID, int shoot_ID, int parent_shoot_ID, uint parent_node, uint parent_petiole_index, uint rank, const helios::vec3 &shoot_base_position, const AxisRotation &shoot_base_rotation, uint current_node_number,
+
1775 float internode_length_shoot_initial, ShootParameters &shoot_params, std::string shoot_type_label, PlantArchitecture *plant_architecture_ptr) :
+
1776 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), base_position(shoot_base_position), base_rotation(shoot_base_rotation), current_node_number(current_node_number), internode_length_max_shoot_initial(internode_length_shoot_initial), shoot_parameters(shoot_params), shoot_type_label(std::move(shoot_type_label)), plantarchitecture_ptr(plant_architecture_ptr) {
+
1777 carbohydrate_pool_molC = 0;
+
1778 phyllochron_counter = 0;
+
1779 isdormant = true;
+
1780 gravitropic_curvature = shoot_params.gravitropic_curvature.val();
+
1781 context_ptr = plant_architecture_ptr->context_ptr;
+
1782
+
1783 if( parent_shoot_ID>=0 ) {
+
1784 plant_architecture_ptr->plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID)->childIDs[(int) parent_node_index].push_back(shoot_ID);
+
1785 }
+
1786
+
1787}
+
1788
+
1789void Shoot::buildShootPhytomers(float internode_radius, float internode_length, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper) {
+
1790
+
1791 for( int i=0; i<current_node_number; i++ ) { //loop over phytomers to build up the shoot
+
1792
+
1793 //Determine position of internode base
+
1794 vec3 internode_base_position;
+
1795 if( i==0 ){ //first phytomer on shoot
+
1796 internode_base_position = base_position;
+
1797 }else{ // not the first phytomer on the shoot
+
1798 internode_base_position = shoot_internode_vertices.back().back();
+
1799 }
+
1800
+
1801 float taper = 1.f;
+
1802 if( current_node_number>1 ){
+
1803 taper = 1.f-radius_taper*float(i)/float(current_node_number-1);
+
1804 }
+
1805
+
1806 //Adding the phytomer(s) to the shoot
+
1807 int pID = appendPhytomer(internode_radius * taper, internode_length, internode_length_scale_factor_fraction, leaf_scale_factor_fraction);
+
1808
+
1809 }
+
1810
+
1811}
+
1812
+
+
1813bool Shoot::sampleChildShootType(std::string &child_shoot_type_label) const{
+
1814
+
1815 auto shoot_ptr = this;
+
1816
+
1817 assert( shoot_ptr->shoot_parameters.child_shoot_type_labels.size() == shoot_ptr->shoot_parameters.child_shoot_type_probabilities.size() );
+
1818
+
1819 child_shoot_type_label = "";
+
1820
+
1821 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
+
1822 child_shoot_type_label = shoot_ptr->shoot_type_label;
+
1823 }else if( shoot_ptr->shoot_parameters.child_shoot_type_labels.size()==1 ){ //if only one child shoot types was specified, use it
+
1824 child_shoot_type_label = shoot_ptr->shoot_parameters.child_shoot_type_labels.at(0);
+
1825 }else{
+
1826 float randf = context_ptr->randu();
+
1827 int shoot_type_index = -1;
+
1828 float cumulative_probability = 0;
+
1829 for (int s = 0; s < shoot_ptr->shoot_parameters.child_shoot_type_labels.size(); s++) {
+
1830 cumulative_probability += shoot_ptr->shoot_parameters.child_shoot_type_probabilities.at(s);
+
1831 if (randf < cumulative_probability ) {
+
1832 shoot_type_index = s;
+
1833 break;
+
1834 }
+
1835 }
+
1836 if (shoot_type_index < 0) {
+
1837 shoot_type_index = shoot_ptr->shoot_parameters.child_shoot_type_labels.size() - 1;
+
1838 }
+
1839 child_shoot_type_label = shoot_ptr->shoot_type_label;
+
1840 if (shoot_type_index >= 0) {
+
1841 child_shoot_type_label = shoot_ptr->shoot_parameters.child_shoot_type_labels.at(shoot_type_index);
+
1842 }
+
1843 }
+
1844
+
1845 bool bud_break = true;
+
1846 if (context_ptr->randu() > plantarchitecture_ptr->shoot_types.at(shoot_ptr->shoot_type_label).vegetative_bud_break_probability.val() ) {
+
1847 bud_break = false;
+
1848 }
1849
-
1850 return bud_break;
-
1851
-
1852}
+
1850
+
1851 return bud_break;
+
1852
+
1853}
-
1853
-
-
1854uint Shoot::sampleEpicormicShoot( float dt, std::vector<float> &epicormic_positions_fraction ){
-
1855
-
1856 std::string epicormic_shoot_label = plantarchitecture_ptr->plant_instances.at(this->plantID).epicormic_shoot_probability_perlength_per_day.first;
-
1857
-
1858 if( epicormic_shoot_label.empty() ){
-
1859 return 0;
-
1860 }
-
1861
-
1862 float epicormic_probability = plantarchitecture_ptr->plant_instances.at(this->plantID).epicormic_shoot_probability_perlength_per_day.second;
-
1863
-
1864 if( epicormic_probability == 0 ){
-
1865 return 0;
-
1866 }
-
1867
-
1868 uint Nshoots = 0;
-
1869
-
1870 epicormic_positions_fraction.clear();
-
1871
-
1872 float shoot_length = this->calculateShootLength();
-
1873
-
1874 float time = dt;
-
1875 while( time>0 ){
-
1876
-
1877 float dta = std::min(time,1.f);
-
1878
-
1879 float shoot_fraction = context_ptr->randu();
-
1880
-
1881 float elevation = fabs(getShootAxisVector(shoot_fraction).z);
-
1882
-
1883 bool new_shoot = uint((epicormic_probability*shoot_length*dta*elevation > context_ptr->randu() ));
-
1884
-
1885 Nshoots += uint(new_shoot);
-
1886
-
1887 if( new_shoot ){
-
1888 epicormic_positions_fraction.push_back(shoot_fraction);
-
1889 }
-
1890
-
1891 time -= dta;
-
1892 }
-
1893
-
1894 assert(epicormic_positions_fraction.size() == Nshoots);
-
1895
-
1896 return Nshoots;
-
1897}
+
1854
+
+
1855uint Shoot::sampleEpicormicShoot( float dt, std::vector<float> &epicormic_positions_fraction ){
+
1856
+
1857 std::string epicormic_shoot_label = plantarchitecture_ptr->plant_instances.at(this->plantID).epicormic_shoot_probability_perlength_per_day.first;
+
1858
+
1859 if( epicormic_shoot_label.empty() ){
+
1860 return 0;
+
1861 }
+
1862
+
1863 float epicormic_probability = plantarchitecture_ptr->plant_instances.at(this->plantID).epicormic_shoot_probability_perlength_per_day.second;
+
1864
+
1865 if( epicormic_probability == 0 ){
+
1866 return 0;
+
1867 }
+
1868
+
1869 uint Nshoots = 0;
+
1870
+
1871 epicormic_positions_fraction.clear();
+
1872
+
1873 float shoot_length = this->calculateShootLength();
+
1874
+
1875 float time = dt;
+
1876 while( time>0 ){
+
1877
+
1878 float dta = std::min(time,1.f);
+
1879
+
1880 float shoot_fraction = context_ptr->randu();
+
1881
+
1882 float elevation = fabs(getShootAxisVector(shoot_fraction).z);
+
1883
+
1884 bool new_shoot = uint((epicormic_probability*shoot_length*dta*elevation > context_ptr->randu() ));
+
1885
+
1886 Nshoots += uint(new_shoot);
+
1887
+
1888 if( new_shoot ){
+
1889 epicormic_positions_fraction.push_back(shoot_fraction);
+
1890 }
+
1891
+
1892 time -= dta;
+
1893 }
+
1894
+
1895 assert(epicormic_positions_fraction.size() == Nshoots);
+
1896
+
1897 return Nshoots;
+
1898}
-
1898
-
-
1899uint 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,
-
1900 float radius_taper, const std::string &shoot_type_label) {
-
1901
-
1902 if( plant_instances.find(plantID) == plant_instances.end() ){
-
1903 helios_runtime_error("ERROR (PlantArchitecture::addBaseStemShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
1904 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
-
1905 helios_runtime_error("ERROR (PlantArchitecture::addBaseStemShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
-
1906 }
-
1907
-
1908 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
-
1909
-
1910 auto shoot_parameters = shoot_types.at(shoot_type_label);
-
1911 validateShootTypes(shoot_parameters);
-
1912
-
1913 if(current_node_number > shoot_parameters.max_nodes.val() ){
-
1914 helios_runtime_error("ERROR (PlantArchitecture::addBaseStemShoot): 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()) + ".");
-
1915 }
-
1916
-
1917 uint shootID = shoot_tree_ptr->size();
-
1918 vec3 base_position = plant_instances.at(plantID).base_position;
-
1919
-
1920 // Create the new shoot
-
1921 auto* shoot_new = (new Shoot(plantID, shootID, -1, 0, 0, 0, base_position, base_rotation, current_node_number, internode_length_max, shoot_parameters, shoot_type_label, this));
-
1922 shoot_tree_ptr->emplace_back(shoot_new);
-
1923
-
1924 // Build phytomer geometry
-
1925 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper);
-
1926
-
1927 return shootID;
-
1928
-
1929}
+
1899
+
+
1900uint 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,
+
1901 float radius_taper, const std::string &shoot_type_label) {
+
1902
+
1903 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1904 helios_runtime_error("ERROR (PlantArchitecture::addBaseStemShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1905 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
+
1906 helios_runtime_error("ERROR (PlantArchitecture::addBaseStemShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
+
1907 }
+
1908
+
1909 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
1910
+
1911 auto shoot_parameters = shoot_types.at(shoot_type_label);
+
1912 validateShootTypes(shoot_parameters);
+
1913
+
1914 if(current_node_number > shoot_parameters.max_nodes.val() ){
+
1915 helios_runtime_error("ERROR (PlantArchitecture::addBaseStemShoot): 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()) + ".");
+
1916 }
+
1917
+
1918 uint shootID = shoot_tree_ptr->size();
+
1919 vec3 base_position = plant_instances.at(plantID).base_position;
+
1920
+
1921 // Create the new shoot
+
1922 auto* shoot_new = (new Shoot(plantID, shootID, -1, 0, 0, 0, base_position, base_rotation, current_node_number, internode_length_max, shoot_parameters, shoot_type_label, this));
+
1923 shoot_tree_ptr->emplace_back(shoot_new);
+
1924
+
1925 // Build phytomer geometry
+
1926 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper);
+
1927
+
1928 return shootID;
+
1929
+
1930}
-
1930
-
-
1931uint 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,
-
1932 float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label) {
-
1933
-
1934 if( plant_instances.find(plantID) == plant_instances.end() ) {
-
1935 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
1936 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
-
1937 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
-
1938 }
-
1939
-
1940 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
-
1941
-
1942 auto shoot_parameters = shoot_types.at(shoot_type_label);
-
1943 validateShootTypes(shoot_parameters);
-
1944
-
1945 if( shoot_tree_ptr->empty() ){
-
1946 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Cannot append shoot to empty shoot. You must call addBaseStemShoot() first for each plant.");
-
1947 }else if( parent_shoot_ID >= int(shoot_tree_ptr->size()) ){
-
1948 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Parent with ID of " + std::to_string(parent_shoot_ID) + " does not exist.");
-
1949 }else if(current_node_number > shoot_parameters.max_nodes.val() ){
-
1950 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()) + ".");
-
1951 }else if( shoot_tree_ptr->at(parent_shoot_ID)->phytomers.empty() ){
-
1952 std::cerr << "WARNING (PlantArchitecture::appendShoot): Shoot does not have any phytomers to append." << std::endl;
-
1953 }
-
1954
-
1955 //stop parent shoot from producing new phytomers at the apex
-
1956 shoot_tree_ptr->at(parent_shoot_ID)->shoot_parameters.max_nodes = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number;
-
1957 shoot_tree_ptr->at(parent_shoot_ID)->terminateApicalBud(); //meristem should not keep growing after appending shoot
-
1958
-
1959 //accumulate all the values that will be passed to Shoot constructor
-
1960 int appended_shootID = int(shoot_tree_ptr->size());
-
1961 uint parent_node = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number-1;
-
1962 uint rank = shoot_tree_ptr->at(parent_shoot_ID)->rank;
-
1963 vec3 base_position = interpolateTube(shoot_tree_ptr->at(parent_shoot_ID)->phytomers.back()->getInternodeNodePositions(), 0.9f );
-
1964
-
1965 // Create the new shoot
-
1966 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));
-
1967 shoot_tree_ptr->emplace_back(shoot_new);
-
1968
-
1969 // Build phytomer geometry
-
1970 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper);
-
1971
-
1972 return appended_shootID;
-
1973
-
1974}
+
1931
+
+
1932uint 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,
+
1933 float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label) {
+
1934
+
1935 if( plant_instances.find(plantID) == plant_instances.end() ) {
+
1936 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1937 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
+
1938 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
+
1939 }
+
1940
+
1941 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
1942
+
1943 auto shoot_parameters = shoot_types.at(shoot_type_label);
+
1944 validateShootTypes(shoot_parameters);
+
1945
+
1946 if( shoot_tree_ptr->empty() ){
+
1947 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Cannot append shoot to empty shoot. You must call addBaseStemShoot() first for each plant.");
+
1948 }else if( parent_shoot_ID >= int(shoot_tree_ptr->size()) ){
+
1949 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Parent with ID of " + std::to_string(parent_shoot_ID) + " does not exist.");
+
1950 }else if(current_node_number > shoot_parameters.max_nodes.val() ){
+
1951 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()) + ".");
+
1952 }else if( shoot_tree_ptr->at(parent_shoot_ID)->phytomers.empty() ){
+
1953 std::cerr << "WARNING (PlantArchitecture::appendShoot): Shoot does not have any phytomers to append." << std::endl;
+
1954 }
+
1955
+
1956 //stop parent shoot from producing new phytomers at the apex
+
1957 shoot_tree_ptr->at(parent_shoot_ID)->shoot_parameters.max_nodes = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number;
+
1958 shoot_tree_ptr->at(parent_shoot_ID)->terminateApicalBud(); //meristem should not keep growing after appending shoot
+
1959
+
1960 //accumulate all the values that will be passed to Shoot constructor
+
1961 int appended_shootID = int(shoot_tree_ptr->size());
+
1962 uint parent_node = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number-1;
+
1963 uint rank = shoot_tree_ptr->at(parent_shoot_ID)->rank;
+
1964 vec3 base_position = interpolateTube(shoot_tree_ptr->at(parent_shoot_ID)->phytomers.back()->getInternodeNodePositions(), 0.9f );
+
1965
+
1966 // Create the new shoot
+
1967 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));
+
1968 shoot_tree_ptr->emplace_back(shoot_new);
+
1969
+
1970 // Build phytomer geometry
+
1971 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper);
+
1972
+
1973 return appended_shootID;
+
1974
+
1975}
-
1975
-
-
1976uint 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,
-
1977 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label, uint petiole_index) {
-
1978
-
1979 if( plant_instances.find(plantID) == plant_instances.end() ){
-
1980 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
1981 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
-
1982 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
-
1983 }
-
1984
-
1985 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
-
1986
-
1987 if(parent_shoot_ID <= -1 || parent_shoot_ID >= shoot_tree_ptr->size() ){
-
1988 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Parent with ID of " + std::to_string(parent_shoot_ID) + " does not exist.");
-
1989 }else if(shoot_tree_ptr->at(parent_shoot_ID)->phytomers.size() <= parent_node_index ) {
-
1990 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Parent shoot does not have a node " + std::to_string(parent_node_index) + ".");
-
1991 }
-
1992
-
1993 // accumulate all the values that will be passed to Shoot constructor
-
1994 auto shoot_parameters = shoot_types.at(shoot_type_label);
-
1995 validateShootTypes(shoot_parameters);
-
1996 uint parent_rank = (int)shoot_tree_ptr->at(parent_shoot_ID)->rank;
-
1997 int parent_node_count = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number;
-
1998 int childID = int(shoot_tree_ptr->size());
-
1999
-
2000 // Calculate the position of the shoot base
-
2001 auto parent_shoot_ptr = shoot_tree_ptr->at(parent_shoot_ID);
-
2002
-
2003 vec3 shoot_base_position = parent_shoot_ptr->shoot_internode_vertices.at(parent_node_index).back();
-
2004
-
2005 // Shift the shoot base position outward by the parent internode radius
-
2006 vec3 petiole_axis = parent_shoot_ptr->phytomers.at(parent_node_index)->getPetioleAxisVector(0,petiole_index);
-
2007 shoot_base_position += 0.9f * petiole_axis * parent_shoot_ptr->phytomers.at(parent_node_index)->getInternodeRadius(1.f);
-
2008
-
2009 // Create the new shoot
-
2010 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));
-
2011 shoot_tree_ptr->emplace_back(shoot_new);
-
2012
-
2013 // Build phytomer geometry
-
2014 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper);
-
2015
-
2016 return childID;
-
2017
-
2018}
+
1976
+
+
1977uint 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,
+
1978 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label, uint petiole_index) {
+
1979
+
1980 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1981 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1982 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
+
1983 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
+
1984 }
+
1985
+
1986 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
1987
+
1988 if(parent_shoot_ID <= -1 || parent_shoot_ID >= shoot_tree_ptr->size() ){
+
1989 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Parent with ID of " + std::to_string(parent_shoot_ID) + " does not exist.");
+
1990 }else if(shoot_tree_ptr->at(parent_shoot_ID)->phytomers.size() <= parent_node_index ) {
+
1991 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Parent shoot does not have a node " + std::to_string(parent_node_index) + ".");
+
1992 }
+
1993
+
1994 // accumulate all the values that will be passed to Shoot constructor
+
1995 auto shoot_parameters = shoot_types.at(shoot_type_label);
+
1996 validateShootTypes(shoot_parameters);
+
1997 uint parent_rank = (int)shoot_tree_ptr->at(parent_shoot_ID)->rank;
+
1998 int parent_node_count = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number;
+
1999 int childID = int(shoot_tree_ptr->size());
+
2000
+
2001 // Calculate the position of the shoot base
+
2002 auto parent_shoot_ptr = shoot_tree_ptr->at(parent_shoot_ID);
+
2003
+
2004 vec3 shoot_base_position = parent_shoot_ptr->shoot_internode_vertices.at(parent_node_index).back();
+
2005
+
2006 // Shift the shoot base position outward by the parent internode radius
+
2007 vec3 petiole_axis = parent_shoot_ptr->phytomers.at(parent_node_index)->getPetioleAxisVector(0,petiole_index);
+
2008 shoot_base_position += 0.9f * petiole_axis * parent_shoot_ptr->phytomers.at(parent_node_index)->getInternodeRadius(1.f);
+
2009
+
2010 // Create the new shoot
+
2011 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));
+
2012 shoot_tree_ptr->emplace_back(shoot_new);
+
2013
+
2014 // Build phytomer geometry
+
2015 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper);
+
2016
+
2017 return childID;
+
2018
+
2019}
-
2019
-
-
2020uint PlantArchitecture::addEpicormicShoot(uint plantID, int parent_shoot_ID, float parent_position_fraction, uint current_node_number, float zenith_perturbation_degrees, float internode_radius, float internode_length_max,
-
2021 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label) {
-
2022
-
2023 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2024 helios_runtime_error("ERROR (PlantArchitecture::addEpicormicShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2025 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
-
2026 helios_runtime_error("ERROR (PlantArchitecture::addEpicormicShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
-
2027 }
-
2028
-
2029 auto &parent_shoot = plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID);
-
2030
-
2031 uint parent_node_index = 0;
-
2032 if( parent_position_fraction>0 ){
-
2033 parent_node_index = std::ceil( parent_position_fraction * float(parent_shoot->phytomers.size()) ) - 1;
-
2034 }
-
2035
-
2036 vec3 petiole_axis = plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID)->phytomers.at(parent_node_index)->getPetioleAxisVector(0,0);
-
2037
-
2038 //\todo Figuring out how to set this correctly to make the shoot vertical, which avoids having to write a child shoot function.
-
2039 AxisRotation base_rotation = make_AxisRotation(0, acos_safe(petiole_axis.z), 0);
-
2040
-
2041 return addChildShoot(plantID, parent_shoot_ID, parent_node_index, current_node_number, base_rotation, internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper, shoot_type_label, 0);
-
2042
-
2043}
+
2020
+
+
2021uint PlantArchitecture::addEpicormicShoot(uint plantID, int parent_shoot_ID, float parent_position_fraction, uint current_node_number, float zenith_perturbation_degrees, float internode_radius, float internode_length_max,
+
2022 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label) {
+
2023
+
2024 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2025 helios_runtime_error("ERROR (PlantArchitecture::addEpicormicShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2026 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
+
2027 helios_runtime_error("ERROR (PlantArchitecture::addEpicormicShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
+
2028 }
+
2029
+
2030 auto &parent_shoot = plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID);
+
2031
+
2032 uint parent_node_index = 0;
+
2033 if( parent_position_fraction>0 ){
+
2034 parent_node_index = std::ceil( parent_position_fraction * float(parent_shoot->phytomers.size()) ) - 1;
+
2035 }
+
2036
+
2037 vec3 petiole_axis = plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID)->phytomers.at(parent_node_index)->getPetioleAxisVector(0,0);
+
2038
+
2039 //\todo Figuring out how to set this correctly to make the shoot vertical, which avoids having to write a child shoot function.
+
2040 AxisRotation base_rotation = make_AxisRotation(0, acos_safe(petiole_axis.z), 0);
+
2041
+
2042 return addChildShoot(plantID, parent_shoot_ID, parent_node_index, current_node_number, base_rotation, internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper, shoot_type_label, 0);
+
2043
+
2044}
-
2044
-
2045void PlantArchitecture::validateShootTypes( ShootParameters &shoot_parameters ) const{
-
2046
-
2047 assert( shoot_parameters.child_shoot_type_probabilities.size() == shoot_parameters.child_shoot_type_labels.size() );
-
2048
-
2049 for( int ind = shoot_parameters.child_shoot_type_labels.size()-1; ind>=0; ind-- ){
-
2050 if( shoot_types.find(shoot_parameters.child_shoot_type_labels.at(ind)) == shoot_types.end() ){
-
2051 shoot_parameters.child_shoot_type_labels.erase(shoot_parameters.child_shoot_type_labels.begin()+ind);
-
2052 shoot_parameters.child_shoot_type_probabilities.erase(shoot_parameters.child_shoot_type_probabilities.begin()+ind);
-
2053 }
-
2054 }
-
2055
-
2056}
-
2057
-
-
2058int PlantArchitecture::appendPhytomerToShoot(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) {
-
2059
-
2060 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2061 helios_runtime_error("ERROR (PlantArchitecture::appendPhytomerToShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2062 }
-
2063
-
2064 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
-
2065
-
2066 if(shootID >= shoot_tree_ptr->size() ){
-
2067 helios_runtime_error("ERROR (PlantArchitecture::appendPhytomerToShoot): Parent with ID of " + std::to_string(shootID) + " does not exist.");
-
2068 }
-
2069
-
2070 auto current_shoot_ptr = plant_instances.at(plantID).shoot_tree.at(shootID);
-
2071
-
2072 int pID = current_shoot_ptr->appendPhytomer(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction);
-
2073
-
2074 current_shoot_ptr->current_node_number ++;
-
2075
-
2076 for( auto &phytomers: current_shoot_ptr->phytomers ){
-
2077 phytomers->shoot_index.y = current_shoot_ptr->current_node_number;
-
2078 }
-
2079
-
2080 //If this shoot reached max nodes, add a terminal floral bud if max_terminal_floral_buds > 0
-
2081 if( current_shoot_ptr->current_node_number == current_shoot_ptr->shoot_parameters.max_nodes.val() ){
-
2082 if ( !current_shoot_ptr->shoot_parameters.flowers_require_dormancy && current_shoot_ptr->shoot_parameters.max_terminal_floral_buds.val() > 0) {
-
2083 current_shoot_ptr->addTerminalFloralBud();
-
2084 BudState state;
-
2085 if( current_shoot_ptr->shoot_parameters.phytomer_parameters.inflorescence.flower_prototype_function!=nullptr ){
-
2086 state = BUD_FLOWER_CLOSED;
-
2087 }else if( current_shoot_ptr->shoot_parameters.phytomer_parameters.inflorescence.fruit_prototype_function!=nullptr ) {
-
2088 state = BUD_FRUITING;
-
2089 }else{
-
2090 return pID;
-
2091 }
-
2092 for( auto &fbuds : current_shoot_ptr->phytomers.back()->floral_buds ) {
-
2093 for( auto &fbud : fbuds ) {
-
2094 if( fbud.isterminal ) {
-
2095 fbud.state = state;
-
2096 current_shoot_ptr->phytomers.back()->updateInflorescence(fbud);
-
2097 }
-
2098 }
-
2099 }
-
2100 }
-
2101 }
-
2102
-
2103 return pID;
-
2104
-
2105}
+
2045
+
2046void PlantArchitecture::validateShootTypes( ShootParameters &shoot_parameters ) const{
+
2047
+
2048 assert( shoot_parameters.child_shoot_type_probabilities.size() == shoot_parameters.child_shoot_type_labels.size() );
+
2049
+
2050 for( int ind = shoot_parameters.child_shoot_type_labels.size()-1; ind>=0; ind-- ){
+
2051 if( shoot_types.find(shoot_parameters.child_shoot_type_labels.at(ind)) == shoot_types.end() ){
+
2052 shoot_parameters.child_shoot_type_labels.erase(shoot_parameters.child_shoot_type_labels.begin()+ind);
+
2053 shoot_parameters.child_shoot_type_probabilities.erase(shoot_parameters.child_shoot_type_probabilities.begin()+ind);
+
2054 }
+
2055 }
+
2056
+
2057}
+
2058
+
+
2059int PlantArchitecture::appendPhytomerToShoot(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) {
+
2060
+
2061 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2062 helios_runtime_error("ERROR (PlantArchitecture::appendPhytomerToShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2063 }
+
2064
+
2065 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
2066
+
2067 if(shootID >= shoot_tree_ptr->size() ){
+
2068 helios_runtime_error("ERROR (PlantArchitecture::appendPhytomerToShoot): Parent with ID of " + std::to_string(shootID) + " does not exist.");
+
2069 }
+
2070
+
2071 auto current_shoot_ptr = plant_instances.at(plantID).shoot_tree.at(shootID);
+
2072
+
2073 int pID = current_shoot_ptr->appendPhytomer(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction);
+
2074
+
2075 current_shoot_ptr->current_node_number ++;
+
2076
+
2077 for( auto &phytomers: current_shoot_ptr->phytomers ){
+
2078 phytomers->shoot_index.y = current_shoot_ptr->current_node_number;
+
2079 }
+
2080
+
2081 //If this shoot reached max nodes, add a terminal floral bud if max_terminal_floral_buds > 0
+
2082 if( current_shoot_ptr->current_node_number == current_shoot_ptr->shoot_parameters.max_nodes.val() ){
+
2083 if ( !current_shoot_ptr->shoot_parameters.flowers_require_dormancy && current_shoot_ptr->shoot_parameters.max_terminal_floral_buds.val() > 0) {
+
2084 current_shoot_ptr->addTerminalFloralBud();
+
2085 BudState state;
+
2086 if( current_shoot_ptr->shoot_parameters.phytomer_parameters.inflorescence.flower_prototype_function!=nullptr ){
+
2087 state = BUD_FLOWER_CLOSED;
+
2088 }else if( current_shoot_ptr->shoot_parameters.phytomer_parameters.inflorescence.fruit_prototype_function!=nullptr ) {
+
2089 state = BUD_FRUITING;
+
2090 }else{
+
2091 return pID;
+
2092 }
+
2093 for( auto &fbuds : current_shoot_ptr->phytomers.back()->floral_buds ) {
+
2094 for( auto &fbud : fbuds ) {
+
2095 if( fbud.isterminal ) {
+
2096 fbud.state = state;
+
2097 current_shoot_ptr->phytomers.back()->updateInflorescence(fbud);
+
2098 }
+
2099 }
+
2100 }
+
2101 }
+
2102 }
+
2103
+
2104 return pID;
+
2105
+
2106}
-
2106
-
-
2107void PlantArchitecture::enableEpicormicChildShoots(uint plantID, const std::string &epicormic_shoot_type_label, float epicormic_probability_perlength_perday) {
-
2108
-
2109 if(shoot_types.find(epicormic_shoot_type_label) == shoot_types.end() ){
-
2110 helios_runtime_error("ERROR (PlantArchitecture::enableEpicormicChildShoots): Shoot type with label of " + epicormic_shoot_type_label + " does not exist.");
-
2111 }else if( epicormic_probability_perlength_perday<0 ){
-
2112 helios_runtime_error("ERROR (PlantArchitecture::enableEpicormicChildShoots): Epicormic probability must be greater than or equal to zero.");
-
2113 }else if( plant_instances.find(plantID) == plant_instances.end() ){
-
2114 helios_runtime_error("ERROR (PlantArchitecture::enableEpicormicChildShoots): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2115 }
-
2116
-
2117 plant_instances.at(plantID).epicormic_shoot_probability_perlength_per_day = std::make_pair(epicormic_shoot_type_label, epicormic_probability_perlength_perday);
-
2118
-
2119}
+
2107
+
+
2108void PlantArchitecture::enableEpicormicChildShoots(uint plantID, const std::string &epicormic_shoot_type_label, float epicormic_probability_perlength_perday) {
+
2109
+
2110 if(shoot_types.find(epicormic_shoot_type_label) == shoot_types.end() ){
+
2111 helios_runtime_error("ERROR (PlantArchitecture::enableEpicormicChildShoots): Shoot type with label of " + epicormic_shoot_type_label + " does not exist.");
+
2112 }else if( epicormic_probability_perlength_perday<0 ){
+
2113 helios_runtime_error("ERROR (PlantArchitecture::enableEpicormicChildShoots): Epicormic probability must be greater than or equal to zero.");
+
2114 }else if( plant_instances.find(plantID) == plant_instances.end() ){
+
2115 helios_runtime_error("ERROR (PlantArchitecture::enableEpicormicChildShoots): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2116 }
+
2117
+
2118 plant_instances.at(plantID).epicormic_shoot_probability_perlength_per_day = std::make_pair(epicormic_shoot_type_label, epicormic_probability_perlength_perday);
+
2119
+
2120}
-
2120
-
- -
2122 build_context_geometry_internode = false;
-
2123}
+
2121
+
+ +
2123 build_context_geometry_internode = false;
+
2124}
-
2124
-
- -
2126 build_context_geometry_petiole = false;
-
2127}
+
2125
+
+ +
2127 build_context_geometry_petiole = false;
+
2128}
-
2128
-
- -
2130 build_context_geometry_peduncle = false;
-
2131}
+
2129
+
+ +
2131 build_context_geometry_peduncle = false;
+
2132}
-
2132
-
- -
2134 ground_clipping_height = ground_height;
-
2135}
+
2133
+
+ +
2135 ground_clipping_height = ground_height;
+
2136}
-
2136
-
2137//void PlantArchitecture::incrementPhytomerInternodeGirth(uint plantID, uint shootID, uint node_number, float girth_change, bool update_context_geometry) {
-
2138//
-
2139// if( girth_change==0 ){
-
2140// return;
-
2141// }
-
2142//
-
2143// if( plant_instances.find(plantID) == plant_instances.end() ){
-
2144// helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2145// }
-
2146//
-
2147// auto shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
-
2148//
-
2149// if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
-
2150// helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
-
2151// }else if( node_number>=shoot->current_node_number ){
-
2152// helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Cannot scale internode " + std::to_string(node_number) + " because there are only " + std::to_string(shoot->current_node_number) + " nodes in this shoot.");
-
2153// }
-
2154//
-
2155// auto phytomer = shoot->phytomers.at(node_number);
-
2156//
-
2157// // Scale the girth of the internode
-
2158// auto &segment = shoot->shoot_internode_radii.at(node_number);
-
2159// for( float &radius : segment ) {
-
2160//
-
2161// float taper = 1.f - 0.5f * float(node_number) / float(shoot->current_node_number);
-
2162//
-
2163// if (radius * girth_change > phytomer->internode_radius_max) {
-
2164// girth_change = phytomer->internode_radius_max / radius;
-
2165// radius = phytomer->internode_radius_max;
-
2166// }else if( girth_change>1.f ) {
-
2167// radius *= 1.f + (girth_change - 1.f) * taper;
-
2168// }else{
-
2169// radius *= girth_change;
-
2170// }
-
2171//
-
2172// }
-
2173//
+
2137
+
2138//void PlantArchitecture::incrementPhytomerInternodeGirth(uint plantID, uint shootID, uint node_number, float girth_change, bool update_context_geometry) {
+
2139//
+
2140// if( girth_change==0 ){
+
2141// return;
+
2142// }
+
2143//
+
2144// if( plant_instances.find(plantID) == plant_instances.end() ){
+
2145// helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2146// }
+
2147//
+
2148// auto shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
2149//
+
2150// if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
2151// helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
+
2152// }else if( node_number>=shoot->current_node_number ){
+
2153// helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Cannot scale internode " + std::to_string(node_number) + " because there are only " + std::to_string(shoot->current_node_number) + " nodes in this shoot.");
+
2154// }
+
2155//
+
2156// auto phytomer = shoot->phytomers.at(node_number);
+
2157//
+
2158// // Scale the girth of the internode
+
2159// auto &segment = shoot->shoot_internode_radii.at(node_number);
+
2160// for( float &radius : segment ) {
+
2161//
+
2162// float taper = 1.f - 0.5f * float(node_number) / float(shoot->current_node_number);
+
2163//
+
2164// if (radius * girth_change > phytomer->internode_radius_max) {
+
2165// girth_change = phytomer->internode_radius_max / radius;
+
2166// radius = phytomer->internode_radius_max;
+
2167// }else if( girth_change>1.f ) {
+
2168// radius *= 1.f + (girth_change - 1.f) * taper;
+
2169// }else{
+
2170// radius *= girth_change;
+
2171// }
+
2172//
+
2173// }
2174//
-
2175// if( update_context_geometry ){
-
2176// context_ptr->setTubeRadii(shoot->internode_tube_objID, flatten(shoot->shoot_internode_radii) );
-
2177// }
-
2178//
-
2179//}
-
2180
-
2181void PlantArchitecture::incrementPhytomerInternodeGirth(uint plantID, uint shootID, uint node_number, bool update_context_geometry) {
-
2182
-
2183 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2184 helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2185 }
-
2186
-
2187 auto shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
-
2188
-
2189 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
-
2190 helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
-
2191 }else if( node_number>=shoot->current_node_number ){
-
2192 helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Cannot scale internode " + std::to_string(node_number) + " because there are only " + std::to_string(shoot->current_node_number) + " nodes in this shoot.");
-
2193 }
-
2194
-
2195 auto phytomer = shoot->phytomers.at(node_number);
-
2196
-
2197 float leaf_area = phytomer->calculateDownstreamLeafArea();
-
2198
-
2199 float internode_area = phytomer->parent_shoot_ptr->shoot_parameters.girth_area_factor.val()*leaf_area*1e-4;
-
2200 phytomer->parent_shoot_ptr->shoot_parameters.girth_area_factor.resample();
-
2201
-
2202 float phytomer_radius = sqrtf(internode_area / M_PI);
-
2203
-
2204 auto &segment = shoot->shoot_internode_radii.at(node_number);
-
2205 for( float &radius : segment ) {
-
2206 if( phytomer_radius > radius ) { //radius should only increase
-
2207 radius = phytomer_radius;
-
2208 }
-
2209 }
-
2210
-
2211 if( update_context_geometry ){
-
2212 context_ptr->setTubeRadii(shoot->internode_tube_objID, flatten(shoot->shoot_internode_radii) );
-
2213 }
-
2214
-
2215}
-
2216
-
2217void PlantArchitecture::setPhytomerLeafScale(uint plantID, uint shootID, uint node_number, float leaf_scale_factor_fraction) {
-
2218
-
2219 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2220 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerLeafScale): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2221 }
-
2222
-
2223 auto parent_shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
-
2224
-
2225 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
-
2226 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerLeafScale): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
-
2227 }else if( node_number>=parent_shoot->current_node_number ){
-
2228 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.");
-
2229 }
-
2230 if(leaf_scale_factor_fraction < 0 || leaf_scale_factor_fraction > 1 ){
-
2231 std::cerr << "WARNING (PlantArchitecture::setPhytomerLeafScale): Leaf scaling factor was outside the range of 0 to 1. No scaling was applied." << std::endl;
-
2232 return;
-
2233 }
-
2234
-
2235 parent_shoot->phytomers.at(node_number)->setLeafScaleFraction(leaf_scale_factor_fraction);
-
2236
-
2237}
-
2238
-
2239void PlantArchitecture::setPlantBasePosition(uint plantID, const helios::vec3 &base_position) {
-
2240
-
2241 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2242 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2243 }
-
2244
-
2245 plant_instances.at(plantID).base_position = base_position;
-
2246
-
2247 //\todo Does not work after shoots have been added to the plant.
-
2248 if( !plant_instances.at(plantID).shoot_tree.empty() ){
-
2249 std::cerr << "WARNING (PlantArchitecture::setPlantBasePosition): This function does not work after shoots have been added to the plant." << std::endl;
-
2250 }
-
2251
-
2252}
-
2253
-
2254helios::vec3 PlantArchitecture::getPlantBasePosition(uint plantID) const{
-
2255 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2256 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2257 }else if( plant_instances.at(plantID).shoot_tree.empty() ){
-
2258 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " has no shoots, so could not get a base position.");
-
2259 }
-
2260 return plant_instances.at(plantID).base_position;
-
2261}
-
2262
-
-
2263float PlantArchitecture::sumPlantLeafArea(uint plantID) const{
-
2264
-
2265 if( plantID>=plant_instances.size() ){
-
2266 helios_runtime_error("ERROR (PlantArchitecture::sumPlantLeafArea): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2267 }
-
2268
-
2269 std::vector<uint> leaf_objIDs = getPlantLeafObjectIDs(plantID);
-
2270
-
2271 float area = 0;
-
2272 for( uint objID : leaf_objIDs ){
-
2273 area += context_ptr->getObjectArea(objID);
-
2274 }
-
2275
-
2276 return area;
-
2277}
+
2175//
+
2176// if( update_context_geometry ){
+
2177// context_ptr->setTubeRadii(shoot->internode_tube_objID, flatten(shoot->shoot_internode_radii) );
+
2178// }
+
2179//
+
2180//}
+
2181
+
2182void PlantArchitecture::incrementPhytomerInternodeGirth(uint plantID, uint shootID, uint node_number, bool update_context_geometry) {
+
2183
+
2184 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2185 helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2186 }
+
2187
+
2188 auto shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
2189
+
2190 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
2191 helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
+
2192 }else if( node_number>=shoot->current_node_number ){
+
2193 helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Cannot scale internode " + std::to_string(node_number) + " because there are only " + std::to_string(shoot->current_node_number) + " nodes in this shoot.");
+
2194 }
+
2195
+
2196 auto phytomer = shoot->phytomers.at(node_number);
+
2197
+
2198 float leaf_area = phytomer->calculateDownstreamLeafArea();
+
2199
+
2200 float internode_area = phytomer->parent_shoot_ptr->shoot_parameters.girth_area_factor.val()*leaf_area*1e-4;
+
2201 phytomer->parent_shoot_ptr->shoot_parameters.girth_area_factor.resample();
+
2202
+
2203 float phytomer_radius = sqrtf(internode_area / M_PI);
+
2204
+
2205 auto &segment = shoot->shoot_internode_radii.at(node_number);
+
2206 for( float &radius : segment ) {
+
2207 if( phytomer_radius > radius ) { //radius should only increase
+
2208 radius = phytomer_radius;
+
2209 }
+
2210 }
+
2211
+
2212 if( update_context_geometry ){
+
2213 context_ptr->setTubeRadii(shoot->internode_tube_objID, flatten(shoot->shoot_internode_radii) );
+
2214 }
+
2215
+
2216}
+
2217
+
2218void PlantArchitecture::setPhytomerLeafScale(uint plantID, uint shootID, uint node_number, float leaf_scale_factor_fraction) {
+
2219
+
2220 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2221 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerLeafScale): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2222 }
+
2223
+
2224 auto parent_shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
2225
+
2226 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
2227 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerLeafScale): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
+
2228 }else if( node_number>=parent_shoot->current_node_number ){
+
2229 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.");
+
2230 }
+
2231 if(leaf_scale_factor_fraction < 0 || leaf_scale_factor_fraction > 1 ){
+
2232 std::cerr << "WARNING (PlantArchitecture::setPhytomerLeafScale): Leaf scaling factor was outside the range of 0 to 1. No scaling was applied." << std::endl;
+
2233 return;
+
2234 }
+
2235
+
2236 parent_shoot->phytomers.at(node_number)->setLeafScaleFraction(leaf_scale_factor_fraction);
+
2237
+
2238}
+
2239
+
2240void PlantArchitecture::setPlantBasePosition(uint plantID, const helios::vec3 &base_position) {
+
2241
+
2242 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2243 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2244 }
+
2245
+
2246 plant_instances.at(plantID).base_position = base_position;
+
2247
+
2248 //\todo Does not work after shoots have been added to the plant.
+
2249 if( !plant_instances.at(plantID).shoot_tree.empty() ){
+
2250 std::cerr << "WARNING (PlantArchitecture::setPlantBasePosition): This function does not work after shoots have been added to the plant." << std::endl;
+
2251 }
+
2252
+
2253}
+
2254
+
2255helios::vec3 PlantArchitecture::getPlantBasePosition(uint plantID) const{
+
2256 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2257 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2258 }else if( plant_instances.at(plantID).shoot_tree.empty() ){
+
2259 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " has no shoots, so could not get a base position.");
+
2260 }
+
2261 return plant_instances.at(plantID).base_position;
+
2262}
+
2263
+
+
2264float PlantArchitecture::sumPlantLeafArea(uint plantID) const{
+
2265
+
2266 if( plantID>=plant_instances.size() ){
+
2267 helios_runtime_error("ERROR (PlantArchitecture::sumPlantLeafArea): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2268 }
+
2269
+
2270 std::vector<uint> leaf_objIDs = getPlantLeafObjectIDs(plantID);
+
2271
+
2272 float area = 0;
+
2273 for( uint objID : leaf_objIDs ){
+
2274 area += context_ptr->getObjectArea(objID);
+
2275 }
+
2276
+
2277 return area;
+
2278}
-
2278
-
2279void PlantArchitecture::setPlantAge(uint plantID, float a_current_age) {
-
2280 //\todo
-
2281// this->current_age = current_age;
-
2282}
-
2283
-
2284float PlantArchitecture::getPlantAge(uint plantID) const{
-
2285 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2286 helios_runtime_error("ERROR (PlantArchitecture::setPlantAge): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2287 }else if( plant_instances.at(plantID).shoot_tree.empty() ){
-
2288 helios_runtime_error("ERROR (PlantArchitecture::setPlantAge): Plant with ID of " + std::to_string(plantID) + " has no shoots, so could not get a base position.");
-
2289 }
-
2290 return plant_instances.at(plantID).current_age;
-
2291}
-
2292
-
2293void PlantArchitecture::harvestPlant(uint plantID){
-
2294
-
2295 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2296 helios_runtime_error("ERROR (PlantArchitecture::harvestPlant): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2297 }
-
2298
-
2299 for( auto& shoot: plant_instances.at(plantID).shoot_tree ){
-
2300 for( auto& phytomer: shoot->phytomers ){
-
2301
-
2302 for( auto& petiole : phytomer->floral_buds ) {
-
2303 for (auto &fbud: petiole) {
-
2304 if (fbud.state != BUD_DORMANT) {
-
2305 phytomer->setFloralBudState(BUD_DEAD, fbud);
-
2306 }
-
2307 }
-
2308 }
-
2309
-
2310 }
-
2311 }
-
2312
-
2313}
-
2314
-
2315void PlantArchitecture::removeShootLeaves(uint plantID, uint shootID){
-
2316 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2317 helios_runtime_error("ERROR (PlantArchitecture::removePlantLeaves): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2318 }
-
2319
-
2320 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
-
2321 helios_runtime_error("ERROR (PlantArchitecture::removeShootLeaves): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
-
2322 }
-
2323
-
2324 auto& shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
-
2325
-
2326 for( auto& phytomer: shoot->phytomers ){
-
2327 phytomer->removeLeaf();
-
2328 }
-
2329
-
2330}
-
2331
-
2332void PlantArchitecture::removePlantLeaves(uint plantID ){
-
2333 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2334 helios_runtime_error("ERROR (PlantArchitecture::removePlantLeaves): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2335 }
-
2336
-
2337 for( auto& shoot: plant_instances.at(plantID).shoot_tree ){
-
2338 for( auto& phytomer: shoot->phytomers ){
-
2339 phytomer->removeLeaf();
-
2340 }
-
2341 }
-
2342}
-
2343
-
2344void PlantArchitecture::makePlantDormant( uint plantID ){
-
2345 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2346 helios_runtime_error("ERROR (PlantArchitecture::makePlantDormant): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2347 }
-
2348
-
2349 for( auto& shoot: plant_instances.at(plantID).shoot_tree ){
-
2350 shoot->makeDormant();
-
2351 }
-
2352}
-
2353
-
2354void PlantArchitecture::breakPlantDormancy( uint plantID ){
-
2355 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2356 helios_runtime_error("ERROR (PlantArchitecture::breakPlantDormancy): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2357 }
-
2358
-
2359 for( auto& shoot: plant_instances.at(plantID).shoot_tree ){
-
2360 shoot->breakDormancy();
-
2361 }
-
2362}
-
2363
+
2279
+
2280void PlantArchitecture::setPlantAge(uint plantID, float a_current_age) {
+
2281 //\todo
+
2282// this->current_age = current_age;
+
2283}
+
2284
+
2285float PlantArchitecture::getPlantAge(uint plantID) const{
+
2286 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2287 helios_runtime_error("ERROR (PlantArchitecture::setPlantAge): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2288 }else if( plant_instances.at(plantID).shoot_tree.empty() ){
+
2289 helios_runtime_error("ERROR (PlantArchitecture::setPlantAge): Plant with ID of " + std::to_string(plantID) + " has no shoots, so could not get a base position.");
+
2290 }
+
2291 return plant_instances.at(plantID).current_age;
+
2292}
+
2293
+
2294void PlantArchitecture::harvestPlant(uint plantID){
+
2295
+
2296 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2297 helios_runtime_error("ERROR (PlantArchitecture::harvestPlant): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2298 }
+
2299
+
2300 for( auto& shoot: plant_instances.at(plantID).shoot_tree ){
+
2301 for( auto& phytomer: shoot->phytomers ){
+
2302
+
2303 for( auto& petiole : phytomer->floral_buds ) {
+
2304 for (auto &fbud: petiole) {
+
2305 if (fbud.state != BUD_DORMANT) {
+
2306 phytomer->setFloralBudState(BUD_DEAD, fbud);
+
2307 }
+
2308 }
+
2309 }
+
2310
+
2311 }
+
2312 }
+
2313
+
2314}
+
2315
+
2316void PlantArchitecture::removeShootLeaves(uint plantID, uint shootID){
+
2317 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2318 helios_runtime_error("ERROR (PlantArchitecture::removePlantLeaves): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2319 }
+
2320
+
2321 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
2322 helios_runtime_error("ERROR (PlantArchitecture::removeShootLeaves): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
+
2323 }
+
2324
+
2325 auto& shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
2326
+
2327 for( auto& phytomer: shoot->phytomers ){
+
2328 phytomer->removeLeaf();
+
2329 }
+
2330
+
2331}
+
2332
+
2333void PlantArchitecture::removePlantLeaves(uint plantID ){
+
2334 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2335 helios_runtime_error("ERROR (PlantArchitecture::removePlantLeaves): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2336 }
+
2337
+
2338 for( auto& shoot: plant_instances.at(plantID).shoot_tree ){
+
2339 for( auto& phytomer: shoot->phytomers ){
+
2340 phytomer->removeLeaf();
+
2341 }
+
2342 }
+
2343}
+
2344
+
2345void PlantArchitecture::makePlantDormant( uint plantID ){
+
2346 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2347 helios_runtime_error("ERROR (PlantArchitecture::makePlantDormant): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2348 }
+
2349
+
2350 for( auto& shoot: plant_instances.at(plantID).shoot_tree ){
+
2351 shoot->makeDormant();
+
2352 }
+
2353}
+
2354
+
2355void PlantArchitecture::breakPlantDormancy( uint plantID ){
+
2356 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2357 helios_runtime_error("ERROR (PlantArchitecture::breakPlantDormancy): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2358 }
+
2359
+
2360 for( auto& shoot: plant_instances.at(plantID).shoot_tree ){
+
2361 shoot->breakDormancy();
+
2362 }
+
2363}
2364
-
2365uint PlantArchitecture::getShootNodeCount( uint plantID, uint shootID ) const{
-
2366 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2367 helios_runtime_error("ERROR (PlantArchitecture::getShootNodeCount): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2368 }else if( plant_instances.at(plantID).shoot_tree.size()<=shootID ){
-
2369 helios_runtime_error("ERROR (PlantArchitecture::getShootNodeCount): Shoot ID is out of range.");
-
2370 }
-
2371 return plant_instances.at(plantID).shoot_tree.at(shootID)->current_node_number;
-
2372}
-
2373
-
2374float PlantArchitecture::getShootTaper( uint plantID, uint shootID ) const{
-
2375
-
2376 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2377 helios_runtime_error("ERROR (PlantArchitecture::getShootTaper): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2378 }else if( plant_instances.at(plantID).shoot_tree.size()<=shootID ){
-
2379 helios_runtime_error("ERROR (PlantArchitecture::getShootTaper): Shoot ID is out of range.");
-
2380 }
-
2381
-
2382 float r0 = plant_instances.at(plantID).shoot_tree.at(shootID)->shoot_internode_radii.front().front();
-
2383 float r1 = plant_instances.at(plantID).shoot_tree.at(shootID)->shoot_internode_radii.back().back();
-
2384
-
2385 float taper = (r0-r1)/r0;
-
2386 if( taper<0 ){
-
2387 taper = 0;
-
2388 }else if( taper>1 ){
-
2389 taper = 1;
-
2390 }
-
2391
-
2392 return taper;
-
2393
-
2394}
-
2395
-
-
2396std::vector<uint> PlantArchitecture::getAllPlantObjectIDs(uint plantID) const{
-
2397
-
2398 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2399 helios_runtime_error("ERROR (PlantArchitecture::getAllPlantObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2400 }
-
2401
-
2402 std::vector<uint> objIDs;
-
2403
-
2404 for( const auto& shoot: plant_instances.at(plantID).shoot_tree ){
-
2405 objIDs.push_back(shoot->internode_tube_objID);
-
2406 for( const auto& phytomer: shoot->phytomers ){
-
2407 std::vector<uint> petiole_objIDs_flat = flatten(phytomer->petiole_objIDs);
-
2408 objIDs.insert(objIDs.end(), petiole_objIDs_flat.begin(), petiole_objIDs_flat.end() );
-
2409 std::vector<uint> leaf_objIDs_flat = flatten(phytomer->leaf_objIDs);
-
2410 objIDs.insert(objIDs.end(), leaf_objIDs_flat.begin(), leaf_objIDs_flat.end() );
-
2411 for( auto &petiole : phytomer->floral_buds ) {
-
2412 for( auto &fbud : petiole ) {
-
2413 std::vector<uint> inflorescence_objIDs_flat = fbud.inflorescence_objIDs;
-
2414 objIDs.insert(objIDs.end(), inflorescence_objIDs_flat.begin(), inflorescence_objIDs_flat.end());
-
2415 std::vector<uint> peduncle_objIDs_flat = fbud.peduncle_objIDs;
-
2416 objIDs.insert(objIDs.end(), peduncle_objIDs_flat.begin(), peduncle_objIDs_flat.end());
-
2417 }
-
2418 }
-
2419 }
-
2420 }
-
2421
-
2422 return objIDs;
-
2423
-
2424}
+
2365
+
2366uint PlantArchitecture::getShootNodeCount( uint plantID, uint shootID ) const{
+
2367 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2368 helios_runtime_error("ERROR (PlantArchitecture::getShootNodeCount): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2369 }else if( plant_instances.at(plantID).shoot_tree.size()<=shootID ){
+
2370 helios_runtime_error("ERROR (PlantArchitecture::getShootNodeCount): Shoot ID is out of range.");
+
2371 }
+
2372 return plant_instances.at(plantID).shoot_tree.at(shootID)->current_node_number;
+
2373}
+
2374
+
2375float PlantArchitecture::getShootTaper( uint plantID, uint shootID ) const{
+
2376
+
2377 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2378 helios_runtime_error("ERROR (PlantArchitecture::getShootTaper): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2379 }else if( plant_instances.at(plantID).shoot_tree.size()<=shootID ){
+
2380 helios_runtime_error("ERROR (PlantArchitecture::getShootTaper): Shoot ID is out of range.");
+
2381 }
+
2382
+
2383 float r0 = plant_instances.at(plantID).shoot_tree.at(shootID)->shoot_internode_radii.front().front();
+
2384 float r1 = plant_instances.at(plantID).shoot_tree.at(shootID)->shoot_internode_radii.back().back();
+
2385
+
2386 float taper = (r0-r1)/r0;
+
2387 if( taper<0 ){
+
2388 taper = 0;
+
2389 }else if( taper>1 ){
+
2390 taper = 1;
+
2391 }
+
2392
+
2393 return taper;
+
2394
+
2395}
+
2396
+
+
2397std::vector<uint> PlantArchitecture::getAllPlantObjectIDs(uint plantID) const{
+
2398
+
2399 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2400 helios_runtime_error("ERROR (PlantArchitecture::getAllPlantObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2401 }
+
2402
+
2403 std::vector<uint> objIDs;
+
2404
+
2405 for( const auto& shoot: plant_instances.at(plantID).shoot_tree ){
+
2406 objIDs.push_back(shoot->internode_tube_objID);
+
2407 for( const auto& phytomer: shoot->phytomers ){
+
2408 std::vector<uint> petiole_objIDs_flat = flatten(phytomer->petiole_objIDs);
+
2409 objIDs.insert(objIDs.end(), petiole_objIDs_flat.begin(), petiole_objIDs_flat.end() );
+
2410 std::vector<uint> leaf_objIDs_flat = flatten(phytomer->leaf_objIDs);
+
2411 objIDs.insert(objIDs.end(), leaf_objIDs_flat.begin(), leaf_objIDs_flat.end() );
+
2412 for( auto &petiole : phytomer->floral_buds ) {
+
2413 for( auto &fbud : petiole ) {
+
2414 std::vector<uint> inflorescence_objIDs_flat = fbud.inflorescence_objIDs;
+
2415 objIDs.insert(objIDs.end(), inflorescence_objIDs_flat.begin(), inflorescence_objIDs_flat.end());
+
2416 std::vector<uint> peduncle_objIDs_flat = fbud.peduncle_objIDs;
+
2417 objIDs.insert(objIDs.end(), peduncle_objIDs_flat.begin(), peduncle_objIDs_flat.end());
+
2418 }
+
2419 }
+
2420 }
+
2421 }
+
2422
+
2423 return objIDs;
+
2424
+
2425}
-
2425
-
-
2426std::vector<uint> PlantArchitecture::getAllPlantUUIDs(uint plantID) const{
-
2427 return context_ptr->getObjectPrimitiveUUIDs(getAllPlantObjectIDs(plantID));
-
2428}
+
2426
+
+
2427std::vector<uint> PlantArchitecture::getAllPlantUUIDs(uint plantID) const{
+
2428 return context_ptr->getObjectPrimitiveUUIDs(getAllPlantObjectIDs(plantID));
+
2429}
-
2429
-
-
2430std::vector<uint> PlantArchitecture::getPlantInternodeObjectIDs(uint plantID) const{
-
2431
-
2432 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2433 helios_runtime_error("ERROR (PlantArchitecture::getPlantInternodeObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2434 }
-
2435
-
2436 std::vector<uint> objIDs;
-
2437
-
2438 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
-
2439
-
2440 for( auto &shoot : shoot_tree ){
-
2441 objIDs.push_back( shoot->internode_tube_objID );
-
2442 }
-
2443
-
2444 return objIDs;
-
2445
-
2446}
+
2430
+
+
2431std::vector<uint> PlantArchitecture::getPlantInternodeObjectIDs(uint plantID) const{
+
2432
+
2433 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2434 helios_runtime_error("ERROR (PlantArchitecture::getPlantInternodeObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2435 }
+
2436
+
2437 std::vector<uint> objIDs;
+
2438
+
2439 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
2440
+
2441 for( auto &shoot : shoot_tree ){
+
2442 objIDs.push_back( shoot->internode_tube_objID );
+
2443 }
+
2444
+
2445 return objIDs;
+
2446
+
2447}
-
2447
-
-
2448std::vector<uint> PlantArchitecture::getPlantPetioleObjectIDs(uint plantID) const{
-
2449 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2450 helios_runtime_error("ERROR (PlantArchitecture::getPlantPetioleObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2451 }
-
2452
-
2453 std::vector<uint> objIDs;
-
2454
-
2455 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
-
2456
-
2457 for( auto &shoot : shoot_tree ){
-
2458 for( auto &phytomer : shoot->phytomers ){
-
2459 for( auto &petiole : phytomer->petiole_objIDs ){
-
2460 objIDs.insert(objIDs.end(), petiole.begin(), petiole.end() );
-
2461 }
-
2462 }
-
2463 }
-
2464
-
2465 return objIDs;
-
2466
-
2467}
+
2448
+
+
2449std::vector<uint> PlantArchitecture::getPlantPetioleObjectIDs(uint plantID) const{
+
2450 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2451 helios_runtime_error("ERROR (PlantArchitecture::getPlantPetioleObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2452 }
+
2453
+
2454 std::vector<uint> objIDs;
+
2455
+
2456 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
2457
+
2458 for( auto &shoot : shoot_tree ){
+
2459 for( auto &phytomer : shoot->phytomers ){
+
2460 for( auto &petiole : phytomer->petiole_objIDs ){
+
2461 objIDs.insert(objIDs.end(), petiole.begin(), petiole.end() );
+
2462 }
+
2463 }
+
2464 }
+
2465
+
2466 return objIDs;
+
2467
+
2468}
-
2468
-
-
2469std::vector<uint> PlantArchitecture::getPlantLeafObjectIDs(uint plantID) const{
-
2470 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2471 helios_runtime_error("ERROR (PlantArchitecture::getPlantLeafObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2472 }
-
2473
-
2474 std::vector<uint> objIDs;
-
2475
-
2476 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
-
2477
-
2478 for( auto &shoot : shoot_tree ){
-
2479 for( auto &phytomer : shoot->phytomers ){
-
2480 for( int petiole=0; petiole<phytomer->leaf_objIDs.size(); petiole++ ) {
-
2481 objIDs.insert(objIDs.end(), phytomer->leaf_objIDs.at(petiole).begin(), phytomer->leaf_objIDs.at(petiole).end());
-
2482 }
-
2483 }
-
2484 }
-
2485
-
2486 return objIDs;
-
2487
-
2488}
+
2469
+
+
2470std::vector<uint> PlantArchitecture::getPlantLeafObjectIDs(uint plantID) const{
+
2471 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2472 helios_runtime_error("ERROR (PlantArchitecture::getPlantLeafObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2473 }
+
2474
+
2475 std::vector<uint> objIDs;
+
2476
+
2477 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
2478
+
2479 for( auto &shoot : shoot_tree ){
+
2480 for( auto &phytomer : shoot->phytomers ){
+
2481 for( int petiole=0; petiole<phytomer->leaf_objIDs.size(); petiole++ ) {
+
2482 objIDs.insert(objIDs.end(), phytomer->leaf_objIDs.at(petiole).begin(), phytomer->leaf_objIDs.at(petiole).end());
+
2483 }
+
2484 }
+
2485 }
+
2486
+
2487 return objIDs;
+
2488
+
2489}
-
2489
-
-
2490std::vector<uint> PlantArchitecture::getPlantPeduncleObjectIDs(uint plantID) const{
-
2491
-
2492 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2493 helios_runtime_error("ERROR (PlantArchitecture::getPlantPeduncleObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2494 }
-
2495
-
2496 std::vector<uint> objIDs;
-
2497
-
2498 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
-
2499
-
2500 for( auto &shoot : shoot_tree ){
-
2501 for( auto &phytomer : shoot->phytomers ){
-
2502 for( auto &petiole : phytomer->floral_buds ) {
-
2503 for( auto &fbud : petiole ) {
-
2504 objIDs.insert(objIDs.end(), fbud.peduncle_objIDs.begin(), fbud.peduncle_objIDs.end());
-
2505 }
-
2506 }
-
2507 }
-
2508 }
-
2509
-
2510 return objIDs;
-
2511
-
2512}
+
2490
+
+
2491std::vector<uint> PlantArchitecture::getPlantPeduncleObjectIDs(uint plantID) const{
+
2492
+
2493 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2494 helios_runtime_error("ERROR (PlantArchitecture::getPlantPeduncleObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2495 }
+
2496
+
2497 std::vector<uint> objIDs;
+
2498
+
2499 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
2500
+
2501 for( auto &shoot : shoot_tree ){
+
2502 for( auto &phytomer : shoot->phytomers ){
+
2503 for( auto &petiole : phytomer->floral_buds ) {
+
2504 for( auto &fbud : petiole ) {
+
2505 objIDs.insert(objIDs.end(), fbud.peduncle_objIDs.begin(), fbud.peduncle_objIDs.end());
+
2506 }
+
2507 }
+
2508 }
+
2509 }
+
2510
+
2511 return objIDs;
+
2512
+
2513}
-
2513
-
-
2514std::vector<uint> PlantArchitecture::getPlantFlowerObjectIDs(uint plantID) const{
-
2515
-
2516 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2517 helios_runtime_error("ERROR (PlantArchitecture::getPlantInflorescenceObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2518 }
-
2519
-
2520 std::vector<uint> objIDs;
-
2521
-
2522 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
-
2523
-
2524 for( auto &shoot : shoot_tree ){
-
2525 for( auto &phytomer : shoot->phytomers ){
-
2526 for(int petiole=0; petiole<phytomer->floral_buds.size(); petiole++ ){
-
2527 for(int bud=0; bud<phytomer->floral_buds.at(petiole).size(); bud++ ){
-
2528 if(phytomer->floral_buds.at(petiole).at(bud).state == BUD_FLOWER_OPEN || phytomer->floral_buds.at(petiole).at(bud).state == BUD_FLOWER_CLOSED ) {
-
2529 objIDs.insert(objIDs.end(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.begin(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.end());
-
2530 }
-
2531 }
-
2532 }
-
2533 }
-
2534 }
-
2535
-
2536 return objIDs;
-
2537
+
2514
+
+
2515std::vector<uint> PlantArchitecture::getPlantFlowerObjectIDs(uint plantID) const{
+
2516
+
2517 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2518 helios_runtime_error("ERROR (PlantArchitecture::getPlantInflorescenceObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2519 }
+
2520
+
2521 std::vector<uint> objIDs;
+
2522
+
2523 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
2524
+
2525 for( auto &shoot : shoot_tree ){
+
2526 for( auto &phytomer : shoot->phytomers ){
+
2527 for(int petiole=0; petiole<phytomer->floral_buds.size(); petiole++ ){
+
2528 for(int bud=0; bud<phytomer->floral_buds.at(petiole).size(); bud++ ){
+
2529 if(phytomer->floral_buds.at(petiole).at(bud).state == BUD_FLOWER_OPEN || phytomer->floral_buds.at(petiole).at(bud).state == BUD_FLOWER_CLOSED ) {
+
2530 objIDs.insert(objIDs.end(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.begin(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.end());
+
2531 }
+
2532 }
+
2533 }
+
2534 }
+
2535 }
+
2536
+
2537 return objIDs;
2538
-
2539}
+
2539
+
2540}
-
2540
-
-
2541std::vector<uint> PlantArchitecture::getPlantFruitObjectIDs(uint plantID) const{
-
2542
-
2543 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2544 helios_runtime_error("ERROR (PlantArchitecture::getPlantInflorescenceObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2545 }
-
2546
-
2547 std::vector<uint> objIDs;
-
2548
-
2549 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
-
2550
-
2551 for( auto &shoot : shoot_tree ){
-
2552 for( auto &phytomer : shoot->phytomers ){
-
2553 for(int petiole=0; petiole<phytomer->floral_buds.size(); petiole++ ){
-
2554 for(int bud=0; bud<phytomer->floral_buds.at(petiole).size(); bud++ ){
-
2555 if(phytomer->floral_buds.at(petiole).at(bud).state == BUD_FRUITING ) {
-
2556 objIDs.insert(objIDs.end(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.begin(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.end());
-
2557 }
-
2558 }
-
2559 }
-
2560 }
-
2561 }
-
2562
-
2563 return objIDs;
-
2564
+
2541
+
+
2542std::vector<uint> PlantArchitecture::getPlantFruitObjectIDs(uint plantID) const{
+
2543
+
2544 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2545 helios_runtime_error("ERROR (PlantArchitecture::getPlantInflorescenceObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2546 }
+
2547
+
2548 std::vector<uint> objIDs;
+
2549
+
2550 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
2551
+
2552 for( auto &shoot : shoot_tree ){
+
2553 for( auto &phytomer : shoot->phytomers ){
+
2554 for(int petiole=0; petiole<phytomer->floral_buds.size(); petiole++ ){
+
2555 for(int bud=0; bud<phytomer->floral_buds.at(petiole).size(); bud++ ){
+
2556 if(phytomer->floral_buds.at(petiole).at(bud).state == BUD_FRUITING ) {
+
2557 objIDs.insert(objIDs.end(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.begin(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.end());
+
2558 }
+
2559 }
+
2560 }
+
2561 }
+
2562 }
+
2563
+
2564 return objIDs;
2565
-
2566}
+
2566
+
2567}
-
2567
-
-
2568uint PlantArchitecture::addPlantInstance(const helios::vec3 &base_position, float current_age) {
-
2569
-
2570 if( current_age<0 ){
-
2571 helios_runtime_error("ERROR (PlantArchitecture::addPlantInstance): Current age must be greater than or equal to zero.");
-
2572 }
-
2573
-
2574 PlantInstance instance(base_position, current_age, context_ptr);
-
2575
-
2576 plant_instances.emplace(plant_count, instance);
-
2577
-
2578 plant_count++;
-
2579
-
2580 return plant_count-1;
-
2581
-
2582}
+
2568
+
+
2569uint PlantArchitecture::addPlantInstance(const helios::vec3 &base_position, float current_age) {
+
2570
+
2571 if( current_age<0 ){
+
2572 helios_runtime_error("ERROR (PlantArchitecture::addPlantInstance): Current age must be greater than or equal to zero.");
+
2573 }
+
2574
+
2575 PlantInstance instance(base_position, current_age, context_ptr);
+
2576
+
2577 plant_instances.emplace(plant_count, instance);
+
2578
+
2579 plant_count++;
+
2580
+
2581 return plant_count-1;
+
2582
+
2583}
-
2583
-
-
2584uint PlantArchitecture::duplicatePlantInstance(uint plantID, const helios::vec3 &base_position, const AxisRotation &base_rotation, float current_age) {
-
2585
-
2586 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2587 helios_runtime_error("ERROR (PlantArchitecture::duplicatePlantInstance): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2588 }
-
2589
-
2590 auto plant_shoot_tree = &plant_instances.at(plantID).shoot_tree;
-
2591
-
2592 uint plantID_new = addPlantInstance(base_position, current_age);
-
2593
-
2594 if( plant_shoot_tree->empty() ){ //no shoots to add
-
2595 return plantID_new;
-
2596 }
-
2597 if( plant_shoot_tree->front()->phytomers.empty() ){ //no phytomers to add
-
2598 return plantID_new;
-
2599 }
-
2600
-
2601 for( auto shoot: *plant_shoot_tree ) {
-
2602
-
2603 uint shootID_new; //ID of the new shoot; will be set once the shoot is created on the first loop iteration
-
2604 for (int node = 0; node < shoot->current_node_number; node++) {
-
2605
-
2606 auto phytomer = shoot->phytomers.at(node);
-
2607 float internode_radius = phytomer->internode_radius_initial;
-
2608 float internode_length_max = phytomer->internode_length_max;
-
2609 float internode_scale_factor_fraction = phytomer->current_internode_scale_factor;
-
2610 float leaf_scale_factor_fraction = phytomer->current_leaf_scale_factor;
-
2611
-
2612 if (node == 0) {//first phytomer on shoot
-
2613 AxisRotation original_base_rotation = shoot->base_rotation;
-
2614 if(shoot->parent_shoot_ID == -1 ) { //first shoot on plant
-
2615 shootID_new = addBaseStemShoot(plantID_new, 1, original_base_rotation + base_rotation, internode_radius, internode_length_max, internode_scale_factor_fraction, leaf_scale_factor_fraction, 0, shoot->shoot_type_label);
-
2616 }else{ //child shoot
-
2617 uint parent_node = plant_shoot_tree->at(shoot->parent_shoot_ID)->parent_node_index;
-
2618 uint parent_petiole_index = 0;
-
2619 for( auto &petiole : phytomer->axillary_vegetative_buds ) {
-
2620 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, 0, shoot->shoot_type_label, parent_petiole_index);
-
2621 parent_petiole_index++;
-
2622 }
-
2623 }
-
2624 } else {
-
2625 //each phytomer needs to be added one-by-one to account for possible internodes/leaves that are not fully elongated
-
2626 appendPhytomerToShoot(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);
-
2627 }
-
2628
-
2629 }
-
2630
-
2631 }
-
2632
-
2633 return plantID_new;
-
2634
-
2635}
+
2584
+
+
2585uint PlantArchitecture::duplicatePlantInstance(uint plantID, const helios::vec3 &base_position, const AxisRotation &base_rotation, float current_age) {
+
2586
+
2587 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2588 helios_runtime_error("ERROR (PlantArchitecture::duplicatePlantInstance): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2589 }
+
2590
+
2591 auto plant_shoot_tree = &plant_instances.at(plantID).shoot_tree;
+
2592
+
2593 uint plantID_new = addPlantInstance(base_position, current_age);
+
2594
+
2595 if( plant_shoot_tree->empty() ){ //no shoots to add
+
2596 return plantID_new;
+
2597 }
+
2598 if( plant_shoot_tree->front()->phytomers.empty() ){ //no phytomers to add
+
2599 return plantID_new;
+
2600 }
+
2601
+
2602 for( auto shoot: *plant_shoot_tree ) {
+
2603
+
2604 uint shootID_new; //ID of the new shoot; will be set once the shoot is created on the first loop iteration
+
2605 for (int node = 0; node < shoot->current_node_number; node++) {
+
2606
+
2607 auto phytomer = shoot->phytomers.at(node);
+
2608 float internode_radius = phytomer->internode_radius_initial;
+
2609 float internode_length_max = phytomer->internode_length_max;
+
2610 float internode_scale_factor_fraction = phytomer->current_internode_scale_factor;
+
2611 float leaf_scale_factor_fraction = phytomer->current_leaf_scale_factor;
+
2612
+
2613 if (node == 0) {//first phytomer on shoot
+
2614 AxisRotation original_base_rotation = shoot->base_rotation;
+
2615 if(shoot->parent_shoot_ID == -1 ) { //first shoot on plant
+
2616 shootID_new = addBaseStemShoot(plantID_new, 1, original_base_rotation + base_rotation, internode_radius, internode_length_max, internode_scale_factor_fraction, leaf_scale_factor_fraction, 0, shoot->shoot_type_label);
+
2617 }else{ //child shoot
+
2618 uint parent_node = plant_shoot_tree->at(shoot->parent_shoot_ID)->parent_node_index;
+
2619 uint parent_petiole_index = 0;
+
2620 for( auto &petiole : phytomer->axillary_vegetative_buds ) {
+
2621 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, 0, shoot->shoot_type_label, parent_petiole_index);
+
2622 parent_petiole_index++;
+
2623 }
+
2624 }
+
2625 } else {
+
2626 //each phytomer needs to be added one-by-one to account for possible internodes/leaves that are not fully elongated
+
2627 appendPhytomerToShoot(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);
+
2628 }
+
2629
+
2630 }
+
2631
+
2632 }
+
2633
+
2634 return plantID_new;
+
2635
+
2636}
-
2636
-
- -
2638
-
2639 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2640 return;
-
2641 }
-
2642
-
2643 context_ptr->deleteObject(getAllPlantObjectIDs(plantID));
-
2644
-
2645 plant_instances.erase(plantID);
-
2646
-
2647}
+
2637
+
+ +
2639
+
2640 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2641 return;
+
2642 }
+
2643
+
2644 context_ptr->deleteObject(getAllPlantObjectIDs(plantID));
+
2645
+
2646 plant_instances.erase(plantID);
+
2647
+
2648}
-
2648
-
-
2649void PlantArchitecture::deletePlantInstance( const std::vector<uint> &plantIDs ){
-
2650
-
2651 for( uint ID : plantIDs ){
- -
2653 }
-
2654
-
2655}
+
2649
+
+
2650void PlantArchitecture::deletePlantInstance( const std::vector<uint> &plantIDs ){
+
2651
+
2652 for( uint ID : plantIDs ){
+ +
2654 }
+
2655
+
2656}
-
2656
-
-
2657void 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, bool is_evergreen) {
-
2658
-
2659 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2660 helios_runtime_error("ERROR (PlantArchitecture::setPlantPhenologicalThresholds): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2661 }
-
2662
-
2663 plant_instances.at(plantID).dd_to_dormancy_break = time_to_dormancy_break;
-
2664 plant_instances.at(plantID).dd_to_flower_initiation = time_to_flower_initiation;
-
2665 plant_instances.at(plantID).dd_to_flower_opening = time_to_flower_opening;
-
2666 plant_instances.at(plantID).dd_to_fruit_set = time_to_fruit_set;
-
2667 plant_instances.at(plantID).dd_to_fruit_maturity = time_to_fruit_maturity;
-
2668 plant_instances.at(plantID).dd_to_senescence = time_to_senescence;
-
2669 plant_instances.at(plantID).is_evergreen = is_evergreen;
-
2670
-
2671}
+
2657
+
+
2658void 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, bool is_evergreen) {
+
2659
+
2660 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2661 helios_runtime_error("ERROR (PlantArchitecture::setPlantPhenologicalThresholds): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2662 }
+
2663
+
2664 plant_instances.at(plantID).dd_to_dormancy_break = time_to_dormancy_break;
+
2665 plant_instances.at(plantID).dd_to_flower_initiation = time_to_flower_initiation;
+
2666 plant_instances.at(plantID).dd_to_flower_opening = time_to_flower_opening;
+
2667 plant_instances.at(plantID).dd_to_fruit_set = time_to_fruit_set;
+
2668 plant_instances.at(plantID).dd_to_fruit_maturity = time_to_fruit_maturity;
+
2669 plant_instances.at(plantID).dd_to_senescence = time_to_senescence;
+
2670 plant_instances.at(plantID).is_evergreen = is_evergreen;
+
2671
+
2672}
-
2672
-
2673void PlantArchitecture::disablePlantPhenology( uint plantID ){
-
2674 plant_instances.at(plantID).dd_to_dormancy_break = 0;
-
2675 plant_instances.at(plantID).dd_to_flower_initiation = -1;
-
2676 plant_instances.at(plantID).dd_to_flower_opening = -1;
-
2677 plant_instances.at(plantID).dd_to_fruit_set = -1;
-
2678 plant_instances.at(plantID).dd_to_fruit_maturity = -1;
-
2679 plant_instances.at(plantID).dd_to_senescence = 1e6;
-
2680}
-
2681
-
- -
2683
-
2684 for (auto &plant: plant_instances ) {
-
2685
-
2686 uint plantID = plant.first;
-
2687
-
2688 advanceTime(plantID, dt);
-
2689
-
2690 }
-
2691
-
2692}
+
2673
+
2674void PlantArchitecture::disablePlantPhenology( uint plantID ){
+
2675 plant_instances.at(plantID).dd_to_dormancy_break = 0;
+
2676 plant_instances.at(plantID).dd_to_flower_initiation = -1;
+
2677 plant_instances.at(plantID).dd_to_flower_opening = -1;
+
2678 plant_instances.at(plantID).dd_to_fruit_set = -1;
+
2679 plant_instances.at(plantID).dd_to_fruit_maturity = -1;
+
2680 plant_instances.at(plantID).dd_to_senescence = 1e6;
+
2681}
+
2682
+
+ +
2684
+
2685 for (auto &plant: plant_instances ) {
+
2686
+
2687 uint plantID = plant.first;
+
2688
+
2689 advanceTime(plantID, dt);
+
2690
+
2691 }
+
2692
+
2693}
-
2693
-
-
2694void PlantArchitecture::advanceTime( uint plantID, float dt ) {
-
2695
-
2696 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2697 helios_runtime_error("ERROR (PlantArchitecture::advanceTime): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2698 }
-
2699
-
2700 PlantInstance& plant_instance = plant_instances.at(plantID);
-
2701
-
2702 auto shoot_tree = &plant_instance.shoot_tree;
-
2703
-
2704 if( shoot_tree->empty() ){
-
2705 return;
-
2706 }
-
2707
-
2708 //accounting for case of dt>phyllochron
-
2709 float phyllochron_min = shoot_tree->front()->shoot_parameters.phyllochron.val();
-
2710 for ( int i=1; i<shoot_tree->size(); i++ ){
-
2711 if( shoot_tree->at(i)->shoot_parameters.phyllochron.val() < phyllochron_min ){
-
2712 phyllochron_min = shoot_tree->at(i)->shoot_parameters.phyllochron.val();
-
2713 }
-
2714 }
-
2715
-
2716 int Nsteps = std::floor(dt/phyllochron_min);
-
2717 float remainder_time = dt-phyllochron_min*float(Nsteps);
-
2718 if( remainder_time>0.f ){
-
2719 Nsteps++;
-
2720 }
-
2721
-
2722 for( int timestep=0; timestep<Nsteps; timestep++ ) {
-
2723
-
2724 float dt_max = phyllochron_min;
-
2725 if (timestep == Nsteps - 1 && remainder_time != 0.f ) {
-
2726 dt_max = remainder_time;
-
2727 }
-
2728
-
2729 plant_instance.current_age += dt_max;
-
2730
-
2731 if( plant_instance.current_age > plant_instance.dd_to_senescence ){
-
2732 std::cout << "Going dormant " << plant_instance.current_age << " " << plant_instance.dd_to_senescence << std::endl;
-
2733 for (const auto& shoot : *shoot_tree) {
-
2734 shoot->makeDormant();
-
2735 shoot->carbohydrate_pool_molC = 100;
-
2736 plant_instance.current_age = 0;
-
2737 }
-
2738 harvestPlant(plantID);
-
2739 continue;
-
2740 }
-
2741
-
2742 size_t shoot_count = shoot_tree->size();
-
2743 for ( int i=0; i<shoot_count; i++ ){
-
2744
-
2745 auto shoot = shoot_tree->at(i);
-
2746
-
2747 for( auto &phytomer : shoot->phytomers ){
-
2748
-
2749 phytomer->age += dt_max;
-
2750
-
2751 if(phytomer->phytomer_parameters.phytomer_callback_function != nullptr ) {
-
2752 phytomer->phytomer_parameters.phytomer_callback_function(phytomer);
-
2753 }
-
2754 }
-
2755
-
2756 // ****** PHENOLOGICAL TRANSITIONS ****** //
-
2757
-
2758 // breaking dormancy
-
2759 bool dormancy_broken_this_timestep = false;
-
2760 if (shoot->isdormant && plant_instance.current_age >= plant_instance.dd_to_dormancy_break) {
-
2761 shoot->breakDormancy();
-
2762 dormancy_broken_this_timestep = true;
-
2763 shoot->carbohydrate_pool_molC = 1e6;
-
2764 }
-
2765
-
2766 if (shoot->isdormant) { //dormant, don't do anything
-
2767 continue;
-
2768 }
-
2769
-
2770 for (auto &phytomer: shoot->phytomers) {
-
2771
-
2772 if (!shoot->isdormant) {
-
2773 phytomer->time_since_dormancy += dt_max;
-
2774 }
-
2775
-
2776 if (phytomer->floral_buds.empty() ) { //no floral buds - skip this phytomer
-
2777 continue;
-
2778 }
-
2779
-
2780 for (auto &petiole: phytomer->floral_buds) {
-
2781 for (auto &fbud: petiole) {
-
2782
-
2783 if (fbud.state != BUD_DORMANT && fbud.state != BUD_DEAD) {
-
2784 fbud.time_counter += dt_max;
-
2785 }
-
2786
-
2787 // -- Flowering -- //
-
2788 if (shoot->shoot_parameters.phytomer_parameters.inflorescence.flower_prototype_function != nullptr) { //user defined a flower prototype function
-
2789 // -- Flower initiation (closed flowers) -- //
-
2790 if (fbud.state == BUD_ACTIVE && plant_instance.dd_to_flower_initiation >= 0.f) { //bud is active and flower initiation is enabled
-
2791 if ((!shoot->shoot_parameters.flowers_require_dormancy && plant_instance.current_age >= plant_instance.dd_to_flower_initiation) ||
-
2792 (shoot->shoot_parameters.flowers_require_dormancy && phytomer->time_since_dormancy >= plant_instance.dd_to_flower_initiation)) {
-
2793 fbud.time_counter = 0;
-
2794 if (context_ptr->randu() < shoot->shoot_parameters.flower_bud_break_probability.val() ) {
-
2795 phytomer->setFloralBudState(BUD_FLOWER_CLOSED, fbud);
-
2796 } else {
-
2797 phytomer->setFloralBudState(BUD_DEAD, fbud);
-
2798 }
-
2799 if (shoot->shoot_parameters.determinate_shoot_growth) {
-
2800 shoot->terminateApicalBud();
-
2801 shoot->terminateAxillaryVegetativeBuds();
-
2802 }
-
2803 }
-
2804
-
2805 // -- Flower opening -- //
-
2806 } else if ((fbud.state == BUD_FLOWER_CLOSED && plant_instance.dd_to_flower_opening >= 0.f) ||
-
2807 (fbud.state == BUD_ACTIVE && plant_instance.dd_to_flower_initiation < 0.f && plant_instance.dd_to_flower_opening >= 0.f)) {
-
2808 if (fbud.time_counter >= plant_instance.dd_to_flower_opening) {
-
2809 fbud.time_counter = 0;
-
2810 if( fbud.state == BUD_FLOWER_CLOSED ) {
-
2811 phytomer->setFloralBudState(BUD_FLOWER_OPEN, fbud);
-
2812 }else{
-
2813 if (context_ptr->randu() < shoot->shoot_parameters.flower_bud_break_probability.val() ) {
-
2814 phytomer->setFloralBudState(BUD_FLOWER_OPEN, fbud);
-
2815 } else {
-
2816 phytomer->setFloralBudState(BUD_DEAD, fbud);
-
2817 }
-
2818 }
-
2819 if (shoot->shoot_parameters.determinate_shoot_growth) {
-
2820 shoot->terminateApicalBud();
-
2821 shoot->terminateAxillaryVegetativeBuds();
-
2822 }
-
2823 }
-
2824 }
-
2825 }
-
2826
-
2827 // -- Fruit Set -- //
-
2828 // If the flower bud is in a 'flowering' state, the fruit set occurs after a certain amount of time
-
2829 if (shoot->shoot_parameters.phytomer_parameters.inflorescence.fruit_prototype_function != nullptr) {
-
2830 if ((fbud.state == BUD_FLOWER_OPEN && plant_instance.dd_to_fruit_set >= 0.f) || //flower opened and fruit set is enabled
-
2831 (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
-
2832 (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
-
2833 if (fbud.time_counter >= plant_instance.dd_to_fruit_set) {
-
2834 fbud.time_counter = 0;
-
2835 if (context_ptr->randu() < shoot->shoot_parameters.fruit_set_probability.val() ) {
-
2836 phytomer->setFloralBudState(BUD_FRUITING, fbud);
-
2837 } else {
-
2838 phytomer->setFloralBudState(BUD_DEAD, fbud);
-
2839 }
-
2840 if (shoot->shoot_parameters.determinate_shoot_growth) {
-
2841 shoot->terminateApicalBud();
-
2842 shoot->terminateAxillaryVegetativeBuds();
-
2843 }
-
2844 }
-
2845 }
-
2846 }
-
2847
-
2848 }
-
2849 }
-
2850
-
2851 }
-
2852
-
2853 // ****** GROWTH/SCALING OF CURRENT PHYTOMERS/FRUIT ****** //
-
2854
-
2855 int node_index = 0;
-
2856 for (auto &phytomer: shoot->phytomers) {
-
2857
-
2858 //scale internode length
-
2859 if (phytomer->current_internode_scale_factor < 1) {
-
2860 float dL_internode = dt_max * shoot->shoot_parameters.elongation_rate.val() * phytomer->internode_length_max;
-
2861 float length_scale = fmin(1.f, (phytomer->getInternodeLength() + dL_internode) / phytomer->internode_length_max);
-
2862 phytomer->setInternodeLengthScaleFraction(length_scale, false);
-
2863 }
-
2864
-
2865 //scale internode girth
-
2866 float inode_radius = phytomer->getInternodeRadius();
-
2867 if (inode_radius < phytomer->internode_radius_max && shoot->shoot_parameters.girth_area_factor.val()>0.f ) {
-
2868 incrementPhytomerInternodeGirth(plantID, shoot->ID, node_index, false);
-
2869 }
-
2870
-
2871 node_index++;
-
2872 }
-
2873
-
2874 node_index = 0;
-
2875 for (auto &phytomer: shoot->phytomers) {
-
2876
-
2877 //scale petiole/leaves
-
2878 if (phytomer->hasLeaf() && phytomer->current_leaf_scale_factor <= 1) {
-
2879 float tip_ind = ceil(float(phytomer->leaf_size_max.front().size()-1)/2.f);
-
2880 float leaf_length = phytomer->current_leaf_scale_factor * phytomer->leaf_size_max.front().at(tip_ind);
-
2881 float dL_leaf = dt_max * shoot->shoot_parameters.elongation_rate.val() * phytomer->leaf_size_max.front().at(tip_ind);
-
2882 float scale = fmin(1.f, (leaf_length + dL_leaf) / phytomer->phytomer_parameters.leaf.prototype_scale.val() );
-
2883 phytomer->phytomer_parameters.leaf.prototype_scale.resample();
-
2884 phytomer->setLeafScaleFraction(scale);
-
2885 }
-
2886
-
2887 //Fruit Growth
-
2888 for (auto &petiole: phytomer->floral_buds) {
-
2889 for (auto &fbud: petiole) {
-
2890
-
2891 // If the floral bud it in a 'fruiting' state, the fruit grows with time
-
2892 if (fbud.state == BUD_FRUITING && fbud.time_counter > 0) {
-
2893 float scale = fmin(1, 0.25f + 0.75f * fbud.time_counter / plant_instance.dd_to_fruit_maturity);
-
2894 phytomer->setInflorescenceScaleFraction(fbud, scale);
-
2895 }
-
2896 }
-
2897 }
-
2898
-
2899 // ****** NEW CHILD SHOOTS FROM VEGETATIVE BUDS ****** //
-
2900 uint parent_petiole_index = 0;
-
2901 for (auto &petiole: phytomer->axillary_vegetative_buds) {
-
2902 for (auto &vbud: petiole) {
-
2903
-
2904 if (vbud.state == BUD_ACTIVE && phytomer->age + dt_max > shoot->shoot_parameters.vegetative_bud_break_time.val()) {
-
2905
-
2906 ShootParameters *new_shoot_parameters = &shoot_types.at(vbud.shoot_type_label);
-
2907 int parent_node_count = shoot->current_node_number;
-
2908
-
2909// float insertion_angle_adjustment = fmin(new_shoot_parameters->insertion_angle_tip.val() + new_shoot_parameters->insertion_angle_decay_rate.val() * float(parent_node_count - phytomer->shoot_index.x - 1), 90.f);
-
2910// AxisRotation base_rotation = make_AxisRotation(deg2rad(insertion_angle_adjustment), deg2rad(new_shoot_parameters->base_yaw.val()), deg2rad(new_shoot_parameters->base_roll.val()));
-
2911// new_shoot_parameters->base_yaw.resample();
-
2912// if( new_shoot_parameters->insertion_angle_decay_rate.val()==0 ){
-
2913// new_shoot_parameters->insertion_angle_tip.resample();
-
2914// }
-
2915 float insertion_angle_adjustment = fmin(shoot->shoot_parameters.insertion_angle_tip.val() + shoot->shoot_parameters.insertion_angle_decay_rate.val() * float(parent_node_count - phytomer->shoot_index.x - 1), 90.f);
-
2916 AxisRotation base_rotation = make_AxisRotation(deg2rad(insertion_angle_adjustment), deg2rad(new_shoot_parameters->base_yaw.val()), deg2rad(new_shoot_parameters->base_roll.val()));
-
2917 new_shoot_parameters->base_yaw.resample();
-
2918 if( shoot->shoot_parameters.insertion_angle_decay_rate.val()==0 ){
-
2919 shoot->shoot_parameters.insertion_angle_tip.resample();
-
2920 }
-
2921
-
2922 //scale the shoot internode length based on proximity from the tip
-
2923 float internode_length_max;
-
2924 if (new_shoot_parameters->growth_requires_dormancy) {
-
2925 internode_length_max = fmax(new_shoot_parameters->internode_length_max.val() - new_shoot_parameters->internode_length_decay_rate.val() * float(parent_node_count - phytomer->shoot_index.x - 1),
-
2926 new_shoot_parameters->internode_length_min.val());
-
2927 } else {
-
2928 internode_length_max = new_shoot_parameters->internode_length_max.val();
-
2929 }
-
2930
-
2931 float internode_radius = shoot_types.at(vbud.shoot_type_label).internode_radius_initial.val();
-
2932
-
2933// std::cout << "Adding child shoot of type " << vbud.shoot_type_label << std::endl;
-
2934
-
2935 uint childID = addChildShoot(plantID, shoot->ID, node_index, 1, base_rotation, internode_radius, internode_length_max, 0.01, 0.01, 0, vbud.shoot_type_label, parent_petiole_index);
-
2936
-
2937 phytomer->setVegetativeBudState( BUD_DEAD, vbud );
-
2938 vbud.shoot_ID = childID;
-
2939 shoot_tree->at(childID)->isdormant = false;
-
2940
-
2941 }
-
2942
-
2943 }
-
2944 parent_petiole_index++;
-
2945 }
-
2946
-
2947 // check for ground collisions
-
2948 if( ground_clipping_height!=-99999 ){
-
2949
-
2950 // internode
-
2951 if ( (phytomer->shoot_index.x==0 && phytomer->rank>0 ) && context_ptr->doesObjectExist(shoot->internode_tube_objID) && detectGroundCollision( shoot->internode_tube_objID ) ) {
-
2952 context_ptr->deleteObject(shoot->internode_tube_objID);
-
2953 shoot->terminateApicalBud();
-
2954 }
-
2955
-
2956 // leaves
-
2957 for( uint petiole=0; petiole<phytomer->leaf_objIDs.size(); petiole++ ) {
-
2958
-
2959 if ( detectGroundCollision(phytomer->leaf_objIDs.at(petiole)) ) {
-
2960 context_ptr->deleteObject(phytomer->leaf_objIDs.at(petiole));
-
2961 phytomer->leaf_objIDs.at(petiole).clear();
-
2962 phytomer->leaf_bases.at(petiole).clear();
-
2963 context_ptr->deleteObject(phytomer->petiole_objIDs.at(petiole));
-
2964 phytomer->petiole_objIDs.at(petiole).clear();
-
2965 }
-
2966
-
2967 }
-
2968
-
2969 //inflorescence
-
2970 for( auto &petiole : phytomer->floral_buds ) {
-
2971 for( auto &fbud : petiole ){
-
2972 for( int p=fbud.inflorescence_objIDs.size()-1; p>=0; p-- ){
-
2973 uint objID = fbud.inflorescence_objIDs.at(p);
-
2974 if ( detectGroundCollision(objID) ) {
-
2975 context_ptr->deleteObject(objID);
-
2976 fbud.inflorescence_objIDs.erase( fbud.inflorescence_objIDs.begin()+p );
-
2977 }
-
2978 }
-
2979 for( int p=fbud.peduncle_objIDs.size()-1; p>=0; p-- ){
-
2980 uint objID = fbud.peduncle_objIDs.at(p);
-
2981 if ( detectGroundCollision(objID) ) {
-
2982 context_ptr->deleteObject(fbud.peduncle_objIDs);
-
2983 context_ptr->deleteObject(fbud.inflorescence_objIDs);
-
2984 fbud.peduncle_objIDs.clear();
-
2985 fbud.inflorescence_objIDs.clear();
-
2986 break;
-
2987 }
-
2988 }
-
2989 }
-
2990 }
-
2991
-
2992 }
-
2993
-
2994 if( output_object_data.at("age") ) {
-
2995 if (shoot->build_context_geometry_internode) {
-
2996 //\todo This is redundant and only needs to be done once per shoot
-
2997 if( context_ptr->doesObjectExist(shoot->internode_tube_objID) ) {
-
2998 context_ptr->setObjectData(shoot->internode_tube_objID, "age", phytomer->age);
-
2999 }
-
3000 }
-
3001 if (phytomer->build_context_geometry_petiole) {
-
3002 context_ptr->setObjectData(phytomer->petiole_objIDs, "age", phytomer->age);
-
3003 }
-
3004 context_ptr->setObjectData(phytomer->leaf_objIDs, "age", phytomer->age);
-
3005 }
-
3006
-
3007 node_index++;
-
3008 }
-
3009
-
3010 // if shoot has reached max_nodes, stop apical growth
-
3011 if (shoot->current_node_number >= shoot->shoot_parameters.max_nodes.val()) {
-
3012 shoot->terminateApicalBud();
-
3013 }
-
3014
-
3015 // If the apical bud is dead, don't do anything more with the shoot
-
3016 if (!shoot->meristem_is_alive) {
-
3017 continue;
-
3018 }
-
3019
-
3020 // ****** PHYLLOCHRON - NEW PHYTOMERS ****** //
-
3021 shoot->phyllochron_counter += dt_max;
-
3022 if (shoot->phyllochron_counter >= float(shoot->shoot_parameters.leaf_flush_count) * shoot->shoot_parameters.phyllochron.val()) {
-
3023 float internode_radius = shoot->shoot_parameters.internode_radius_initial.val();
-
3024 float internode_length_max = shoot->internode_length_max_shoot_initial;
-
3025 for (int leaf = 0; leaf < shoot->shoot_parameters.leaf_flush_count; leaf++) {
-
3026 appendPhytomerToShoot(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
-
3027 }
-
3028 shoot->shoot_parameters.phyllochron.resample();
-
3029 shoot->phyllochron_counter = shoot->phyllochron_counter - float(shoot->shoot_parameters.leaf_flush_count) * shoot->shoot_parameters.phyllochron.val();
-
3030 }
-
3031
-
3032 // ****** EPICORMIC SHOOTS ****** //
-
3033 std::string epicormic_shoot_label = plant_instance.epicormic_shoot_probability_perlength_per_day.first;
-
3034 if( !epicormic_shoot_label.empty() ) {
-
3035 std::vector<float> epicormic_fraction;
-
3036 uint Nepicormic = shoot->sampleEpicormicShoot(dt, epicormic_fraction);
-
3037 for (int s = 0; s < Nepicormic; s++) {
-
3038 float internode_radius = shoot_types.at(epicormic_shoot_label).internode_radius_initial.val();
-
3039 shoot_types.at(epicormic_shoot_label).internode_radius_initial.resample();
-
3040 float internode_length_max = shoot_types.at(epicormic_shoot_label).internode_length_max.val();
-
3041 shoot_types.at(epicormic_shoot_label).internode_length_max.resample();
-
3042 std::cout << "Adding epicormic shoot" << std::endl;
-
3043 addEpicormicShoot(plantID, shoot->ID, epicormic_fraction.at(s), 1, 0, internode_radius, internode_length_max, 0.01, 0.01, 0, epicormic_shoot_label);
-
3044 }
-
3045 }
-
3046
-
3047 // **** subtract maintenance carbon costs **** //
-
3048 subtractShootMaintenanceCarbon(dt_max);
-
3049
-
3050 if( output_object_data.find("carbohydrate_concentration")!=output_object_data.end() ){
-
3051 float shoot_volume = shoot->calculateShootInternodeVolume();
-
3052 context_ptr->setObjectData( shoot->internode_tube_objID, "carbohydrate_concentration", shoot->carbohydrate_pool_molC / shoot_volume );
-
3053 }
-
3054
-
3055 }
-
3056
-
3057 }
-
3058
-
3059 //update Context geometry
-
3060 shoot_tree->front()->updateShootNodes(true);
-
3061
-
3062}
+
2694
+
+
2695void PlantArchitecture::advanceTime( uint plantID, float dt ) {
+
2696
+
2697 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2698 helios_runtime_error("ERROR (PlantArchitecture::advanceTime): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2699 }
+
2700
+
2701 PlantInstance& plant_instance = plant_instances.at(plantID);
+
2702
+
2703 auto shoot_tree = &plant_instance.shoot_tree;
+
2704
+
2705 if( shoot_tree->empty() ){
+
2706 return;
+
2707 }
+
2708
+
2709 //accounting for case of dt>phyllochron
+
2710 float phyllochron_min = shoot_tree->front()->shoot_parameters.phyllochron.val();
+
2711 for ( int i=1; i<shoot_tree->size(); i++ ){
+
2712 if( shoot_tree->at(i)->shoot_parameters.phyllochron.val() < phyllochron_min ){
+
2713 phyllochron_min = shoot_tree->at(i)->shoot_parameters.phyllochron.val();
+
2714 }
+
2715 }
+
2716
+
2717 int Nsteps = std::floor(dt/phyllochron_min);
+
2718 float remainder_time = dt-phyllochron_min*float(Nsteps);
+
2719 if( remainder_time>0.f ){
+
2720 Nsteps++;
+
2721 }
+
2722
+
2723 for( int timestep=0; timestep<Nsteps; timestep++ ) {
+
2724
+
2725 float dt_max = phyllochron_min;
+
2726 if (timestep == Nsteps - 1 && remainder_time != 0.f ) {
+
2727 dt_max = remainder_time;
+
2728 }
+
2729
+
2730 plant_instance.current_age += dt_max;
+
2731
+
2732 if( plant_instance.current_age > plant_instance.dd_to_senescence ){
+
2733 std::cout << "Going dormant" << std::endl;
+
2734 for (const auto& shoot : *shoot_tree) {
+
2735 shoot->makeDormant();
+
2736 shoot->carbohydrate_pool_molC = 100;
+
2737 plant_instance.current_age = 0;
+
2738 }
+
2739 harvestPlant(plantID);
+
2740 continue;
+
2741 }
+
2742
+
2743 size_t shoot_count = shoot_tree->size();
+
2744 for ( int i=0; i<shoot_count; i++ ){
+
2745
+
2746 auto shoot = shoot_tree->at(i);
+
2747
+
2748 for( auto &phytomer : shoot->phytomers ){
+
2749
+
2750 phytomer->age += dt_max;
+
2751
+
2752 if(phytomer->phytomer_parameters.phytomer_callback_function != nullptr ) {
+
2753 phytomer->phytomer_parameters.phytomer_callback_function(phytomer);
+
2754 }
+
2755 }
+
2756
+
2757 // ****** PHENOLOGICAL TRANSITIONS ****** //
+
2758
+
2759 // breaking dormancy
+
2760 bool dormancy_broken_this_timestep = false;
+
2761 if (shoot->isdormant && plant_instance.current_age >= plant_instance.dd_to_dormancy_break) {
+
2762 shoot->breakDormancy();
+
2763 dormancy_broken_this_timestep = true;
+
2764 shoot->carbohydrate_pool_molC = 1e6;
+
2765 }
+
2766
+
2767 if (shoot->isdormant) { //dormant, don't do anything
+
2768 continue;
+
2769 }
+
2770
+
2771 for (auto &phytomer: shoot->phytomers) {
+
2772
+
2773 if (!shoot->isdormant) {
+
2774 phytomer->time_since_dormancy += dt_max;
+
2775 }
+
2776
+
2777 if (phytomer->floral_buds.empty() ) { //no floral buds - skip this phytomer
+
2778 continue;
+
2779 }
+
2780
+
2781 for (auto &petiole: phytomer->floral_buds) {
+
2782 for (auto &fbud: petiole) {
+
2783
+
2784 if (fbud.state != BUD_DORMANT && fbud.state != BUD_DEAD) {
+
2785 fbud.time_counter += dt_max;
+
2786 }
+
2787
+
2788 // -- Flowering -- //
+
2789 if (shoot->shoot_parameters.phytomer_parameters.inflorescence.flower_prototype_function != nullptr) { //user defined a flower prototype function
+
2790 // -- Flower initiation (closed flowers) -- //
+
2791 if (fbud.state == BUD_ACTIVE && plant_instance.dd_to_flower_initiation >= 0.f) { //bud is active and flower initiation is enabled
+
2792 if ((!shoot->shoot_parameters.flowers_require_dormancy && plant_instance.current_age >= plant_instance.dd_to_flower_initiation) ||
+
2793 (shoot->shoot_parameters.flowers_require_dormancy && phytomer->time_since_dormancy >= plant_instance.dd_to_flower_initiation)) {
+
2794 fbud.time_counter = 0;
+
2795 if (context_ptr->randu() < shoot->shoot_parameters.flower_bud_break_probability.val() ) {
+
2796 phytomer->setFloralBudState(BUD_FLOWER_CLOSED, fbud);
+
2797 } else {
+
2798 phytomer->setFloralBudState(BUD_DEAD, fbud);
+
2799 }
+
2800 if (shoot->shoot_parameters.determinate_shoot_growth) {
+
2801 shoot->terminateApicalBud();
+
2802 shoot->terminateAxillaryVegetativeBuds();
+
2803 }
+
2804 }
+
2805
+
2806 // -- Flower opening -- //
+
2807 } else if ((fbud.state == BUD_FLOWER_CLOSED && plant_instance.dd_to_flower_opening >= 0.f) ||
+
2808 (fbud.state == BUD_ACTIVE && plant_instance.dd_to_flower_initiation < 0.f && plant_instance.dd_to_flower_opening >= 0.f)) {
+
2809 if (fbud.time_counter >= plant_instance.dd_to_flower_opening) {
+
2810 fbud.time_counter = 0;
+
2811 if( fbud.state == BUD_FLOWER_CLOSED ) {
+
2812 phytomer->setFloralBudState(BUD_FLOWER_OPEN, fbud);
+
2813 }else{
+
2814 if (context_ptr->randu() < shoot->shoot_parameters.flower_bud_break_probability.val() ) {
+
2815 phytomer->setFloralBudState(BUD_FLOWER_OPEN, fbud);
+
2816 } else {
+
2817 phytomer->setFloralBudState(BUD_DEAD, fbud);
+
2818 }
+
2819 }
+
2820 if (shoot->shoot_parameters.determinate_shoot_growth) {
+
2821 shoot->terminateApicalBud();
+
2822 shoot->terminateAxillaryVegetativeBuds();
+
2823 }
+
2824 }
+
2825 }
+
2826 }
+
2827
+
2828 // -- Fruit Set -- //
+
2829 // If the flower bud is in a 'flowering' state, the fruit set occurs after a certain amount of time
+
2830 if (shoot->shoot_parameters.phytomer_parameters.inflorescence.fruit_prototype_function != nullptr) {
+
2831 if ((fbud.state == BUD_FLOWER_OPEN && plant_instance.dd_to_fruit_set >= 0.f) || //flower opened and fruit set is enabled
+
2832 (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
+
2833 (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
+
2834 if (fbud.time_counter >= plant_instance.dd_to_fruit_set) {
+
2835 fbud.time_counter = 0;
+
2836 if (context_ptr->randu() < shoot->shoot_parameters.fruit_set_probability.val() ) {
+
2837 phytomer->setFloralBudState(BUD_FRUITING, fbud);
+
2838 } else {
+
2839 phytomer->setFloralBudState(BUD_DEAD, fbud);
+
2840 }
+
2841 if (shoot->shoot_parameters.determinate_shoot_growth) {
+
2842 shoot->terminateApicalBud();
+
2843 shoot->terminateAxillaryVegetativeBuds();
+
2844 }
+
2845 }
+
2846 }
+
2847 }
+
2848
+
2849 }
+
2850 }
+
2851
+
2852 }
+
2853
+
2854 // ****** GROWTH/SCALING OF CURRENT PHYTOMERS/FRUIT ****** //
+
2855
+
2856 int node_index = 0;
+
2857 for (auto &phytomer: shoot->phytomers) {
+
2858
+
2859 //scale internode length
+
2860 if (phytomer->current_internode_scale_factor < 1) {
+
2861 float dL_internode = dt_max * shoot->shoot_parameters.elongation_rate.val() * phytomer->internode_length_max;
+
2862 float length_scale = fmin(1.f, (phytomer->getInternodeLength() + dL_internode) / phytomer->internode_length_max);
+
2863 phytomer->setInternodeLengthScaleFraction(length_scale, false);
+
2864 }
+
2865
+
2866 //scale internode girth
+
2867 float inode_radius = phytomer->getInternodeRadius();
+
2868 if (inode_radius < phytomer->internode_radius_max && shoot->shoot_parameters.girth_area_factor.val()>0.f ) {
+
2869 incrementPhytomerInternodeGirth(plantID, shoot->ID, node_index, false);
+
2870 }
+
2871
+
2872 node_index++;
+
2873 }
+
2874
+
2875 node_index = 0;
+
2876 for (auto &phytomer: shoot->phytomers) {
+
2877
+
2878 //scale petiole/leaves
+
2879 if (phytomer->hasLeaf() && phytomer->current_leaf_scale_factor <= 1) {
+
2880 float tip_ind = ceil(float(phytomer->leaf_size_max.front().size()-1)/2.f);
+
2881 float leaf_length = phytomer->current_leaf_scale_factor * phytomer->leaf_size_max.front().at(tip_ind);
+
2882 float dL_leaf = dt_max * shoot->shoot_parameters.elongation_rate.val() * phytomer->leaf_size_max.front().at(tip_ind);
+
2883 float scale = fmin(1.f, (leaf_length + dL_leaf) / phytomer->phytomer_parameters.leaf.prototype_scale.val() );
+
2884 phytomer->phytomer_parameters.leaf.prototype_scale.resample();
+
2885 phytomer->setLeafScaleFraction(scale);
+
2886 }
+
2887
+
2888 //Fruit Growth
+
2889 for (auto &petiole: phytomer->floral_buds) {
+
2890 for (auto &fbud: petiole) {
+
2891
+
2892 // If the floral bud it in a 'fruiting' state, the fruit grows with time
+
2893 if (fbud.state == BUD_FRUITING && fbud.time_counter > 0) {
+
2894 float scale = fmin(1, 0.25f + 0.75f * fbud.time_counter / plant_instance.dd_to_fruit_maturity);
+
2895 phytomer->setInflorescenceScaleFraction(fbud, scale);
+
2896 }
+
2897 }
+
2898 }
+
2899
+
2900 // ****** NEW CHILD SHOOTS FROM VEGETATIVE BUDS ****** //
+
2901 uint parent_petiole_index = 0;
+
2902 for (auto &petiole: phytomer->axillary_vegetative_buds) {
+
2903 for (auto &vbud: petiole) {
+
2904
+
2905 if (vbud.state == BUD_ACTIVE && phytomer->age + dt_max > shoot->shoot_parameters.vegetative_bud_break_time.val()) {
+
2906
+
2907 ShootParameters *new_shoot_parameters = &shoot_types.at(vbud.shoot_type_label);
+
2908 int parent_node_count = shoot->current_node_number;
+
2909
+
2910// float insertion_angle_adjustment = fmin(new_shoot_parameters->insertion_angle_tip.val() + new_shoot_parameters->insertion_angle_decay_rate.val() * float(parent_node_count - phytomer->shoot_index.x - 1), 90.f);
+
2911// AxisRotation base_rotation = make_AxisRotation(deg2rad(insertion_angle_adjustment), deg2rad(new_shoot_parameters->base_yaw.val()), deg2rad(new_shoot_parameters->base_roll.val()));
+
2912// new_shoot_parameters->base_yaw.resample();
+
2913// if( new_shoot_parameters->insertion_angle_decay_rate.val()==0 ){
+
2914// new_shoot_parameters->insertion_angle_tip.resample();
+
2915// }
+
2916 float insertion_angle_adjustment = fmin(shoot->shoot_parameters.insertion_angle_tip.val() + shoot->shoot_parameters.insertion_angle_decay_rate.val() * float(parent_node_count - phytomer->shoot_index.x - 1), 90.f);
+
2917 AxisRotation base_rotation = make_AxisRotation(deg2rad(insertion_angle_adjustment), deg2rad(new_shoot_parameters->base_yaw.val()), deg2rad(new_shoot_parameters->base_roll.val()));
+
2918 new_shoot_parameters->base_yaw.resample();
+
2919 if( shoot->shoot_parameters.insertion_angle_decay_rate.val()==0 ){
+
2920 shoot->shoot_parameters.insertion_angle_tip.resample();
+
2921 }
+
2922
+
2923 //scale the shoot internode length based on proximity from the tip
+
2924 float internode_length_max;
+
2925 if (new_shoot_parameters->growth_requires_dormancy) {
+
2926 internode_length_max = fmax(new_shoot_parameters->internode_length_max.val() - new_shoot_parameters->internode_length_decay_rate.val() * float(parent_node_count - phytomer->shoot_index.x - 1),
+
2927 new_shoot_parameters->internode_length_min.val());
+
2928 } else {
+
2929 internode_length_max = new_shoot_parameters->internode_length_max.val();
+
2930 }
+
2931
+
2932 float internode_radius = shoot_types.at(vbud.shoot_type_label).internode_radius_initial.val();
+
2933
+
2934// std::cout << "Adding child shoot of type " << vbud.shoot_type_label << std::endl;
+
2935
+
2936 uint childID = addChildShoot(plantID, shoot->ID, node_index, 1, base_rotation, internode_radius, internode_length_max, 0.01, 0.01, 0, vbud.shoot_type_label, parent_petiole_index);
+
2937
+
2938 phytomer->setVegetativeBudState( BUD_DEAD, vbud );
+
2939 vbud.shoot_ID = childID;
+
2940 shoot_tree->at(childID)->isdormant = false;
+
2941
+
2942 }
+
2943
+
2944 }
+
2945 parent_petiole_index++;
+
2946 }
+
2947
+
2948 // check for ground collisions
+
2949 if( ground_clipping_height!=-99999 ){
+
2950
+
2951 // internode
+
2952 if ( (phytomer->shoot_index.x==0 && phytomer->rank>0 ) && context_ptr->doesObjectExist(shoot->internode_tube_objID) && detectGroundCollision( shoot->internode_tube_objID ) ) {
+
2953 context_ptr->deleteObject(shoot->internode_tube_objID);
+
2954 shoot->terminateApicalBud();
+
2955 }
+
2956
+
2957 // leaves
+
2958 for( uint petiole=0; petiole<phytomer->leaf_objIDs.size(); petiole++ ) {
+
2959
+
2960 if ( detectGroundCollision(phytomer->leaf_objIDs.at(petiole)) ) {
+
2961 context_ptr->deleteObject(phytomer->leaf_objIDs.at(petiole));
+
2962 phytomer->leaf_objIDs.at(petiole).clear();
+
2963 phytomer->leaf_bases.at(petiole).clear();
+
2964 context_ptr->deleteObject(phytomer->petiole_objIDs.at(petiole));
+
2965 phytomer->petiole_objIDs.at(petiole).clear();
+
2966 }
+
2967
+
2968 }
+
2969
+
2970 //inflorescence
+
2971 for( auto &petiole : phytomer->floral_buds ) {
+
2972 for( auto &fbud : petiole ){
+
2973 for( int p=fbud.inflorescence_objIDs.size()-1; p>=0; p-- ){
+
2974 uint objID = fbud.inflorescence_objIDs.at(p);
+
2975 if ( detectGroundCollision(objID) ) {
+
2976 context_ptr->deleteObject(objID);
+
2977 fbud.inflorescence_objIDs.erase( fbud.inflorescence_objIDs.begin()+p );
+
2978 }
+
2979 }
+
2980 for( int p=fbud.peduncle_objIDs.size()-1; p>=0; p-- ){
+
2981 uint objID = fbud.peduncle_objIDs.at(p);
+
2982 if ( detectGroundCollision(objID) ) {
+
2983 context_ptr->deleteObject(fbud.peduncle_objIDs);
+
2984 context_ptr->deleteObject(fbud.inflorescence_objIDs);
+
2985 fbud.peduncle_objIDs.clear();
+
2986 fbud.inflorescence_objIDs.clear();
+
2987 break;
+
2988 }
+
2989 }
+
2990 }
+
2991 }
+
2992
+
2993 }
+
2994
+
2995 if( output_object_data.at("age") ) {
+
2996 if (shoot->build_context_geometry_internode) {
+
2997 //\todo This is redundant and only needs to be done once per shoot
+
2998 if( context_ptr->doesObjectExist(shoot->internode_tube_objID) ) {
+
2999 context_ptr->setObjectData(shoot->internode_tube_objID, "age", phytomer->age);
+
3000 }
+
3001 }
+
3002 if (phytomer->build_context_geometry_petiole) {
+
3003 context_ptr->setObjectData(phytomer->petiole_objIDs, "age", phytomer->age);
+
3004 }
+
3005 context_ptr->setObjectData(phytomer->leaf_objIDs, "age", phytomer->age);
+
3006 }
+
3007
+
3008 node_index++;
+
3009 }
+
3010
+
3011 // if shoot has reached max_nodes, stop apical growth
+
3012 if (shoot->current_node_number >= shoot->shoot_parameters.max_nodes.val()) {
+
3013 shoot->terminateApicalBud();
+
3014 }
+
3015
+
3016 // If the apical bud is dead, don't do anything more with the shoot
+
3017 if (!shoot->meristem_is_alive) {
+
3018 continue;
+
3019 }
+
3020
+
3021 // ****** PHYLLOCHRON - NEW PHYTOMERS ****** //
+
3022 shoot->phyllochron_counter += dt_max;
+
3023 if (shoot->phyllochron_counter >= float(shoot->shoot_parameters.leaf_flush_count) * shoot->shoot_parameters.phyllochron.val()) {
+
3024 float internode_radius = shoot->shoot_parameters.internode_radius_initial.val();
+
3025 float internode_length_max = shoot->internode_length_max_shoot_initial;
+
3026 for (int leaf = 0; leaf < shoot->shoot_parameters.leaf_flush_count; leaf++) {
+
3027 appendPhytomerToShoot(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
+
3028 }
+
3029 shoot->shoot_parameters.phyllochron.resample();
+
3030 shoot->phyllochron_counter = shoot->phyllochron_counter - float(shoot->shoot_parameters.leaf_flush_count) * shoot->shoot_parameters.phyllochron.val();
+
3031 }
+
3032
+
3033 // ****** EPICORMIC SHOOTS ****** //
+
3034 std::string epicormic_shoot_label = plant_instance.epicormic_shoot_probability_perlength_per_day.first;
+
3035 if( !epicormic_shoot_label.empty() ) {
+
3036 std::vector<float> epicormic_fraction;
+
3037 uint Nepicormic = shoot->sampleEpicormicShoot(dt, epicormic_fraction);
+
3038 for (int s = 0; s < Nepicormic; s++) {
+
3039 float internode_radius = shoot_types.at(epicormic_shoot_label).internode_radius_initial.val();
+
3040 shoot_types.at(epicormic_shoot_label).internode_radius_initial.resample();
+
3041 float internode_length_max = shoot_types.at(epicormic_shoot_label).internode_length_max.val();
+
3042 shoot_types.at(epicormic_shoot_label).internode_length_max.resample();
+
3043 std::cout << "Adding epicormic shoot" << std::endl;
+
3044 addEpicormicShoot(plantID, shoot->ID, epicormic_fraction.at(s), 1, 0, internode_radius, internode_length_max, 0.01, 0.01, 0, epicormic_shoot_label);
+
3045 }
+
3046 }
+
3047
+
3048 // **** subtract maintenance carbon costs **** //
+
3049 subtractShootMaintenanceCarbon(dt_max);
+
3050
+
3051 if( output_object_data.find("carbohydrate_concentration")!=output_object_data.end() ){
+
3052 float shoot_volume = shoot->calculateShootInternodeVolume();
+
3053 context_ptr->setObjectData( shoot->internode_tube_objID, "carbohydrate_concentration", shoot->carbohydrate_pool_molC / shoot_volume );
+
3054 }
+
3055
+
3056 }
+
3057
+
3058 }
+
3059
+
3060 //update Context geometry
+
3061 shoot_tree->front()->updateShootNodes(true);
+
3062
+
3063}
-
3063
-
3064std::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) {
-
3065
-
3066 uint Nverts = vertices.size();
-
3067
-
3068 if( radii.size()!=Nverts || colors.size()!=Nverts ){
-
3069 helios_runtime_error("ERROR (makeTubeFromCones): Length of vertex vectors is not consistent.");
-
3070 }
-
3071
-
3072 std::vector<uint> objIDs(Nverts-1);
-
3073
-
3074 for( uint v=0; v<Nverts-1; v++ ){
-
3075
-
3076 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) );
-
3077
-
3078 }
-
3079
-
3080 return objIDs;
-
3081
-
3082}
-
3083
-
3084bool PlantArchitecture::detectGroundCollision(uint objID) {
-
3085 std::vector<uint> objIDs = {objID};
-
3086 return detectGroundCollision(objIDs);
-
3087}
-
3088
-
3089bool PlantArchitecture::detectGroundCollision(const std::vector<uint> &objID) {
-
3090
-
3091 for( uint ID : objID ){
-
3092 if( context_ptr->doesObjectExist(ID) ) {
-
3093 const std::vector<uint> &UUIDs = context_ptr->getObjectPrimitiveUUIDs(ID);
-
3094 for (uint UUID: UUIDs) {
-
3095 const std::vector<vec3> &vertices = context_ptr->getPrimitiveVertices(UUID);
-
3096 for (const vec3 &v: vertices) {
-
3097 if (v.z < ground_clipping_height) {
-
3098 return true;
-
3099 }
-
3100 }
-
3101 }
-
3102 }
-
3103 }
-
3104 return false;
-
3105
-
3106}
-
3107
-
-
3108void PlantArchitecture::optionalOutputObjectData( const std::string &object_data_label ){
-
3109 if( output_object_data.find(object_data_label)==output_object_data.end() ){
-
3110 std::cerr << "WARNING (PlantArchitecture::optionalOutputObjectData): Output object data of '" << object_data_label << "' is not a valid option." << std::endl;
-
3111 return;
-
3112 }
-
3113 output_object_data.at(object_data_label) = true;
-
3114}
+
3064
+
3065std::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) {
+
3066
+
3067 uint Nverts = vertices.size();
+
3068
+
3069 if( radii.size()!=Nverts || colors.size()!=Nverts ){
+
3070 helios_runtime_error("ERROR (makeTubeFromCones): Length of vertex vectors is not consistent.");
+
3071 }
+
3072
+
3073 std::vector<uint> objIDs(Nverts-1);
+
3074
+
3075 for( uint v=0; v<Nverts-1; v++ ){
+
3076
+
3077 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) );
+
3078
+
3079 }
+
3080
+
3081 return objIDs;
+
3082
+
3083}
+
3084
+
3085bool PlantArchitecture::detectGroundCollision(uint objID) {
+
3086 std::vector<uint> objIDs = {objID};
+
3087 return detectGroundCollision(objIDs);
+
3088}
+
3089
+
3090bool PlantArchitecture::detectGroundCollision(const std::vector<uint> &objID) {
+
3091
+
3092 for( uint ID : objID ){
+
3093 if( context_ptr->doesObjectExist(ID) ) {
+
3094 const std::vector<uint> &UUIDs = context_ptr->getObjectPrimitiveUUIDs(ID);
+
3095 for (uint UUID: UUIDs) {
+
3096 const std::vector<vec3> &vertices = context_ptr->getPrimitiveVertices(UUID);
+
3097 for (const vec3 &v: vertices) {
+
3098 if (v.z < ground_clipping_height) {
+
3099 return true;
+
3100 }
+
3101 }
+
3102 }
+
3103 }
+
3104 }
+
3105 return false;
+
3106
+
3107}
+
3108
+
+
3109void PlantArchitecture::optionalOutputObjectData( const std::string &object_data_label ){
+
3110 if( output_object_data.find(object_data_label)==output_object_data.end() ){
+
3111 std::cerr << "WARNING (PlantArchitecture::optionalOutputObjectData): Output object data of '" << object_data_label << "' is not a valid option." << std::endl;
+
3112 return;
+
3113 }
+
3114 output_object_data.at(object_data_label) = true;
+
3115}
-
3115
-
-
3116void PlantArchitecture::optionalOutputObjectData( const std::vector<std::string> &object_data_labels ){
-
3117 for( auto &label : object_data_labels){
-
3118 if( output_object_data.find(label)==output_object_data.end() ){
-
3119 std::cerr << "WARNING (PlantArchitecture::optionalOutputObjectData): Output object data of '" << label << "' is not a valid option." << std::endl;
-
3120 continue;
-
3121 }
-
3122 output_object_data.at(label) = true;
-
3123 }
-
3124}
+
3116
+
+
3117void PlantArchitecture::optionalOutputObjectData( const std::vector<std::string> &object_data_labels ){
+
3118 for( auto &label : object_data_labels){
+
3119 if( output_object_data.find(label)==output_object_data.end() ){
+
3120 std::cerr << "WARNING (PlantArchitecture::optionalOutputObjectData): Output object data of '" << label << "' is not a valid option." << std::endl;
+
3121 continue;
+
3122 }
+
3123 output_object_data.at(label) = true;
+
3124 }
+
3125}
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.
-
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, float radius_taper, const std::string &shoot_type_label, uint petiole_index=0)
Manually add a child shoot at the axillary bud of a phytomer.
-
int appendPhytomerToShoot(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.
-
std::vector< uint > getPlantFlowerObjectIDs(uint plantID) const
Get object IDs for all inflorescence objects for a given plant.
-
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, float radius_taper, 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 enableGroundClipping(float ground_height=0.f)
Enable automatic removal of organs that are below the ground plane.
-
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, float radius_taper, 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 > 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, bool is_evergreen=false)
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.
+
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
+
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, float radius_taper, const std::string &shoot_type_label, uint petiole_index=0)
Manually add a child shoot at the axillary bud of a phytomer.
+
int appendPhytomerToShoot(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.
+
std::vector< uint > getPlantFlowerObjectIDs(uint plantID) const
Get object IDs for all inflorescence objects for a given plant.
+
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, float radius_taper, 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 enableGroundClipping(float ground_height=0.f)
Enable automatic removal of organs that are below the ground plane.
+
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, float radius_taper, 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 > 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, bool is_evergreen=false)
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.
std::vector< uint > buildPlantCanopyFromLibrary(const helios::vec3 &canopy_center_position, const helios::vec2 &plant_spacing_xy, const helios::int2 &plant_count_xy, float age)
Build a canopy of regularly spaced plants based on the model currently loaded from the library.
-
void disablePeduncleContextBuild()
Do not build peduncle primitive geometry in the Context.
-
void deletePlantInstance(uint plantID)
Delete an existing plant instance.
-
void enableEpicormicChildShoots(uint plantID, const std::string &epicormic_shoot_type_label, float epicormic_probability_perlength_perday)
Enable shoot type to produce epicormic child shoots (water sprouts)
+
void disablePeduncleContextBuild()
Do not build peduncle primitive geometry in the Context.
+
void deletePlantInstance(uint plantID)
Delete an existing plant instance.
+
void enableEpicormicChildShoots(uint plantID, const std::string &epicormic_shoot_type_label, float epicormic_probability_perlength_perday)
Enable shoot type to produce epicormic child shoots (water sprouts)
void defineShootType(const std::string &shoot_type_label, const ShootParameters &shoot_params)
Define a new shoot type based on a set of ShootParameters.
-
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.
+
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 buildPlantInstanceFromLibrary(const helios::vec3 &base_position, float age)
Build a plant instance based on the model currently loaded from the library.
-
void optionalOutputObjectData(const std::string &object_data_label)
Add optional output object data values to the Context.
-
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.
-
std::vector< uint > getAllPlantObjectIDs(uint plantID) const
Get object IDs for all organs objects for a given plant.
-
uint addEpicormicShoot(uint plantID, int parent_shoot_ID, float parent_position_fraction, uint current_node_number, float zenith_perturbation_degrees, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label)
Manually add a child epicormic shoot (water sprout) at an arbitrary position along the shoot.
-
float sumPlantLeafArea(uint plantID) const
Sum the one-sided leaf area of all leaves in the 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 for all plants.
-
std::vector< uint > getPlantLeafObjectIDs(uint plantID) const
Get object IDs for all leaf objects for a given plant.
+
void optionalOutputObjectData(const std::string &object_data_label)
Add optional output object data values to the Context.
+
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.
+
std::vector< uint > getAllPlantObjectIDs(uint plantID) const
Get object IDs for all organs objects for a given plant.
+
uint addEpicormicShoot(uint plantID, int parent_shoot_ID, float parent_position_fraction, uint current_node_number, float zenith_perturbation_degrees, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label)
Manually add a child epicormic shoot (water sprout) at an arbitrary position along the shoot.
+
float sumPlantLeafArea(uint plantID) const
Sum the one-sided leaf area of all leaves in the 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 for all plants.
+
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:4174
void scaleGirth(float S)
Method to scale the girth of the cone.
Definition Context.cpp:4223
Stores the state associated with simulation.
Definition Context.h:1882
@@ -3379,22 +3380,22 @@
vec3 cross(const vec3 &a, const vec3 &b)
Cross product of two vec3 vectors.
-
void setInternodeMaxLength(float internode_length_max_new)
Set the fully-elongated (maximum) internode length.
+
void setInternodeMaxLength(float internode_length_max_new)
Set the fully-elongated (maximum) internode length.
std::vector< std::vector< helios::vec3 > > petiole_vertices
Coordinates of internode tube segments. Index is tube segment within internode.
-
void setInternodeMaxRadius(float internode_radius_max_new)
Set the maximum radius of the internode.
+
void setInternodeMaxRadius(float internode_radius_max_new)
Set the maximum radius of the internode.
helios::int3 shoot_index
.x = index of phytomer along shoot, .y = current number of phytomers on parent shoot,...
-
void setLeafScaleFraction(float leaf_scale_factor_fraction)
Set the leaf scale as a fraction of its total fully-elongated scale factor. Value is uniformly applie...
-
void setLeafPrototypeScale(float leaf_prototype_scale)
Set the fully-elongated (maximum) leaf prototype scale. Value is uniformly applied for all leaves/lea...
-
void scaleInternodeMaxLength(float scale_factor)
Scale the fully-elongated (maximum) internode length as a fraction of its current fully-elongated len...
+
void setLeafScaleFraction(float leaf_scale_factor_fraction)
Set the leaf scale as a fraction of its total fully-elongated scale factor. Value is uniformly applie...
+
void setLeafPrototypeScale(float leaf_prototype_scale)
Set the fully-elongated (maximum) leaf prototype scale. Value is uniformly applied for all leaves/lea...
+
void scaleInternodeMaxLength(float scale_factor)
Scale the fully-elongated (maximum) internode length as a fraction of its current fully-elongated len...
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, float plant_age)
void updateShootNodes(bool update_context_geometry=true)
Recalculate and apply the shoot's origin position and shift all downstream shoots.
-
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.
+
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.
int appendPhytomer(float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction)
Append a phytomer at the shoot apex.
-
uint sampleEpicormicShoot(float dt, std::vector< float > &epicormic_positions_fraction)
Randomly sample whether the shoot should produce an epicormic shoot (water sprout) over timestep.
+
uint sampleEpicormicShoot(float dt, std::vector< float > &epicormic_positions_fraction)
Randomly sample whether the shoot should produce an epicormic shoot (water sprout) over timestep.
ShootParameters()
Default constructor - does not set random number generator.
diff --git a/doc/html/_plant_architecture_8h.html b/doc/html/_plant_architecture_8h.html index 0eb7db4bc..0cde2b724 100644 --- a/doc/html/_plant_architecture_8h.html +++ b/doc/html/_plant_architecture_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_plant_architecture_8h_source.html b/doc/html/_plant_architecture_8h_source.html index c706b86a0..a33490b57 100644 --- a/doc/html/_plant_architecture_8h_source.html +++ b/doc/html/_plant_architecture_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -1312,53 +1312,53 @@
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.
-
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, float radius_taper, const std::string &shoot_type_label, uint petiole_index=0)
Manually add a child shoot at the axillary bud of a phytomer.
-
int appendPhytomerToShoot(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.
+
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
+
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, float radius_taper, const std::string &shoot_type_label, uint petiole_index=0)
Manually add a child shoot at the axillary bud of a phytomer.
+
int appendPhytomerToShoot(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.
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.
+
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.
-
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, float radius_taper, 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 enableGroundClipping(float ground_height=0.f)
Enable automatic removal of organs that are below the ground plane.
-
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, float radius_taper, 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 > 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, bool is_evergreen=false)
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.
+
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, float radius_taper, 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 enableGroundClipping(float ground_height=0.f)
Enable automatic removal of organs that are below the ground plane.
+
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, float radius_taper, 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 > 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, bool is_evergreen=false)
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.
std::vector< uint > buildPlantCanopyFromLibrary(const helios::vec3 &canopy_center_position, const helios::vec2 &plant_spacing_xy, const helios::int2 &plant_count_xy, float age)
Build a canopy of regularly spaced plants based on the model currently loaded from the library.
static int selfTest()
Unit test routines.
Definition selfTest.cpp:21
-
void disablePeduncleContextBuild()
Do not build peduncle primitive geometry in the Context.
-
void deletePlantInstance(uint plantID)
Delete an existing plant instance.
-
void enableEpicormicChildShoots(uint plantID, const std::string &epicormic_shoot_type_label, float epicormic_probability_perlength_perday)
Enable shoot type to produce epicormic child shoots (water sprouts)
+
void disablePeduncleContextBuild()
Do not build peduncle primitive geometry in the Context.
+
void deletePlantInstance(uint plantID)
Delete an existing plant instance.
+
void enableEpicormicChildShoots(uint plantID, const std::string &epicormic_shoot_type_label, float epicormic_probability_perlength_perday)
Enable shoot type to produce epicormic child shoots (water sprouts)
void defineShootType(const std::string &shoot_type_label, const ShootParameters &shoot_params)
Define a new shoot type based on a set of ShootParameters.
-
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.
+
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 buildPlantInstanceFromLibrary(const helios::vec3 &base_position, float age)
Build a plant instance based on the model currently loaded from the library.
-
void optionalOutputObjectData(const std::string &object_data_label)
Add optional output object data values to the Context.
-
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.
-
std::vector< uint > getAllPlantObjectIDs(uint plantID) const
Get object IDs for all organs objects for a given plant.
+
void optionalOutputObjectData(const std::string &object_data_label)
Add optional output object data values to the Context.
+
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.
+
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.
-
uint addEpicormicShoot(uint plantID, int parent_shoot_ID, float parent_position_fraction, uint current_node_number, float zenith_perturbation_degrees, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label)
Manually add a child epicormic shoot (water sprout) at an arbitrary position along the shoot.
-
float sumPlantLeafArea(uint plantID) const
Sum the one-sided leaf area of all leaves in the 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 for all plants.
-
std::vector< uint > getPlantLeafObjectIDs(uint plantID) const
Get object IDs for all leaf objects for a given plant.
+
uint addEpicormicShoot(uint plantID, int parent_shoot_ID, float parent_position_fraction, uint current_node_number, float zenith_perturbation_degrees, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label)
Manually add a child epicormic shoot (water sprout) at an arbitrary position along the shoot.
+
float sumPlantLeafArea(uint plantID) const
Sum the one-sided leaf area of all leaves in the 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 for all plants.
+
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:1882
float mean(const std::vector< float > &vect)
Mean value of a vector of floats.
Definition global.cpp:1002
-
void setInternodeMaxLength(float internode_length_max_new)
Set the fully-elongated (maximum) internode length.
+
void setInternodeMaxLength(float internode_length_max_new)
Set the fully-elongated (maximum) internode length.
std::vector< std::vector< helios::vec3 > > petiole_vertices
Coordinates of internode tube segments. Index is tube segment within internode.
-
void setInternodeMaxRadius(float internode_radius_max_new)
Set the maximum radius of the internode.
+
void setInternodeMaxRadius(float internode_radius_max_new)
Set the maximum radius of the internode.
float time_since_dormancy
Time since the phytomer last broke dormancy (=0 if currently dormant)
helios::int3 shoot_index
.x = index of phytomer along shoot, .y = current number of phytomers on parent shoot,...
-
void setLeafScaleFraction(float leaf_scale_factor_fraction)
Set the leaf scale as a fraction of its total fully-elongated scale factor. Value is uniformly applie...
+
void setLeafScaleFraction(float leaf_scale_factor_fraction)
Set the leaf scale as a fraction of its total fully-elongated scale factor. Value is uniformly applie...
float age
Time since the phytomer was created.
-
void setLeafPrototypeScale(float leaf_prototype_scale)
Set the fully-elongated (maximum) leaf prototype scale. Value is uniformly applied for all leaves/lea...
-
void scaleInternodeMaxLength(float scale_factor)
Scale the fully-elongated (maximum) internode length as a fraction of its current fully-elongated len...
+
void setLeafPrototypeScale(float leaf_prototype_scale)
Set the fully-elongated (maximum) leaf prototype scale. Value is uniformly applied for all leaves/lea...
+
void scaleInternodeMaxLength(float scale_factor)
Scale the fully-elongated (maximum) internode length as a fraction of its current fully-elongated len...
PhytomerParameters()
Default constructor - does not set random number generator.
void(* phytomer_callback_function)(std::shared_ptr< Phytomer > phytomer_ptr)
@@ -1371,9 +1371,9 @@
void updateShootNodes(bool update_context_geometry=true)
Recalculate and apply the shoot's origin position and shift all downstream shoots.
-
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.
+
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.
int appendPhytomer(float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction)
Append a phytomer at the shoot apex.
-
uint sampleEpicormicShoot(float dt, std::vector< float > &epicormic_positions_fraction)
Randomly sample whether the shoot should produce an epicormic shoot (water sprout) over timestep.
+
uint sampleEpicormicShoot(float dt, std::vector< float > &epicormic_positions_fraction)
Randomly sample whether the shoot should produce an epicormic shoot (water sprout) over timestep.
ShootParameters()
Default constructor - does not set random number generator.
diff --git a/doc/html/_plant_architecture_doc.html b/doc/html/_plant_architecture_doc.html index dd907f9a4..922429bdf 100644 --- a/doc/html/_plant_architecture_doc.html +++ b/doc/html/_plant_architecture_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -472,7 +472,7 @@

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...
+
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:5343

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 ){
@@ -530,7 +530,7 @@

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. +internode_radius_max RandomParameter_float unlimited meters Maximum internode radius for girth growth expansion. 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. @@ -548,7 +548,7 @@

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. +tortuosity RandomParameter_float 0 degrees/(meters)^0.5 Factor determining the amount of random "wiggle" in internode growth along the shoot. — Growth Parameters — @@ -612,8 +612,8 @@

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)
-\] + d\theta = -\frac{1}{2}\left(\theta\right)dL + T\xi(dL) +\]" src="form_162.png" width="165" height="32"/>

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$.

diff --git a/doc/html/_plant_library_8cpp.html b/doc/html/_plant_library_8cpp.html index 2848ff711..4132fcc5d 100644 --- a/doc/html/_plant_library_8cpp.html +++ b/doc/html/_plant_library_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_plant_library_8cpp_source.html b/doc/html/_plant_library_8cpp_source.html index 794932df3..c4d9339f8 100644 --- a/doc/html/_plant_library_8cpp_source.html +++ b/doc/html/_plant_library_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -304,7 +304,7 @@
200 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
201 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 24;
202 shoot_parameters_trunk.max_nodes = 20;
-
203 shoot_parameters_trunk.girth_area_factor = 35.f;
+
203 shoot_parameters_trunk.girth_area_factor = 15.f;
204 shoot_parameters_trunk.internode_radius_initial = 0.01;
205 shoot_parameters_trunk.vegetative_bud_break_probability = 0;
206 shoot_parameters_trunk.vegetative_bud_break_time = 0;
@@ -322,7 +322,7 @@
218 shoot_parameters_proleptic.max_nodes = 40;
219 shoot_parameters_proleptic.phyllochron = 0.9;
220 shoot_parameters_proleptic.elongation_rate = 0.25;
-
221 shoot_parameters_proleptic.girth_area_factor = 35.f;
+
221 shoot_parameters_proleptic.girth_area_factor = 15.f;
222 shoot_parameters_proleptic.vegetative_bud_break_probability = 0.15;
223 shoot_parameters_proleptic.vegetative_bud_break_time = 0;
224 shoot_parameters_proleptic.leaf_flush_count = 1;
@@ -439,7 +439,7 @@
335 phytomer_parameters_apple.internode.max_floral_buds_per_petiole = 1;
336
337 phytomer_parameters_apple.petiole.petioles_per_internode = 1;
-
338 phytomer_parameters_apple.petiole.pitch.uniformDistribution(-25,-40);
+
338 phytomer_parameters_apple.petiole.pitch.uniformDistribution(-40,-25);
339 phytomer_parameters_apple.petiole.taper = 0.1;
340 phytomer_parameters_apple.petiole.curvature = 0;
341 phytomer_parameters_apple.petiole.length = 0.04;
@@ -476,11 +476,11 @@
372 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
373 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 24;
374 shoot_parameters_trunk.max_nodes = 20;
-
375 shoot_parameters_trunk.girth_area_factor = 16.f;
+
375 shoot_parameters_trunk.girth_area_factor = 12.f;
376 shoot_parameters_trunk.internode_radius_initial = 0.01;
377 shoot_parameters_trunk.vegetative_bud_break_probability = 0;
378 shoot_parameters_trunk.vegetative_bud_break_time = 0;
-
379 shoot_parameters_trunk.tortuosity = 6;
+
379 shoot_parameters_trunk.tortuosity = 4;
380 shoot_parameters_trunk.internode_length_max = 0.05;
381 shoot_parameters_trunk.internode_length_decay_rate = 0;
382 shoot_parameters_trunk.defineChildShootTypes({"scaffold"},{1});
@@ -499,7 +499,7 @@
395 shoot_parameters_proleptic.vegetative_bud_break_time = 0;
396 shoot_parameters_proleptic.leaf_flush_count = 1;
397 shoot_parameters_proleptic.gravitropic_curvature = 500;
-
398 shoot_parameters_proleptic.tortuosity = 20;
+
398 shoot_parameters_proleptic.tortuosity = 10;
399 shoot_parameters_proleptic.internode_radius_initial = 0.006;
400 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 20, 25);
401 shoot_parameters_proleptic.insertion_angle_decay_rate = 20;
@@ -534,7 +534,7 @@
430 shoot_parameters_scaffold.max_nodes = 40;
431 shoot_parameters_scaffold.gravitropic_curvature = 400;
432 shoot_parameters_scaffold.internode_length_max = 0.04;
-
433 shoot_parameters_scaffold.tortuosity = 10;
+
433 shoot_parameters_scaffold.tortuosity = 6;
434 shoot_parameters_scaffold.defineChildShootTypes({"proleptic"},{1.0});
435
436 defineShootType("trunk", shoot_parameters_trunk);
@@ -1193,9 +1193,9 @@
1089 shoot_parameters_main.vegetative_bud_break_time = 1;
1090 shoot_parameters_main.phyllochron = 0.5;
1091 shoot_parameters_main.elongation_rate = 0.15;
-
1092 shoot_parameters_main.girth_area_factor = 4.f;
+
1092 shoot_parameters_main.girth_area_factor = 2.f;
1093 shoot_parameters_main.gravitropic_curvature = 300;
-
1094 shoot_parameters_main.tortuosity = 20;
+
1094 shoot_parameters_main.tortuosity = 10;
1095 shoot_parameters_main.internode_length_max.uniformDistribution(0.075,0.1);
1096 shoot_parameters_main.internode_length_decay_rate = 0;
1097 shoot_parameters_main.insertion_angle_tip = 45;
@@ -1221,1335 +1221,1336 @@
1117 shoot_parameters_cane.internode_radius_max = 0.1;
1118 shoot_parameters_cane.insertion_angle_tip.uniformDistribution(60, 120);
1119 shoot_parameters_cane.max_nodes = 9;
-
1120 shoot_parameters_cane.tortuosity = 1.5;
-
1121 shoot_parameters_cane.gravitropic_curvature = 10;
-
1122 shoot_parameters_cane.vegetative_bud_break_probability = 1.0;
-
1123 shoot_parameters_cane.defineChildShootTypes({"grapevine_shoot"},{1.f});
-
1124
-
1125 ShootParameters shoot_parameters_trunk = shoot_parameters_main;
-
1126 shoot_parameters_trunk.phytomer_parameters.internode.image_texture = "plugins/plantarchitecture/assets/textures/GrapeBark.jpg";
-
1127 shoot_parameters_trunk.phytomer_parameters.internode.pitch = 0;
-
1128 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
-
1129 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 25;
-
1130 shoot_parameters_trunk.phytomer_parameters.internode.max_floral_buds_per_petiole = 0;
-
1131 shoot_parameters_trunk.internode_radius_max = 1;
-
1132 shoot_parameters_trunk.phyllochron = 1.25;
-
1133 shoot_parameters_trunk.insertion_angle_tip = 90;
-
1134 shoot_parameters_trunk.max_nodes = 18;
-
1135 shoot_parameters_trunk.tortuosity = 1;
-
1136 shoot_parameters_trunk.vegetative_bud_break_probability = 0;
-
1137 shoot_parameters_trunk.defineChildShootTypes({"grapevine_shoot"},{1.f});
-
1138
-
1139 defineShootType("grapevine_trunk", shoot_parameters_trunk);
-
1140 defineShootType("grapevine_cane", shoot_parameters_cane);
-
1141 defineShootType("grapevine_shoot", shoot_parameters_main);
-
1142
-
1143}
-
1144
-
1145uint PlantArchitecture::buildGrapevineVSP(const helios::vec3 &base_position) {
-
1146
-
1147 if (shoot_types.empty()) {
-
1148 //automatically initialize redbud plant shoots
-
1149 initializeGrapevineVSPShoots();
-
1150 }
-
1151
-
1152 uint plantID = addPlantInstance(base_position, 0);
-
1153
-
1154 uint uID_stem = addBaseStemShoot(plantID, 17, make_AxisRotation(context_ptr->randu(0,0.05*M_PI), 0, 0), 0.04, 0.05, 1, 1, 0.1, "grapevine_trunk");
-
1155 //appendPhytomerToShoot( plantID, uID_stem, getCurrentShootParameters("grapevine_trunk").phytomer_parameters, 1e-3, 0.1, 1, 1 );
-
1156
-
1157 uint uID_cane_L = appendShoot( plantID, uID_stem, 8, make_AxisRotation(context_ptr->randu(float(0.45f*M_PI),0.52f*M_PI),0,M_PI), 0.015, 0.15, 1, 1, 0.6, "grapevine_cane" );
-
1158 uint uID_cane_R = appendShoot( plantID, uID_stem, 8, make_AxisRotation(context_ptr->randu(float(0.45f*M_PI),0.52f*M_PI),M_PI,M_PI), 0.015, 0.15, 1, 1, 0.6, "grapevine_cane" );
-
1159
-
1160// makePlantDormant(plantID);
-
1161
-
1162 removeShootLeaves( plantID, uID_stem );
-
1163 removeShootLeaves( plantID, uID_cane_L );
-
1164 removeShootLeaves( plantID, uID_cane_R );
-
1165
-
1166 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 5, 8, 25, false);
-
1167
-
1168 return plantID;
-
1169
-
1170}
-
1171
-
1172void PlantArchitecture::initializeOliveTreeShoots(){
-
1173
-
1174 // ---- Phytomer Parameters ---- //
-
1175
-
1176 PhytomerParameters phytomer_parameters_olive(context_ptr->getRandomGenerator());
-
1177
-
1178 phytomer_parameters_olive.internode.pitch = 0;
-
1179 phytomer_parameters_olive.internode.phyllotactic_angle.uniformDistribution(80, 100 );
-
1180 phytomer_parameters_olive.internode.length_segments = 1;
-
1181 phytomer_parameters_olive.internode.image_texture = "plugins/plantarchitecture/assets/textures/OliveBark.jpg";
-
1182 phytomer_parameters_olive.internode.max_floral_buds_per_petiole = 3;
-
1183
-
1184 phytomer_parameters_olive.petiole.petioles_per_internode = 2;
-
1185 phytomer_parameters_olive.petiole.pitch.uniformDistribution(-40,-20);
-
1186 phytomer_parameters_olive.petiole.taper = 0.1;
-
1187 phytomer_parameters_olive.petiole.curvature = 0;
-
1188 phytomer_parameters_olive.petiole.length = 0.01;
-
1189 phytomer_parameters_olive.petiole.radius = 0.0005;
-
1190 phytomer_parameters_olive.petiole.length_segments = 1;
-
1191 phytomer_parameters_olive.petiole.radial_subdivisions = 3;
-
1192 phytomer_parameters_olive.petiole.color = make_RGBcolor(0.61, 0.5, 0.24);
-
1193
-
1194 phytomer_parameters_olive.leaf.leaves_per_petiole = 1;
-
1195 phytomer_parameters_olive.leaf.prototype_function = OliveLeafPrototype;
-
1196 phytomer_parameters_olive.leaf.prototype_scale = 0.07;
-
1197 phytomer_parameters_olive.leaf.unique_prototypes = 1;
-
1198 phytomer_parameters_olive.leaf.subdivisions = 1;
-
1199
-
1200 phytomer_parameters_olive.peduncle.length = 0.065;
-
1201 phytomer_parameters_olive.peduncle.radius = 0.001;
-
1202 phytomer_parameters_olive.peduncle.pitch = 60;
-
1203 phytomer_parameters_olive.peduncle.roll = 0;
-
1204 phytomer_parameters_olive.peduncle.length_segments = 1;
-
1205 phytomer_parameters_olive.peduncle.color = make_RGBcolor(0.7, 0.72, 0.7);
-
1206
-
1207 phytomer_parameters_olive.inflorescence.flowers_per_peduncle = 10;
-
1208 phytomer_parameters_olive.inflorescence.flower_offset = 0.13;
-
1209 phytomer_parameters_olive.inflorescence.pitch.uniformDistribution(80,100);
-
1210 phytomer_parameters_olive.inflorescence.roll.uniformDistribution(0,360);
-
1211 phytomer_parameters_olive.inflorescence.flower_prototype_scale = 0.01;
-
1212// phytomer_parameters_olive.inflorescence.flower_prototype_function = OliveFlowerPrototype;
-
1213 phytomer_parameters_olive.inflorescence.fruit_prototype_scale = 0.025;
-
1214 phytomer_parameters_olive.inflorescence.fruit_prototype_function = OliveFruitPrototype;
-
1215
-
1216 // ---- Shoot Parameters ---- //
-
1217
-
1218 // Trunk
-
1219 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
-
1220 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_olive;
-
1221 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
-
1222 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 20;
-
1223 shoot_parameters_trunk.max_nodes = 20;
-
1224 shoot_parameters_trunk.girth_area_factor = 3.f;
-
1225 shoot_parameters_trunk.internode_radius_initial = 0.01;
-
1226 shoot_parameters_trunk.vegetative_bud_break_probability = 0;
-
1227 shoot_parameters_trunk.vegetative_bud_break_time = 0;
-
1228 shoot_parameters_trunk.tortuosity = 6;
-
1229 shoot_parameters_trunk.internode_length_max = 0.05;
-
1230 shoot_parameters_trunk.internode_length_decay_rate = 0;
-
1231 shoot_parameters_trunk.defineChildShootTypes({"scaffold"},{1});
-
1232
-
1233 // Proleptic shoots
-
1234 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
-
1235 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_olive;
-
1236// shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = OlivePhytomerCreationFunction;
-
1237 shoot_parameters_proleptic.phytomer_parameters.phytomer_callback_function = OlivePhytomerCallbackFunction;
-
1238 shoot_parameters_proleptic.max_nodes = 20;
-
1239 shoot_parameters_proleptic.phyllochron = 1.0;
-
1240 shoot_parameters_proleptic.elongation_rate = 0.25;
-
1241 shoot_parameters_proleptic.girth_area_factor = 5.f;
-
1242 shoot_parameters_proleptic.vegetative_bud_break_probability = 0.15;
-
1243 shoot_parameters_proleptic.vegetative_bud_break_time = 0;
-
1244 shoot_parameters_proleptic.leaf_flush_count = 1;
-
1245 shoot_parameters_proleptic.gravitropic_curvature = 450;
-
1246 shoot_parameters_proleptic.tortuosity = 25;
-
1247 shoot_parameters_proleptic.internode_radius_initial = 0.002;
-
1248 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 15, 25);
-
1249 shoot_parameters_proleptic.insertion_angle_decay_rate = 2;
-
1250 shoot_parameters_proleptic.internode_length_max = 0.05;
-
1251 shoot_parameters_proleptic.internode_length_min = 0.03;
-
1252 shoot_parameters_proleptic.internode_length_decay_rate = 0.004;
-
1253 shoot_parameters_proleptic.fruit_set_probability = 0.25;
-
1254 shoot_parameters_proleptic.flower_bud_break_probability = 0.25;
-
1255 shoot_parameters_proleptic.max_terminal_floral_buds = 4;
-
1256 shoot_parameters_proleptic.flowers_require_dormancy = true;
-
1257 shoot_parameters_proleptic.growth_requires_dormancy = true;
-
1258 shoot_parameters_proleptic.determinate_shoot_growth = false;
-
1259 shoot_parameters_proleptic.defineChildShootTypes({"proleptic"},{1.0});
-
1260
-
1261 // Main scaffolds
-
1262 ShootParameters shoot_parameters_scaffold = shoot_parameters_proleptic;
-
1263 shoot_parameters_scaffold.phytomer_parameters.internode.radial_subdivisions = 10;
-
1264 shoot_parameters_scaffold.max_nodes = 12;
-
1265 shoot_parameters_scaffold.gravitropic_curvature = 700;
-
1266 shoot_parameters_scaffold.internode_length_max = 0.04;
-
1267 shoot_parameters_scaffold.tortuosity = 10;
-
1268 shoot_parameters_scaffold.defineChildShootTypes({"proleptic"},{1.0});
-
1269
-
1270 defineShootType("trunk", shoot_parameters_trunk);
-
1271 defineShootType("scaffold", shoot_parameters_scaffold);
-
1272 defineShootType("proleptic", shoot_parameters_proleptic);
-
1273
-
1274}
-
1275
-
1276uint PlantArchitecture::buildOliveTree(const helios::vec3 &base_position) {
-
1277
-
1278 if( shoot_types.empty() ){
-
1279 //automatically initialize almond tree shoots
-
1280 initializeOliveTreeShoots();
-
1281 }
-
1282
-
1283 uint plantID = addPlantInstance(base_position, 0);
-
1284
-
1285 uint uID_trunk = addBaseStemShoot(plantID, 19, 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)), 0.015, 0.008, 1.f, 1.f, 0, "trunk");
-
1286 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
-
1287
-
1288 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
-
1289
-
1290 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
-
1291 for( const auto & phytomer : phytomers ){
-
1292 phytomer->removeLeaf();
-
1293 phytomer->setVegetativeBudState(BUD_DEAD);
-
1294 phytomer->setFloralBudState(BUD_DEAD);
-
1295 }
-
1296
-
1297 uint Nscaffolds = 4;//context_ptr->randu(4,5);
-
1298
-
1299 for( int i=0; i<Nscaffolds; i++ ) {
-
1300 float pitch = context_ptr->randu(deg2rad(30), deg2rad(35));
-
1301 uint uID_shoot = addChildShoot( plantID, uID_trunk, getShootNodeCount(plantID,uID_trunk)-i-1, context_ptr->randu(5, 7), make_AxisRotation(pitch, (float(i) + context_ptr->randu(-0.2f, 0.2f)) / float(Nscaffolds) * 2 * M_PI, 0), 0.007, 0.06, 1.f, 1.f, 0.5, "scaffold", 0);
-
1302
-
1303 }
-
1304
-
1305 makePlantDormant(plantID);
-
1306
-
1307 setPlantPhenologicalThresholds(plantID, 0, -1, 1, 3, 8, 20, true);
-
1308
-
1309 return plantID;
-
1310
-
1311}
-
1312
-
1313void PlantArchitecture::initializePistachioTreeShoots(){
-
1314
-
1315 // ---- Phytomer Parameters ---- //
-
1316
-
1317 PhytomerParameters phytomer_parameters_pistachio(context_ptr->getRandomGenerator());
-
1318
-
1319 phytomer_parameters_pistachio.internode.pitch = 0;
-
1320 phytomer_parameters_pistachio.internode.phyllotactic_angle.uniformDistribution(160, 200);
-
1321 phytomer_parameters_pistachio.internode.length_segments = 1;
-
1322 phytomer_parameters_pistachio.internode.image_texture = "plugins/plantarchitecture/assets/textures/OliveBark.jpg";
-
1323 phytomer_parameters_pistachio.internode.max_floral_buds_per_petiole = 3;
-
1324
-
1325 phytomer_parameters_pistachio.petiole.petioles_per_internode = 2;
-
1326 phytomer_parameters_pistachio.petiole.pitch.uniformDistribution(-45, -60);
-
1327 phytomer_parameters_pistachio.petiole.taper = 0.1;
-
1328 phytomer_parameters_pistachio.petiole.curvature.uniformDistribution(-800,800);
-
1329 phytomer_parameters_pistachio.petiole.length = 0.075;
-
1330 phytomer_parameters_pistachio.petiole.radius = 0.001;
-
1331 phytomer_parameters_pistachio.petiole.length_segments = 1;
-
1332 phytomer_parameters_pistachio.petiole.radial_subdivisions = 3;
-
1333 phytomer_parameters_pistachio.petiole.color = make_RGBcolor(0.6, 0.6, 0.4);
-
1334
-
1335 phytomer_parameters_pistachio.leaf.leaves_per_petiole = 3;
-
1336 phytomer_parameters_pistachio.leaf.prototype_function = PistachioLeafPrototype;
-
1337 phytomer_parameters_pistachio.leaf.prototype_scale = 0.08;
-
1338 phytomer_parameters_pistachio.leaf.leaflet_offset = 0.3;
-
1339 phytomer_parameters_pistachio.leaf.leaflet_scale = 0.75;
-
1340 phytomer_parameters_pistachio.leaf.pitch.uniformDistribution(-20,20);
-
1341 phytomer_parameters_pistachio.leaf.roll.uniformDistribution(-20,20);
-
1342 phytomer_parameters_pistachio.leaf.unique_prototypes = 5;
-
1343 phytomer_parameters_pistachio.leaf.subdivisions = 3;
-
1344
-
1345 phytomer_parameters_pistachio.peduncle.length = 0.1;
-
1346 phytomer_parameters_pistachio.peduncle.radius = 0.001;
-
1347 phytomer_parameters_pistachio.peduncle.pitch = 60;
-
1348 phytomer_parameters_pistachio.peduncle.roll = 0;
-
1349 phytomer_parameters_pistachio.peduncle.length_segments = 1;
-
1350 phytomer_parameters_pistachio.peduncle.curvature.uniformDistribution(500,900);
-
1351 phytomer_parameters_pistachio.peduncle.color = make_RGBcolor(0.7, 0.72, 0.7);
-
1352
-
1353 phytomer_parameters_pistachio.inflorescence.flowers_per_peduncle = 16;
-
1354 phytomer_parameters_pistachio.inflorescence.flower_offset = 0.08;
-
1355 phytomer_parameters_pistachio.inflorescence.pitch.uniformDistribution(50, 70);
-
1356 phytomer_parameters_pistachio.inflorescence.roll.uniformDistribution(0, 360);
-
1357 phytomer_parameters_pistachio.inflorescence.flower_prototype_scale = 0.025;
-
1358// phytomer_parameters_pistachio.inflorescence.flower_prototype_function = PistachioFlowerPrototype;
-
1359 phytomer_parameters_pistachio.inflorescence.fruit_prototype_scale = 0.025;
-
1360 phytomer_parameters_pistachio.inflorescence.fruit_prototype_function = PistachioFruitPrototype;
-
1361
-
1362 // ---- Shoot Parameters ---- //
-
1363
-
1364 // Trunk
-
1365 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
-
1366 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_pistachio;
-
1367 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 180;
-
1368 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 20;
-
1369 shoot_parameters_trunk.max_nodes = 20;
-
1370 shoot_parameters_trunk.girth_area_factor = 5.f;
-
1371 shoot_parameters_trunk.internode_radius_initial = 0.01;
-
1372 shoot_parameters_trunk.vegetative_bud_break_probability = 0;
-
1373 shoot_parameters_trunk.vegetative_bud_break_time = 0;
-
1374 shoot_parameters_trunk.tortuosity = 5;
-
1375 shoot_parameters_trunk.internode_length_max = 0.05;
-
1376 shoot_parameters_trunk.internode_length_decay_rate = 0;
-
1377 shoot_parameters_trunk.defineChildShootTypes({"proleptic"},{1});
-
1378
-
1379 // Proleptic shoots
-
1380 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
-
1381 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_pistachio;
-
1382 shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = PistachioPhytomerCreationFunction;
-
1383 shoot_parameters_proleptic.phytomer_parameters.phytomer_callback_function = PistachioPhytomerCallbackFunction;
-
1384 shoot_parameters_proleptic.max_nodes = 20;
-
1385 shoot_parameters_proleptic.phyllochron = 1;
-
1386 shoot_parameters_proleptic.elongation_rate = 0.25;
-
1387 shoot_parameters_proleptic.girth_area_factor = 10.f;
-
1388 shoot_parameters_proleptic.vegetative_bud_break_probability = 0.15;
-
1389 shoot_parameters_proleptic.vegetative_bud_break_time = 0;
-
1390 shoot_parameters_proleptic.leaf_flush_count = 1;
-
1391 shoot_parameters_proleptic.gravitropic_curvature = 500;
-
1392 shoot_parameters_proleptic.tortuosity = 15;
-
1393 shoot_parameters_proleptic.internode_radius_initial = 0.002;
-
1394 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 45, 55);
-
1395 shoot_parameters_proleptic.insertion_angle_decay_rate = 10;
-
1396 shoot_parameters_proleptic.internode_length_max = 0.04;
-
1397 shoot_parameters_proleptic.internode_length_min = 0.02;
-
1398 shoot_parameters_proleptic.internode_length_decay_rate = 0.005;
-
1399 shoot_parameters_proleptic.fruit_set_probability = 0.35;
-
1400 shoot_parameters_proleptic.flower_bud_break_probability = 0.35;
-
1401 shoot_parameters_proleptic.max_terminal_floral_buds = 4;
-
1402 shoot_parameters_proleptic.flowers_require_dormancy = true;
-
1403 shoot_parameters_proleptic.growth_requires_dormancy = true;
-
1404 shoot_parameters_proleptic.determinate_shoot_growth = false;
-
1405
-
1406 defineShootType("trunk", shoot_parameters_trunk);
-
1407 defineShootType("proleptic", shoot_parameters_proleptic);
-
1408
-
1409}
-
1410
-
1411uint PlantArchitecture::buildPistachioTree(const helios::vec3 &base_position) {
-
1412
-
1413 if( shoot_types.empty() ){
-
1414 //automatically initialize almond tree shoots
-
1415 initializePistachioTreeShoots();
-
1416 }
-
1417
-
1418 uint plantID = addPlantInstance(base_position, 0);
-
1419
-
1420 uint uID_trunk = addBaseStemShoot(plantID, 19, 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)), 0.015, 0.03, 1.f, 1.f, 0, "trunk");
-
1421 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
-
1422
-
1423 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
-
1424
-
1425 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
-
1426 for( const auto & phytomer : phytomers ){
-
1427 phytomer->removeLeaf();
-
1428 phytomer->setVegetativeBudState(BUD_DEAD);
-
1429 phytomer->setFloralBudState(BUD_DEAD);
-
1430 }
-
1431
-
1432 uint Nscaffolds = 4;//context_ptr->randu(4,5);
-
1433
-
1434 for( int i=0; i<Nscaffolds; i++ ) {
-
1435 float pitch = context_ptr->randu(deg2rad(65), deg2rad(80));
-
1436 uint uID_shoot = addChildShoot( plantID, uID_trunk, getShootNodeCount(plantID,uID_trunk)-i-1, 1, make_AxisRotation(pitch, (float(i) + context_ptr->randu(-0.2f, 0.2f)) / float(Nscaffolds) * 2 * M_PI, 0), 0.007, 0.06, 1.f, 1.f, 0.5, "proleptic", 0);
-
1437
-
1438 }
-
1439
-
1440 makePlantDormant(plantID);
-
1441
-
1442 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 4, 8, 20, false);
-
1443
-
1444 return plantID;
-
1445
-
1446}
-
1447
-
1448void PlantArchitecture::initializePuncturevineShoots() {
-
1449
-
1450 // ---- Phytomer Parameters ---- //
-
1451
-
1452 PhytomerParameters phytomer_parameters_puncturevine(context_ptr->getRandomGenerator());
-
1453
-
1454 phytomer_parameters_puncturevine.internode.pitch.uniformDistribution(0,15);
-
1455 phytomer_parameters_puncturevine.internode.phyllotactic_angle = 180.f;
-
1456 phytomer_parameters_puncturevine.internode.color = make_RGBcolor(0.55, 0.52, 0.39);
-
1457 phytomer_parameters_puncturevine.internode.length_segments = 1;
-
1458
-
1459 phytomer_parameters_puncturevine.petiole.petioles_per_internode = 1;
-
1460 phytomer_parameters_puncturevine.petiole.pitch.uniformDistribution(80, 100);
-
1461 phytomer_parameters_puncturevine.petiole.radius = 0.0003;
-
1462 phytomer_parameters_puncturevine.petiole.length = 0.025;
-
1463 phytomer_parameters_puncturevine.petiole.taper = 0;
-
1464 phytomer_parameters_puncturevine.petiole.curvature = 0;
-
1465 phytomer_parameters_puncturevine.petiole.color = phytomer_parameters_puncturevine.internode.color;
-
1466 phytomer_parameters_puncturevine.petiole.length_segments = 1;
-
1467
-
1468 phytomer_parameters_puncturevine.leaf.leaves_per_petiole = 11;
-
1469 phytomer_parameters_puncturevine.leaf.pitch.uniformDistribution(-10,10);
-
1470 phytomer_parameters_puncturevine.leaf.yaw = 30;
-
1471 phytomer_parameters_puncturevine.leaf.roll.uniformDistribution(-5,5);
-
1472 phytomer_parameters_puncturevine.leaf.prototype_function = PuncturevineLeafPrototype;
-
1473 phytomer_parameters_puncturevine.leaf.prototype_scale = 0.008;
-
1474 phytomer_parameters_puncturevine.leaf.leaflet_offset = 0.15;
-
1475 phytomer_parameters_puncturevine.leaf.leaflet_scale = 1;
-
1476 phytomer_parameters_puncturevine.leaf.subdivisions = 3;
-
1477
-
1478 phytomer_parameters_puncturevine.peduncle.length = 0.001;
-
1479 phytomer_parameters_puncturevine.inflorescence.flowers_per_peduncle = 1;
-
1480 phytomer_parameters_puncturevine.inflorescence.pitch = -90.f;
-
1481 phytomer_parameters_puncturevine.inflorescence.flower_prototype_function = PuncturevineFlowerPrototype;
-
1482 phytomer_parameters_puncturevine.inflorescence.flower_prototype_scale = 0.006;
-
1483
-
1484 // ---- Shoot Parameters ---- //
-
1485
-
1486 ShootParameters shoot_parameters_primary(context_ptr->getRandomGenerator());
-
1487 shoot_parameters_primary.phytomer_parameters = phytomer_parameters_puncturevine;
-
1488 shoot_parameters_primary.vegetative_bud_break_probability = 0.3;
-
1489 shoot_parameters_primary.vegetative_bud_break_time = 3;
-
1490 shoot_parameters_primary.base_roll = 90;
-
1491 shoot_parameters_primary.internode_radius_initial = 0.001;
-
1492 shoot_parameters_primary.phyllochron = 1;
-
1493 shoot_parameters_primary.elongation_rate = 0.2;
-
1494 shoot_parameters_primary.girth_area_factor = 0.f;
-
1495 shoot_parameters_primary.internode_length_max = 0.02;
-
1496 shoot_parameters_primary.internode_length_decay_rate = 0;
-
1497 shoot_parameters_primary.insertion_angle_tip.uniformDistribution(50, 80);
-
1498 shoot_parameters_primary.flowers_require_dormancy = false;
-
1499 shoot_parameters_primary.growth_requires_dormancy = false;
-
1500 shoot_parameters_primary.flower_bud_break_probability = 0.2;
-
1501 shoot_parameters_primary.determinate_shoot_growth = false;
-
1502 shoot_parameters_primary.max_nodes = 15;
-
1503 shoot_parameters_primary.gravitropic_curvature = 20;
-
1504 shoot_parameters_primary.tortuosity = 0;
-
1505 shoot_parameters_primary.defineChildShootTypes({"secondary_puncturevine"}, {1.f});
-
1506
-
1507 ShootParameters shoot_parameters_base = shoot_parameters_primary;
-
1508 shoot_parameters_base.phytomer_parameters = phytomer_parameters_puncturevine;
-
1509 shoot_parameters_base.phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(137.5-10,137.5+10);
-
1510 shoot_parameters_base.phytomer_parameters.petiole.petioles_per_internode = 0;
-
1511 shoot_parameters_base.phytomer_parameters.internode.pitch = 0;
-
1512 shoot_parameters_base.phytomer_parameters.petiole.pitch = 0;
-
1513 shoot_parameters_base.vegetative_bud_break_probability = 1;
-
1514 shoot_parameters_base.vegetative_bud_break_time = 1;
-
1515 shoot_parameters_base.internode_radius_initial = 0.001;
-
1516 shoot_parameters_base.phyllochron = 1;
-
1517 shoot_parameters_base.elongation_rate = 0.25;
-
1518 shoot_parameters_base.gravitropic_curvature = 0;
-
1519 shoot_parameters_base.internode_length_max = 0.01;
-
1520 shoot_parameters_base.internode_length_decay_rate = 0;
-
1521 shoot_parameters_base.insertion_angle_tip = 90;
-
1522 shoot_parameters_base.insertion_angle_decay_rate = 0;
-
1523 shoot_parameters_base.internode_radius_initial = 0.0005;
-
1524 shoot_parameters_base.flowers_require_dormancy = false;
-
1525 shoot_parameters_base.growth_requires_dormancy = false;
-
1526 shoot_parameters_base.flower_bud_break_probability = 0.0;
-
1527 shoot_parameters_base.max_nodes.uniformDistribution(3,5);
-
1528 shoot_parameters_base.defineChildShootTypes({"primary_puncturevine"},{1.f});
-
1529
-
1530 ShootParameters shoot_parameters_children = shoot_parameters_primary;
-
1531 shoot_parameters_children.base_roll = 0;
-
1532
-
1533 defineShootType("base_puncturevine", shoot_parameters_base);
-
1534 defineShootType("primary_puncturevine", shoot_parameters_primary);
-
1535 defineShootType("secondary_puncturevine", shoot_parameters_children);
-
1536
-
1537}
-
1538
-
1539uint PlantArchitecture::buildPuncturevinePlant(const helios::vec3 &base_position) {
-
1540
-
1541 if (shoot_types.empty()) {
-
1542 //automatically initialize puncturevine plant shoots
-
1543 initializePuncturevineShoots();
-
1544 }
-
1545
-
1546 uint plantID = addPlantInstance(base_position, 0);
-
1547
-
1548 uint uID_stem = addBaseStemShoot(plantID, 3, make_AxisRotation(0, 0.f, 0.f), 0.001, 0.001, 1, 1, 0, "base_puncturevine");
-
1549
-
1550 breakPlantDormancy(plantID);
-
1551
-
1552 setPlantPhenologicalThresholds(plantID, 0, -1, 7, 1000, 5, 100, false);
-
1553
-
1554 return plantID;
-
1555
-
1556}
-
1557
-
1558void PlantArchitecture::initializeEasternRedbudShoots() {
-
1559
-
1560 // ---- Phytomer Parameters ---- //
-
1561
-
1562 PhytomerParameters phytomer_parameters_redbud(context_ptr->getRandomGenerator());
-
1563
-
1564 phytomer_parameters_redbud.internode.pitch = 15;
-
1565 phytomer_parameters_redbud.internode.phyllotactic_angle.uniformDistribution(170,190);
-
1566// phytomer_parameters_redbud.internode.color = make_RGBcolor(0.55, 0.52, 0.39);
-
1567 phytomer_parameters_redbud.internode.image_texture = "plugins/plantarchitecture/assets/textures/WesternRedbudBark.jpg";
-
1568 phytomer_parameters_redbud.internode.color.scale(0.3);
-
1569 phytomer_parameters_redbud.internode.length_segments = 1;
-
1570 phytomer_parameters_redbud.internode.max_floral_buds_per_petiole = 5;
-
1571
-
1572 phytomer_parameters_redbud.petiole.petioles_per_internode = 1;
-
1573 phytomer_parameters_redbud.petiole.color = make_RGBcolor(0.65, 0.52, 0.39);
-
1574 phytomer_parameters_redbud.petiole.pitch.uniformDistribution(20, 40);
-
1575 phytomer_parameters_redbud.petiole.radius = 0.0017;
-
1576 phytomer_parameters_redbud.petiole.length = 0.05;
-
1577 phytomer_parameters_redbud.petiole.taper = 0;
-
1578 phytomer_parameters_redbud.petiole.curvature = 0;
-
1579 phytomer_parameters_redbud.petiole.length_segments = 1;
-
1580
-
1581 phytomer_parameters_redbud.leaf.leaves_per_petiole = 1;
-
1582 phytomer_parameters_redbud.leaf.pitch.uniformDistribution(-110, -80);
-
1583 phytomer_parameters_redbud.leaf.yaw = 0;
-
1584 phytomer_parameters_redbud.leaf.roll.uniformDistribution(-5, 5);
-
1585 phytomer_parameters_redbud.leaf.prototype_function = RedbudLeafPrototype;
-
1586 phytomer_parameters_redbud.leaf.prototype_scale = 0.1;
-
1587 phytomer_parameters_redbud.leaf.subdivisions = 5;
-
1588
-
1589 phytomer_parameters_redbud.peduncle.length = 0.02;
-
1590 phytomer_parameters_redbud.peduncle.pitch.uniformDistribution(50,90);
-
1591 phytomer_parameters_redbud.peduncle.color = make_RGBcolor(0.32, 0.05, 0.13);
-
1592
-
1593 phytomer_parameters_redbud.inflorescence.flowers_per_peduncle = 1;
-
1594 phytomer_parameters_redbud.inflorescence.pitch = 0;
-
1595 phytomer_parameters_redbud.inflorescence.flower_prototype_function = RedbudFlowerPrototype;
-
1596 phytomer_parameters_redbud.inflorescence.flower_prototype_scale = 0.04;
-
1597 phytomer_parameters_redbud.inflorescence.fruit_prototype_function = RedbudFruitPrototype;
-
1598 phytomer_parameters_redbud.inflorescence.fruit_prototype_scale = 0.1;
-
1599 phytomer_parameters_redbud.inflorescence.fruit_gravity_factor_fraction = 0.7;
-
1600
-
1601 phytomer_parameters_redbud.phytomer_creation_function = RedbudPhytomerCreationFunction;
-
1602 phytomer_parameters_redbud.phytomer_callback_function = RedbudPhytomerCallbackFunction;
-
1603
-
1604 // ---- Shoot Parameters ---- //
-
1605
-
1606 ShootParameters shoot_parameters_main(context_ptr->getRandomGenerator());
-
1607 shoot_parameters_main.phytomer_parameters = phytomer_parameters_redbud;
-
1608 shoot_parameters_main.vegetative_bud_break_probability = 1.0;
-
1609 shoot_parameters_main.vegetative_bud_break_time = 1;
-
1610 shoot_parameters_main.phyllochron = 1.5;
-
1611 shoot_parameters_main.elongation_rate = 0.17;
-
1612 shoot_parameters_main.girth_area_factor = 3.f;
-
1613 shoot_parameters_main.gravitropic_curvature = 300;
-
1614 shoot_parameters_main.tortuosity = 20;
-
1615 shoot_parameters_main.internode_length_max = 0.04;
-
1616 shoot_parameters_main.internode_length_decay_rate = 0.005;
-
1617 shoot_parameters_main.insertion_angle_tip = 75;
-
1618 shoot_parameters_main.insertion_angle_decay_rate = 10;
-
1619 shoot_parameters_main.internode_radius_initial = 0.0015;
-
1620 shoot_parameters_main.internode_radius_max = 0.02;
-
1621 shoot_parameters_main.flowers_require_dormancy = true;
-
1622 shoot_parameters_main.growth_requires_dormancy = true;
-
1623 shoot_parameters_main.determinate_shoot_growth = false;
-
1624 shoot_parameters_main.max_terminal_floral_buds = 0;
-
1625 shoot_parameters_main.flower_bud_break_probability = 0.8;
-
1626 shoot_parameters_main.fruit_set_probability = 0.3;
-
1627 shoot_parameters_main.max_nodes = 30;
-
1628 shoot_parameters_main.base_roll = 90;
-
1629
-
1630 ShootParameters shoot_parameters_trunk = shoot_parameters_main;
-
1631 shoot_parameters_trunk.phytomer_parameters.internode.pitch = 0;
-
1632 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 15;
-
1633 shoot_parameters_trunk.phytomer_parameters.internode.max_floral_buds_per_petiole = 0;
-
1634 shoot_parameters_trunk.internode_radius_max = 1;
-
1635 shoot_parameters_trunk.phyllochron = 1.25;
-
1636 shoot_parameters_trunk.insertion_angle_tip = 60;
-
1637 shoot_parameters_trunk.max_nodes = 45;
-
1638 shoot_parameters_trunk.tortuosity = 5;
-
1639 shoot_parameters_trunk.defineChildShootTypes({"eastern_redbud_shoot"},{1.f});
-
1640
-
1641 defineShootType("eastern_redbud_trunk", shoot_parameters_trunk);
-
1642 defineShootType("eastern_redbud_shoot", shoot_parameters_main);
-
1643
-
1644}
-
1645
-
1646uint PlantArchitecture::buildEasternRedbudPlant(const helios::vec3 &base_position) {
-
1647
-
1648 if (shoot_types.empty()) {
-
1649 //automatically initialize redbud plant shoots
-
1650 initializeEasternRedbudShoots();
-
1651 }
-
1652
-
1653 uint plantID = addPlantInstance(base_position, 0);
-
1654
-
1655 uint uID_stem = addBaseStemShoot(plantID, 16, make_AxisRotation(context_ptr->randu(0,0.1*M_PI), context_ptr->randu(0,2*M_PI), context_ptr->randu(0,2*M_PI)), 0.0075, 0.05, 1, 1, 0.4, "eastern_redbud_trunk");
-
1656
-
1657 makePlantDormant(plantID);
-
1658
-
1659 removeShootLeaves( plantID, uID_stem );
-
1660
-
1661 setPlantPhenologicalThresholds(plantID, 0, -1, 1, 3, 3, 12, false);
-
1662
-
1663 return plantID;
-
1664
-
1665}
-
1666
-
1667void PlantArchitecture::initializeRomaineLettuceShoots() {
-
1668
-
1669 // ---- Phytomer Parameters ---- //
-
1670
-
1671 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
-
1672
-
1673 phytomer_parameters.internode.pitch = 0;
-
1674 phytomer_parameters.internode.phyllotactic_angle = 137.5;
-
1675 phytomer_parameters.internode.color = make_RGBcolor(0.402,0.423,0.413);
-
1676 phytomer_parameters.internode.length_segments = 1;
-
1677 phytomer_parameters.internode.radial_subdivisions = 10;
-
1678
-
1679 phytomer_parameters.petiole.petioles_per_internode = 1;
-
1680 phytomer_parameters.petiole.pitch.uniformDistribution(0,30);
-
1681 phytomer_parameters.petiole.radius = 0.001;
-
1682 phytomer_parameters.petiole.length = 0.001;
-
1683 phytomer_parameters.petiole.length_segments = 1;
-
1684 phytomer_parameters.petiole.radial_subdivisions = 3;
-
1685 phytomer_parameters.petiole.color = RGB::red;
-
1686
-
1687 phytomer_parameters.leaf.leaves_per_petiole = 1;
-
1688 phytomer_parameters.leaf.pitch = 0;
-
1689 phytomer_parameters.leaf.yaw = 0;
-
1690 phytomer_parameters.leaf.roll = 0;
-
1691 phytomer_parameters.leaf.prototype_function = RomaineLettuceLeafPrototype;
-
1692 phytomer_parameters.leaf.prototype_scale.uniformDistribution(0.15,0.25);
-
1693 phytomer_parameters.leaf.subdivisions = 30;
-
1694
-
1695 phytomer_parameters.phytomer_creation_function = RomaineLettucePhytomerCreationFunction;
-
1696
-
1697 // ---- Shoot Parameters ---- //
-
1698
-
1699 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
-
1700 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters;
-
1701 shoot_parameters_mainstem.vegetative_bud_break_probability = 0;
-
1702 shoot_parameters_mainstem.internode_radius_initial = 0.01;
-
1703 shoot_parameters_mainstem.phyllochron = 1;
-
1704 shoot_parameters_mainstem.elongation_rate = 0.15;
-
1705 shoot_parameters_mainstem.girth_area_factor = 0.f;
-
1706 shoot_parameters_mainstem.gravitropic_curvature = 10;
-
1707 shoot_parameters_mainstem.internode_length_max = 0.001;
-
1708 shoot_parameters_mainstem.internode_length_decay_rate = 0;
-
1709 shoot_parameters_mainstem.flowers_require_dormancy = false;
-
1710 shoot_parameters_mainstem.growth_requires_dormancy = false;
-
1711 shoot_parameters_mainstem.flower_bud_break_probability = 0.0;
-
1712 shoot_parameters_mainstem.max_nodes = 25;
-
1713
-
1714 defineShootType("mainstem",shoot_parameters_mainstem);
-
1715
+
1120 shoot_parameters_cane.gravitropic_curvature.uniformDistribution(-20,20);
+
1121 shoot_parameters_cane.tortuosity = 1;
+
1122 shoot_parameters_cane.gravitropic_curvature = 10;
+
1123 shoot_parameters_cane.vegetative_bud_break_probability = 1.0;
+
1124 shoot_parameters_cane.defineChildShootTypes({"grapevine_shoot"},{1.f});
+
1125
+
1126 ShootParameters shoot_parameters_trunk = shoot_parameters_main;
+
1127 shoot_parameters_trunk.phytomer_parameters.internode.image_texture = "plugins/plantarchitecture/assets/textures/GrapeBark.jpg";
+
1128 shoot_parameters_trunk.phytomer_parameters.internode.pitch = 0;
+
1129 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
+
1130 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 25;
+
1131 shoot_parameters_trunk.phytomer_parameters.internode.max_floral_buds_per_petiole = 0;
+
1132 shoot_parameters_trunk.internode_radius_max = 1;
+
1133 shoot_parameters_trunk.phyllochron = 1.25;
+
1134 shoot_parameters_trunk.insertion_angle_tip = 90;
+
1135 shoot_parameters_trunk.max_nodes = 18;
+
1136 shoot_parameters_trunk.tortuosity = 0;
+
1137 shoot_parameters_trunk.vegetative_bud_break_probability = 0;
+
1138 shoot_parameters_trunk.defineChildShootTypes({"grapevine_shoot"},{1.f});
+
1139
+
1140 defineShootType("grapevine_trunk", shoot_parameters_trunk);
+
1141 defineShootType("grapevine_cane", shoot_parameters_cane);
+
1142 defineShootType("grapevine_shoot", shoot_parameters_main);
+
1143
+
1144}
+
1145
+
1146uint PlantArchitecture::buildGrapevineVSP(const helios::vec3 &base_position) {
+
1147
+
1148 if (shoot_types.empty()) {
+
1149 //automatically initialize redbud plant shoots
+
1150 initializeGrapevineVSPShoots();
+
1151 }
+
1152
+
1153 uint plantID = addPlantInstance(base_position, 0);
+
1154
+
1155 uint uID_stem = addBaseStemShoot(plantID, 17, make_AxisRotation(context_ptr->randu(0,0.05*M_PI), 0, 0), 0.04, 0.05, 1, 1, 0.1, "grapevine_trunk");
+
1156 //appendPhytomerToShoot( plantID, uID_stem, getCurrentShootParameters("grapevine_trunk").phytomer_parameters, 1e-3, 0.1, 1, 1 );
+
1157
+
1158 uint uID_cane_L = appendShoot( plantID, uID_stem, 8, make_AxisRotation(context_ptr->randu(float(0.45f*M_PI),0.52f*M_PI),0,M_PI), 0.005, 0.15, 1, 1, 0.5, "grapevine_cane" );
+
1159 uint uID_cane_R = appendShoot( plantID, uID_stem, 8, make_AxisRotation(context_ptr->randu(float(0.45f*M_PI),0.52f*M_PI),M_PI,M_PI), 0.005, 0.15, 1, 1, 0.5, "grapevine_cane" );
+
1160
+
1161// makePlantDormant(plantID);
+
1162
+
1163 removeShootLeaves( plantID, uID_stem );
+
1164 removeShootLeaves( plantID, uID_cane_L );
+
1165 removeShootLeaves( plantID, uID_cane_R );
+
1166
+
1167 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 5, 8, 25, false);
+
1168
+
1169 return plantID;
+
1170
+
1171}
+
1172
+
1173void PlantArchitecture::initializeOliveTreeShoots(){
+
1174
+
1175 // ---- Phytomer Parameters ---- //
+
1176
+
1177 PhytomerParameters phytomer_parameters_olive(context_ptr->getRandomGenerator());
+
1178
+
1179 phytomer_parameters_olive.internode.pitch = 0;
+
1180 phytomer_parameters_olive.internode.phyllotactic_angle.uniformDistribution(80, 100 );
+
1181 phytomer_parameters_olive.internode.length_segments = 1;
+
1182 phytomer_parameters_olive.internode.image_texture = "plugins/plantarchitecture/assets/textures/OliveBark.jpg";
+
1183 phytomer_parameters_olive.internode.max_floral_buds_per_petiole = 3;
+
1184
+
1185 phytomer_parameters_olive.petiole.petioles_per_internode = 2;
+
1186 phytomer_parameters_olive.petiole.pitch.uniformDistribution(-40,-20);
+
1187 phytomer_parameters_olive.petiole.taper = 0.1;
+
1188 phytomer_parameters_olive.petiole.curvature = 0;
+
1189 phytomer_parameters_olive.petiole.length = 0.01;
+
1190 phytomer_parameters_olive.petiole.radius = 0.0005;
+
1191 phytomer_parameters_olive.petiole.length_segments = 1;
+
1192 phytomer_parameters_olive.petiole.radial_subdivisions = 3;
+
1193 phytomer_parameters_olive.petiole.color = make_RGBcolor(0.61, 0.5, 0.24);
+
1194
+
1195 phytomer_parameters_olive.leaf.leaves_per_petiole = 1;
+
1196 phytomer_parameters_olive.leaf.prototype_function = OliveLeafPrototype;
+
1197 phytomer_parameters_olive.leaf.prototype_scale = 0.07;
+
1198 phytomer_parameters_olive.leaf.unique_prototypes = 1;
+
1199 phytomer_parameters_olive.leaf.subdivisions = 1;
+
1200
+
1201 phytomer_parameters_olive.peduncle.length = 0.065;
+
1202 phytomer_parameters_olive.peduncle.radius = 0.001;
+
1203 phytomer_parameters_olive.peduncle.pitch = 60;
+
1204 phytomer_parameters_olive.peduncle.roll = 0;
+
1205 phytomer_parameters_olive.peduncle.length_segments = 1;
+
1206 phytomer_parameters_olive.peduncle.color = make_RGBcolor(0.7, 0.72, 0.7);
+
1207
+
1208 phytomer_parameters_olive.inflorescence.flowers_per_peduncle = 10;
+
1209 phytomer_parameters_olive.inflorescence.flower_offset = 0.13;
+
1210 phytomer_parameters_olive.inflorescence.pitch.uniformDistribution(80,100);
+
1211 phytomer_parameters_olive.inflorescence.roll.uniformDistribution(0,360);
+
1212 phytomer_parameters_olive.inflorescence.flower_prototype_scale = 0.01;
+
1213// phytomer_parameters_olive.inflorescence.flower_prototype_function = OliveFlowerPrototype;
+
1214 phytomer_parameters_olive.inflorescence.fruit_prototype_scale = 0.025;
+
1215 phytomer_parameters_olive.inflorescence.fruit_prototype_function = OliveFruitPrototype;
+
1216
+
1217 // ---- Shoot Parameters ---- //
+
1218
+
1219 // Trunk
+
1220 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
+
1221 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_olive;
+
1222 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
+
1223 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 20;
+
1224 shoot_parameters_trunk.max_nodes = 20;
+
1225 shoot_parameters_trunk.girth_area_factor = 3.f;
+
1226 shoot_parameters_trunk.internode_radius_initial = 0.01;
+
1227 shoot_parameters_trunk.vegetative_bud_break_probability = 0;
+
1228 shoot_parameters_trunk.vegetative_bud_break_time = 0;
+
1229 shoot_parameters_trunk.tortuosity = 1;
+
1230 shoot_parameters_trunk.internode_length_max = 0.05;
+
1231 shoot_parameters_trunk.internode_length_decay_rate = 0;
+
1232 shoot_parameters_trunk.defineChildShootTypes({"scaffold"},{1});
+
1233
+
1234 // Proleptic shoots
+
1235 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
+
1236 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_olive;
+
1237// shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = OlivePhytomerCreationFunction;
+
1238 shoot_parameters_proleptic.phytomer_parameters.phytomer_callback_function = OlivePhytomerCallbackFunction;
+
1239 shoot_parameters_proleptic.max_nodes = 20;
+
1240 shoot_parameters_proleptic.phyllochron = 1.0;
+
1241 shoot_parameters_proleptic.elongation_rate = 0.25;
+
1242 shoot_parameters_proleptic.girth_area_factor = 5.f;
+
1243 shoot_parameters_proleptic.vegetative_bud_break_probability = 0.15;
+
1244 shoot_parameters_proleptic.vegetative_bud_break_time = 0;
+
1245 shoot_parameters_proleptic.leaf_flush_count = 1;
+
1246 shoot_parameters_proleptic.gravitropic_curvature = 450;
+
1247 shoot_parameters_proleptic.tortuosity = 6;
+
1248 shoot_parameters_proleptic.internode_radius_initial = 0.002;
+
1249 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 15, 25);
+
1250 shoot_parameters_proleptic.insertion_angle_decay_rate = 2;
+
1251 shoot_parameters_proleptic.internode_length_max = 0.05;
+
1252 shoot_parameters_proleptic.internode_length_min = 0.03;
+
1253 shoot_parameters_proleptic.internode_length_decay_rate = 0.004;
+
1254 shoot_parameters_proleptic.fruit_set_probability = 0.25;
+
1255 shoot_parameters_proleptic.flower_bud_break_probability = 0.25;
+
1256 shoot_parameters_proleptic.max_terminal_floral_buds = 4;
+
1257 shoot_parameters_proleptic.flowers_require_dormancy = true;
+
1258 shoot_parameters_proleptic.growth_requires_dormancy = true;
+
1259 shoot_parameters_proleptic.determinate_shoot_growth = false;
+
1260 shoot_parameters_proleptic.defineChildShootTypes({"proleptic"},{1.0});
+
1261
+
1262 // Main scaffolds
+
1263 ShootParameters shoot_parameters_scaffold = shoot_parameters_proleptic;
+
1264 shoot_parameters_scaffold.phytomer_parameters.internode.radial_subdivisions = 10;
+
1265 shoot_parameters_scaffold.max_nodes = 12;
+
1266 shoot_parameters_scaffold.gravitropic_curvature = 700;
+
1267 shoot_parameters_scaffold.internode_length_max = 0.04;
+
1268 shoot_parameters_scaffold.tortuosity = 3;
+
1269 shoot_parameters_scaffold.defineChildShootTypes({"proleptic"},{1.0});
+
1270
+
1271 defineShootType("trunk", shoot_parameters_trunk);
+
1272 defineShootType("scaffold", shoot_parameters_scaffold);
+
1273 defineShootType("proleptic", shoot_parameters_proleptic);
+
1274
+
1275}
+
1276
+
1277uint PlantArchitecture::buildOliveTree(const helios::vec3 &base_position) {
+
1278
+
1279 if( shoot_types.empty() ){
+
1280 //automatically initialize almond tree shoots
+
1281 initializeOliveTreeShoots();
+
1282 }
+
1283
+
1284 uint plantID = addPlantInstance(base_position, 0);
+
1285
+
1286 uint uID_trunk = addBaseStemShoot(plantID, 19, 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)), 0.015, 0.008, 1.f, 1.f, 0, "trunk");
+
1287 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
+
1288
+
1289 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
+
1290
+
1291 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
+
1292 for( const auto & phytomer : phytomers ){
+
1293 phytomer->removeLeaf();
+
1294 phytomer->setVegetativeBudState(BUD_DEAD);
+
1295 phytomer->setFloralBudState(BUD_DEAD);
+
1296 }
+
1297
+
1298 uint Nscaffolds = 4;//context_ptr->randu(4,5);
+
1299
+
1300 for( int i=0; i<Nscaffolds; i++ ) {
+
1301 float pitch = context_ptr->randu(deg2rad(30), deg2rad(35));
+
1302 uint uID_shoot = addChildShoot( plantID, uID_trunk, getShootNodeCount(plantID,uID_trunk)-i-1, context_ptr->randu(5, 7), make_AxisRotation(pitch, (float(i) + context_ptr->randu(-0.2f, 0.2f)) / float(Nscaffolds) * 2 * M_PI, 0), 0.007, 0.06, 1.f, 1.f, 0.5, "scaffold", 0);
+
1303
+
1304 }
+
1305
+
1306 makePlantDormant(plantID);
+
1307
+
1308 setPlantPhenologicalThresholds(plantID, 0, -1, 1, 3, 8, 20, true);
+
1309
+
1310 return plantID;
+
1311
+
1312}
+
1313
+
1314void PlantArchitecture::initializePistachioTreeShoots(){
+
1315
+
1316 // ---- Phytomer Parameters ---- //
+
1317
+
1318 PhytomerParameters phytomer_parameters_pistachio(context_ptr->getRandomGenerator());
+
1319
+
1320 phytomer_parameters_pistachio.internode.pitch = 0;
+
1321 phytomer_parameters_pistachio.internode.phyllotactic_angle.uniformDistribution(160, 200);
+
1322 phytomer_parameters_pistachio.internode.length_segments = 1;
+
1323 phytomer_parameters_pistachio.internode.image_texture = "plugins/plantarchitecture/assets/textures/OliveBark.jpg";
+
1324 phytomer_parameters_pistachio.internode.max_floral_buds_per_petiole = 3;
+
1325
+
1326 phytomer_parameters_pistachio.petiole.petioles_per_internode = 2;
+
1327 phytomer_parameters_pistachio.petiole.pitch.uniformDistribution(-60, -45);
+
1328 phytomer_parameters_pistachio.petiole.taper = 0.1;
+
1329 phytomer_parameters_pistachio.petiole.curvature.uniformDistribution(-800,800);
+
1330 phytomer_parameters_pistachio.petiole.length = 0.075;
+
1331 phytomer_parameters_pistachio.petiole.radius = 0.001;
+
1332 phytomer_parameters_pistachio.petiole.length_segments = 1;
+
1333 phytomer_parameters_pistachio.petiole.radial_subdivisions = 3;
+
1334 phytomer_parameters_pistachio.petiole.color = make_RGBcolor(0.6, 0.6, 0.4);
+
1335
+
1336 phytomer_parameters_pistachio.leaf.leaves_per_petiole = 3;
+
1337 phytomer_parameters_pistachio.leaf.prototype_function = PistachioLeafPrototype;
+
1338 phytomer_parameters_pistachio.leaf.prototype_scale = 0.08;
+
1339 phytomer_parameters_pistachio.leaf.leaflet_offset = 0.3;
+
1340 phytomer_parameters_pistachio.leaf.leaflet_scale = 0.75;
+
1341 phytomer_parameters_pistachio.leaf.pitch.uniformDistribution(-20,20);
+
1342 phytomer_parameters_pistachio.leaf.roll.uniformDistribution(-20,20);
+
1343 phytomer_parameters_pistachio.leaf.unique_prototypes = 5;
+
1344 phytomer_parameters_pistachio.leaf.subdivisions = 3;
+
1345
+
1346 phytomer_parameters_pistachio.peduncle.length = 0.1;
+
1347 phytomer_parameters_pistachio.peduncle.radius = 0.001;
+
1348 phytomer_parameters_pistachio.peduncle.pitch = 60;
+
1349 phytomer_parameters_pistachio.peduncle.roll = 0;
+
1350 phytomer_parameters_pistachio.peduncle.length_segments = 1;
+
1351 phytomer_parameters_pistachio.peduncle.curvature.uniformDistribution(500,900);
+
1352 phytomer_parameters_pistachio.peduncle.color = make_RGBcolor(0.7, 0.72, 0.7);
+
1353
+
1354 phytomer_parameters_pistachio.inflorescence.flowers_per_peduncle = 16;
+
1355 phytomer_parameters_pistachio.inflorescence.flower_offset = 0.08;
+
1356 phytomer_parameters_pistachio.inflorescence.pitch.uniformDistribution(50, 70);
+
1357 phytomer_parameters_pistachio.inflorescence.roll.uniformDistribution(0, 360);
+
1358 phytomer_parameters_pistachio.inflorescence.flower_prototype_scale = 0.025;
+
1359// phytomer_parameters_pistachio.inflorescence.flower_prototype_function = PistachioFlowerPrototype;
+
1360 phytomer_parameters_pistachio.inflorescence.fruit_prototype_scale = 0.025;
+
1361 phytomer_parameters_pistachio.inflorescence.fruit_prototype_function = PistachioFruitPrototype;
+
1362
+
1363 // ---- Shoot Parameters ---- //
+
1364
+
1365 // Trunk
+
1366 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
+
1367 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_pistachio;
+
1368 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 180;
+
1369 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 20;
+
1370 shoot_parameters_trunk.max_nodes = 20;
+
1371 shoot_parameters_trunk.girth_area_factor = 5.f;
+
1372 shoot_parameters_trunk.internode_radius_initial = 0.01;
+
1373 shoot_parameters_trunk.vegetative_bud_break_probability = 0;
+
1374 shoot_parameters_trunk.vegetative_bud_break_time = 0;
+
1375 shoot_parameters_trunk.tortuosity = 2;
+
1376 shoot_parameters_trunk.internode_length_max = 0.05;
+
1377 shoot_parameters_trunk.internode_length_decay_rate = 0;
+
1378 shoot_parameters_trunk.defineChildShootTypes({"proleptic"},{1});
+
1379
+
1380 // Proleptic shoots
+
1381 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
+
1382 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_pistachio;
+
1383 shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = PistachioPhytomerCreationFunction;
+
1384 shoot_parameters_proleptic.phytomer_parameters.phytomer_callback_function = PistachioPhytomerCallbackFunction;
+
1385 shoot_parameters_proleptic.max_nodes = 20;
+
1386 shoot_parameters_proleptic.phyllochron = 1;
+
1387 shoot_parameters_proleptic.elongation_rate = 0.25;
+
1388 shoot_parameters_proleptic.girth_area_factor = 10.f;
+
1389 shoot_parameters_proleptic.vegetative_bud_break_probability = 0.15;
+
1390 shoot_parameters_proleptic.vegetative_bud_break_time = 0;
+
1391 shoot_parameters_proleptic.leaf_flush_count = 1;
+
1392 shoot_parameters_proleptic.gravitropic_curvature = 500;
+
1393 shoot_parameters_proleptic.tortuosity = 10;
+
1394 shoot_parameters_proleptic.internode_radius_initial = 0.002;
+
1395 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 45, 55);
+
1396 shoot_parameters_proleptic.insertion_angle_decay_rate = 10;
+
1397 shoot_parameters_proleptic.internode_length_max = 0.04;
+
1398 shoot_parameters_proleptic.internode_length_min = 0.02;
+
1399 shoot_parameters_proleptic.internode_length_decay_rate = 0.005;
+
1400 shoot_parameters_proleptic.fruit_set_probability = 0.35;
+
1401 shoot_parameters_proleptic.flower_bud_break_probability = 0.35;
+
1402 shoot_parameters_proleptic.max_terminal_floral_buds = 4;
+
1403 shoot_parameters_proleptic.flowers_require_dormancy = true;
+
1404 shoot_parameters_proleptic.growth_requires_dormancy = true;
+
1405 shoot_parameters_proleptic.determinate_shoot_growth = false;
+
1406
+
1407 defineShootType("trunk", shoot_parameters_trunk);
+
1408 defineShootType("proleptic", shoot_parameters_proleptic);
+
1409
+
1410}
+
1411
+
1412uint PlantArchitecture::buildPistachioTree(const helios::vec3 &base_position) {
+
1413
+
1414 if( shoot_types.empty() ){
+
1415 //automatically initialize almond tree shoots
+
1416 initializePistachioTreeShoots();
+
1417 }
+
1418
+
1419 uint plantID = addPlantInstance(base_position, 0);
+
1420
+
1421 uint uID_trunk = addBaseStemShoot(plantID, 19, 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)), 0.015, 0.03, 1.f, 1.f, 0, "trunk");
+
1422 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
+
1423
+
1424 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
+
1425
+
1426 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
+
1427 for( const auto & phytomer : phytomers ){
+
1428 phytomer->removeLeaf();
+
1429 phytomer->setVegetativeBudState(BUD_DEAD);
+
1430 phytomer->setFloralBudState(BUD_DEAD);
+
1431 }
+
1432
+
1433 uint Nscaffolds = 4;//context_ptr->randu(4,5);
+
1434
+
1435 for( int i=0; i<Nscaffolds; i++ ) {
+
1436 float pitch = context_ptr->randu(deg2rad(65), deg2rad(80));
+
1437 uint uID_shoot = addChildShoot( plantID, uID_trunk, getShootNodeCount(plantID,uID_trunk)-i-1, 1, make_AxisRotation(pitch, (float(i) + context_ptr->randu(-0.2f, 0.2f)) / float(Nscaffolds) * 2 * M_PI, 0), 0.007, 0.06, 1.f, 1.f, 0.5, "proleptic", 0);
+
1438
+
1439 }
+
1440
+
1441 makePlantDormant(plantID);
+
1442
+
1443 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 4, 8, 20, false);
+
1444
+
1445 return plantID;
+
1446
+
1447}
+
1448
+
1449void PlantArchitecture::initializePuncturevineShoots() {
+
1450
+
1451 // ---- Phytomer Parameters ---- //
+
1452
+
1453 PhytomerParameters phytomer_parameters_puncturevine(context_ptr->getRandomGenerator());
+
1454
+
1455 phytomer_parameters_puncturevine.internode.pitch.uniformDistribution(0,15);
+
1456 phytomer_parameters_puncturevine.internode.phyllotactic_angle = 180.f;
+
1457 phytomer_parameters_puncturevine.internode.color = make_RGBcolor(0.55, 0.52, 0.39);
+
1458 phytomer_parameters_puncturevine.internode.length_segments = 1;
+
1459
+
1460 phytomer_parameters_puncturevine.petiole.petioles_per_internode = 1;
+
1461 phytomer_parameters_puncturevine.petiole.pitch.uniformDistribution(80, 100);
+
1462 phytomer_parameters_puncturevine.petiole.radius = 0.0003;
+
1463 phytomer_parameters_puncturevine.petiole.length = 0.025;
+
1464 phytomer_parameters_puncturevine.petiole.taper = 0;
+
1465 phytomer_parameters_puncturevine.petiole.curvature = 0;
+
1466 phytomer_parameters_puncturevine.petiole.color = phytomer_parameters_puncturevine.internode.color;
+
1467 phytomer_parameters_puncturevine.petiole.length_segments = 1;
+
1468
+
1469 phytomer_parameters_puncturevine.leaf.leaves_per_petiole = 11;
+
1470 phytomer_parameters_puncturevine.leaf.pitch.uniformDistribution(-10,10);
+
1471 phytomer_parameters_puncturevine.leaf.yaw = 30;
+
1472 phytomer_parameters_puncturevine.leaf.roll.uniformDistribution(-5,5);
+
1473 phytomer_parameters_puncturevine.leaf.prototype_function = PuncturevineLeafPrototype;
+
1474 phytomer_parameters_puncturevine.leaf.prototype_scale = 0.008;
+
1475 phytomer_parameters_puncturevine.leaf.leaflet_offset = 0.15;
+
1476 phytomer_parameters_puncturevine.leaf.leaflet_scale = 1;
+
1477 phytomer_parameters_puncturevine.leaf.subdivisions = 3;
+
1478
+
1479 phytomer_parameters_puncturevine.peduncle.length = 0.001;
+
1480 phytomer_parameters_puncturevine.inflorescence.flowers_per_peduncle = 1;
+
1481 phytomer_parameters_puncturevine.inflorescence.pitch = -90.f;
+
1482 phytomer_parameters_puncturevine.inflorescence.flower_prototype_function = PuncturevineFlowerPrototype;
+
1483 phytomer_parameters_puncturevine.inflorescence.flower_prototype_scale = 0.006;
+
1484
+
1485 // ---- Shoot Parameters ---- //
+
1486
+
1487 ShootParameters shoot_parameters_primary(context_ptr->getRandomGenerator());
+
1488 shoot_parameters_primary.phytomer_parameters = phytomer_parameters_puncturevine;
+
1489 shoot_parameters_primary.vegetative_bud_break_probability = 0.3;
+
1490 shoot_parameters_primary.vegetative_bud_break_time = 3;
+
1491 shoot_parameters_primary.base_roll = 90;
+
1492 shoot_parameters_primary.internode_radius_initial = 0.001;
+
1493 shoot_parameters_primary.phyllochron = 1;
+
1494 shoot_parameters_primary.elongation_rate = 0.2;
+
1495 shoot_parameters_primary.girth_area_factor = 0.f;
+
1496 shoot_parameters_primary.internode_length_max = 0.02;
+
1497 shoot_parameters_primary.internode_length_decay_rate = 0;
+
1498 shoot_parameters_primary.insertion_angle_tip.uniformDistribution(50, 80);
+
1499 shoot_parameters_primary.flowers_require_dormancy = false;
+
1500 shoot_parameters_primary.growth_requires_dormancy = false;
+
1501 shoot_parameters_primary.flower_bud_break_probability = 0.2;
+
1502 shoot_parameters_primary.determinate_shoot_growth = false;
+
1503 shoot_parameters_primary.max_nodes = 15;
+
1504 shoot_parameters_primary.gravitropic_curvature = 20;
+
1505 shoot_parameters_primary.tortuosity = 0;
+
1506 shoot_parameters_primary.defineChildShootTypes({"secondary_puncturevine"}, {1.f});
+
1507
+
1508 ShootParameters shoot_parameters_base = shoot_parameters_primary;
+
1509 shoot_parameters_base.phytomer_parameters = phytomer_parameters_puncturevine;
+
1510 shoot_parameters_base.phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(137.5-10,137.5+10);
+
1511 shoot_parameters_base.phytomer_parameters.petiole.petioles_per_internode = 0;
+
1512 shoot_parameters_base.phytomer_parameters.internode.pitch = 0;
+
1513 shoot_parameters_base.phytomer_parameters.petiole.pitch = 0;
+
1514 shoot_parameters_base.vegetative_bud_break_probability = 1;
+
1515 shoot_parameters_base.vegetative_bud_break_time = 1;
+
1516 shoot_parameters_base.internode_radius_initial = 0.001;
+
1517 shoot_parameters_base.phyllochron = 1;
+
1518 shoot_parameters_base.elongation_rate = 0.25;
+
1519 shoot_parameters_base.gravitropic_curvature = 0;
+
1520 shoot_parameters_base.internode_length_max = 0.01;
+
1521 shoot_parameters_base.internode_length_decay_rate = 0;
+
1522 shoot_parameters_base.insertion_angle_tip = 90;
+
1523 shoot_parameters_base.insertion_angle_decay_rate = 0;
+
1524 shoot_parameters_base.internode_radius_initial = 0.0005;
+
1525 shoot_parameters_base.flowers_require_dormancy = false;
+
1526 shoot_parameters_base.growth_requires_dormancy = false;
+
1527 shoot_parameters_base.flower_bud_break_probability = 0.0;
+
1528 shoot_parameters_base.max_nodes.uniformDistribution(3,5);
+
1529 shoot_parameters_base.defineChildShootTypes({"primary_puncturevine"},{1.f});
+
1530
+
1531 ShootParameters shoot_parameters_children = shoot_parameters_primary;
+
1532 shoot_parameters_children.base_roll = 0;
+
1533
+
1534 defineShootType("base_puncturevine", shoot_parameters_base);
+
1535 defineShootType("primary_puncturevine", shoot_parameters_primary);
+
1536 defineShootType("secondary_puncturevine", shoot_parameters_children);
+
1537
+
1538}
+
1539
+
1540uint PlantArchitecture::buildPuncturevinePlant(const helios::vec3 &base_position) {
+
1541
+
1542 if (shoot_types.empty()) {
+
1543 //automatically initialize puncturevine plant shoots
+
1544 initializePuncturevineShoots();
+
1545 }
+
1546
+
1547 uint plantID = addPlantInstance(base_position, 0);
+
1548
+
1549 uint uID_stem = addBaseStemShoot(plantID, 3, make_AxisRotation(0, 0.f, 0.f), 0.001, 0.001, 1, 1, 0, "base_puncturevine");
+
1550
+
1551 breakPlantDormancy(plantID);
+
1552
+
1553 setPlantPhenologicalThresholds(plantID, 0, -1, 7, 1000, 5, 100, false);
+
1554
+
1555 return plantID;
+
1556
+
1557}
+
1558
+
1559void PlantArchitecture::initializeEasternRedbudShoots() {
+
1560
+
1561 // ---- Phytomer Parameters ---- //
+
1562
+
1563 PhytomerParameters phytomer_parameters_redbud(context_ptr->getRandomGenerator());
+
1564
+
1565 phytomer_parameters_redbud.internode.pitch = 15;
+
1566 phytomer_parameters_redbud.internode.phyllotactic_angle.uniformDistribution(170,190);
+
1567// phytomer_parameters_redbud.internode.color = make_RGBcolor(0.55, 0.52, 0.39);
+
1568 phytomer_parameters_redbud.internode.image_texture = "plugins/plantarchitecture/assets/textures/WesternRedbudBark.jpg";
+
1569 phytomer_parameters_redbud.internode.color.scale(0.3);
+
1570 phytomer_parameters_redbud.internode.length_segments = 1;
+
1571 phytomer_parameters_redbud.internode.max_floral_buds_per_petiole = 5;
+
1572
+
1573 phytomer_parameters_redbud.petiole.petioles_per_internode = 1;
+
1574 phytomer_parameters_redbud.petiole.color = make_RGBcolor(0.65, 0.52, 0.39);
+
1575 phytomer_parameters_redbud.petiole.pitch.uniformDistribution(20, 40);
+
1576 phytomer_parameters_redbud.petiole.radius = 0.0017;
+
1577 phytomer_parameters_redbud.petiole.length = 0.05;
+
1578 phytomer_parameters_redbud.petiole.taper = 0;
+
1579 phytomer_parameters_redbud.petiole.curvature = 0;
+
1580 phytomer_parameters_redbud.petiole.length_segments = 1;
+
1581
+
1582 phytomer_parameters_redbud.leaf.leaves_per_petiole = 1;
+
1583 phytomer_parameters_redbud.leaf.pitch.uniformDistribution(-110, -80);
+
1584 phytomer_parameters_redbud.leaf.yaw = 0;
+
1585 phytomer_parameters_redbud.leaf.roll.uniformDistribution(-5, 5);
+
1586 phytomer_parameters_redbud.leaf.prototype_function = RedbudLeafPrototype;
+
1587 phytomer_parameters_redbud.leaf.prototype_scale = 0.1;
+
1588 phytomer_parameters_redbud.leaf.subdivisions = 5;
+
1589
+
1590 phytomer_parameters_redbud.peduncle.length = 0.02;
+
1591 phytomer_parameters_redbud.peduncle.pitch.uniformDistribution(50,90);
+
1592 phytomer_parameters_redbud.peduncle.color = make_RGBcolor(0.32, 0.05, 0.13);
+
1593
+
1594 phytomer_parameters_redbud.inflorescence.flowers_per_peduncle = 1;
+
1595 phytomer_parameters_redbud.inflorescence.pitch = 0;
+
1596 phytomer_parameters_redbud.inflorescence.flower_prototype_function = RedbudFlowerPrototype;
+
1597 phytomer_parameters_redbud.inflorescence.flower_prototype_scale = 0.04;
+
1598 phytomer_parameters_redbud.inflorescence.fruit_prototype_function = RedbudFruitPrototype;
+
1599 phytomer_parameters_redbud.inflorescence.fruit_prototype_scale = 0.1;
+
1600 phytomer_parameters_redbud.inflorescence.fruit_gravity_factor_fraction = 0.7;
+
1601
+
1602 phytomer_parameters_redbud.phytomer_creation_function = RedbudPhytomerCreationFunction;
+
1603 phytomer_parameters_redbud.phytomer_callback_function = RedbudPhytomerCallbackFunction;
+
1604
+
1605 // ---- Shoot Parameters ---- //
+
1606
+
1607 ShootParameters shoot_parameters_main(context_ptr->getRandomGenerator());
+
1608 shoot_parameters_main.phytomer_parameters = phytomer_parameters_redbud;
+
1609 shoot_parameters_main.vegetative_bud_break_probability = 1.0;
+
1610 shoot_parameters_main.vegetative_bud_break_time = 1;
+
1611 shoot_parameters_main.phyllochron = 1.5;
+
1612 shoot_parameters_main.elongation_rate = 0.17;
+
1613 shoot_parameters_main.girth_area_factor = 5.f;
+
1614 shoot_parameters_main.gravitropic_curvature = 300;
+
1615 shoot_parameters_main.tortuosity = 10;
+
1616 shoot_parameters_main.internode_length_max = 0.04;
+
1617 shoot_parameters_main.internode_length_decay_rate = 0.005;
+
1618 shoot_parameters_main.insertion_angle_tip = 75;
+
1619 shoot_parameters_main.insertion_angle_decay_rate = 10;
+
1620 shoot_parameters_main.internode_radius_initial = 0.0015;
+
1621 shoot_parameters_main.internode_radius_max = 0.02;
+
1622 shoot_parameters_main.flowers_require_dormancy = true;
+
1623 shoot_parameters_main.growth_requires_dormancy = true;
+
1624 shoot_parameters_main.determinate_shoot_growth = false;
+
1625 shoot_parameters_main.max_terminal_floral_buds = 0;
+
1626 shoot_parameters_main.flower_bud_break_probability = 0.8;
+
1627 shoot_parameters_main.fruit_set_probability = 0.3;
+
1628 shoot_parameters_main.max_nodes = 30;
+
1629 shoot_parameters_main.base_roll = 90;
+
1630
+
1631 ShootParameters shoot_parameters_trunk = shoot_parameters_main;
+
1632 shoot_parameters_trunk.phytomer_parameters.internode.pitch = 0;
+
1633 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 15;
+
1634 shoot_parameters_trunk.phytomer_parameters.internode.max_floral_buds_per_petiole = 0;
+
1635 shoot_parameters_trunk.internode_radius_max = 1;
+
1636 shoot_parameters_trunk.phyllochron = 1.25;
+
1637 shoot_parameters_trunk.insertion_angle_tip = 60;
+
1638 shoot_parameters_trunk.max_nodes = 45;
+
1639 shoot_parameters_trunk.tortuosity = 0.5;
+
1640 shoot_parameters_trunk.defineChildShootTypes({"eastern_redbud_shoot"},{1.f});
+
1641
+
1642 defineShootType("eastern_redbud_trunk", shoot_parameters_trunk);
+
1643 defineShootType("eastern_redbud_shoot", shoot_parameters_main);
+
1644
+
1645}
+
1646
+
1647uint PlantArchitecture::buildEasternRedbudPlant(const helios::vec3 &base_position) {
+
1648
+
1649 if (shoot_types.empty()) {
+
1650 //automatically initialize redbud plant shoots
+
1651 initializeEasternRedbudShoots();
+
1652 }
+
1653
+
1654 uint plantID = addPlantInstance(base_position, 0);
+
1655
+
1656 uint uID_stem = addBaseStemShoot(plantID, 16, make_AxisRotation(context_ptr->randu(0,0.1*M_PI), context_ptr->randu(0,2*M_PI), context_ptr->randu(0,2*M_PI)), 0.0075, 0.05, 1, 1, 0.4, "eastern_redbud_trunk");
+
1657
+
1658 makePlantDormant(plantID);
+
1659
+
1660 removeShootLeaves( plantID, uID_stem );
+
1661
+
1662 setPlantPhenologicalThresholds(plantID, 0, -1, 1, 3, 3, 12, false);
+
1663
+
1664 return plantID;
+
1665
+
1666}
+
1667
+
1668void PlantArchitecture::initializeRomaineLettuceShoots() {
+
1669
+
1670 // ---- Phytomer Parameters ---- //
+
1671
+
1672 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
+
1673
+
1674 phytomer_parameters.internode.pitch = 0;
+
1675 phytomer_parameters.internode.phyllotactic_angle = 137.5;
+
1676 phytomer_parameters.internode.color = make_RGBcolor(0.402,0.423,0.413);
+
1677 phytomer_parameters.internode.length_segments = 1;
+
1678 phytomer_parameters.internode.radial_subdivisions = 10;
+
1679
+
1680 phytomer_parameters.petiole.petioles_per_internode = 1;
+
1681 phytomer_parameters.petiole.pitch.uniformDistribution(0,30);
+
1682 phytomer_parameters.petiole.radius = 0.001;
+
1683 phytomer_parameters.petiole.length = 0.001;
+
1684 phytomer_parameters.petiole.length_segments = 1;
+
1685 phytomer_parameters.petiole.radial_subdivisions = 3;
+
1686 phytomer_parameters.petiole.color = RGB::red;
+
1687
+
1688 phytomer_parameters.leaf.leaves_per_petiole = 1;
+
1689 phytomer_parameters.leaf.pitch = 0;
+
1690 phytomer_parameters.leaf.yaw = 0;
+
1691 phytomer_parameters.leaf.roll = 0;
+
1692 phytomer_parameters.leaf.prototype_function = RomaineLettuceLeafPrototype;
+
1693 phytomer_parameters.leaf.prototype_scale.uniformDistribution(0.15,0.25);
+
1694 phytomer_parameters.leaf.subdivisions = 30;
+
1695
+
1696 phytomer_parameters.phytomer_creation_function = RomaineLettucePhytomerCreationFunction;
+
1697
+
1698 // ---- Shoot Parameters ---- //
+
1699
+
1700 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
+
1701 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters;
+
1702 shoot_parameters_mainstem.vegetative_bud_break_probability = 0;
+
1703 shoot_parameters_mainstem.internode_radius_initial = 0.01;
+
1704 shoot_parameters_mainstem.phyllochron = 1;
+
1705 shoot_parameters_mainstem.elongation_rate = 0.15;
+
1706 shoot_parameters_mainstem.girth_area_factor = 0.f;
+
1707 shoot_parameters_mainstem.gravitropic_curvature = 10;
+
1708 shoot_parameters_mainstem.internode_length_max = 0.001;
+
1709 shoot_parameters_mainstem.internode_length_decay_rate = 0;
+
1710 shoot_parameters_mainstem.flowers_require_dormancy = false;
+
1711 shoot_parameters_mainstem.growth_requires_dormancy = false;
+
1712 shoot_parameters_mainstem.flower_bud_break_probability = 0.0;
+
1713 shoot_parameters_mainstem.max_nodes = 25;
+
1714
+
1715 defineShootType("mainstem",shoot_parameters_mainstem);
1716
-
1717}
-
1718
-
1719uint PlantArchitecture::buildRomaineLettucePlant(const helios::vec3 &base_position) {
-
1720
-
1721 if (shoot_types.empty()) {
-
1722 //automatically initialize sugarbeet plant shoots
-
1723 initializeSugarbeetShoots();
-
1724 }
-
1725
-
1726 uint plantID = addPlantInstance(base_position, 0);
-
1727
-
1728 uint uID_stem = addBaseStemShoot(plantID, 3, make_AxisRotation(context_ptr->randu(0.f, 0.03f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), 0.25f * M_PI), 0.005, 0.001, 1, 1, 0, "mainstem");
-
1729
-
1730 breakPlantDormancy(plantID);
-
1731
-
1732 setPlantPhenologicalThresholds(plantID, 0, 1000, 10, 60, 5, 100, false);
-
1733
-
1734 return plantID;
-
1735
-
1736}
-
1737
-
1738void PlantArchitecture::initializeSorghumShoots() {
-
1739
-
1740 // ---- Phytomer Parameters ---- //
-
1741
-
1742 PhytomerParameters phytomer_parameters_sorghum(context_ptr->getRandomGenerator());
-
1743
-
1744 phytomer_parameters_sorghum.internode.pitch = 0;
-
1745 phytomer_parameters_sorghum.internode.phyllotactic_angle.uniformDistribution(170,190);
-
1746 phytomer_parameters_sorghum.internode.color = make_RGBcolor(0.09,0.13,0.06);
-
1747 phytomer_parameters_sorghum.internode.length_segments = 2;
-
1748 phytomer_parameters_sorghum.internode.radial_subdivisions = 10;
-
1749 phytomer_parameters_sorghum.internode.max_floral_buds_per_petiole = 0;
-
1750 phytomer_parameters_sorghum.internode.max_vegetative_buds_per_petiole = 0;
-
1751
-
1752 phytomer_parameters_sorghum.petiole.petioles_per_internode = 1;
-
1753 phytomer_parameters_sorghum.petiole.pitch.uniformDistribution(-40,-20);
-
1754 phytomer_parameters_sorghum.petiole.radius = 0.0;
-
1755 phytomer_parameters_sorghum.petiole.length = 0.05;
-
1756 phytomer_parameters_sorghum.petiole.taper = 0;
-
1757 phytomer_parameters_sorghum.petiole.curvature = 0;
-
1758 phytomer_parameters_sorghum.petiole.length_segments = 1;
-
1759
-
1760 phytomer_parameters_sorghum.leaf.leaves_per_petiole = 1;
-
1761 phytomer_parameters_sorghum.leaf.pitch = 0;
-
1762 phytomer_parameters_sorghum.leaf.yaw = 0;
-
1763 phytomer_parameters_sorghum.leaf.roll = 0;
-
1764 phytomer_parameters_sorghum.leaf.prototype_function = SorghumLeafPrototype;
-
1765 phytomer_parameters_sorghum.leaf.prototype_scale = 0.6;
-
1766 phytomer_parameters_sorghum.leaf.subdivisions = 50;
-
1767 phytomer_parameters_sorghum.leaf.unique_prototypes = 10;
-
1768
-
1769 phytomer_parameters_sorghum.peduncle.length = 0.3;
-
1770 phytomer_parameters_sorghum.peduncle.radius = 0.008;
-
1771 phytomer_parameters_sorghum.peduncle.color = phytomer_parameters_sorghum.internode.color;
-
1772 phytomer_parameters_sorghum.peduncle.radial_subdivisions = 10;
-
1773
-
1774 phytomer_parameters_sorghum.inflorescence.flowers_per_peduncle = 1;
-
1775 phytomer_parameters_sorghum.inflorescence.pitch = 0;
-
1776 phytomer_parameters_sorghum.inflorescence.roll = 0;
-
1777 phytomer_parameters_sorghum.inflorescence.fruit_prototype_scale = 0.16;
-
1778 phytomer_parameters_sorghum.inflorescence.fruit_prototype_function = SorghumPaniclePrototype;
-
1779
-
1780 phytomer_parameters_sorghum.phytomer_creation_function = SorghumPhytomerCreationFunction;
-
1781
-
1782 // ---- Shoot Parameters ---- //
-
1783
-
1784 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
-
1785 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_sorghum;
-
1786 shoot_parameters_mainstem.vegetative_bud_break_probability = 0;
-
1787 shoot_parameters_mainstem.flower_bud_break_probability = 1;
-
1788 shoot_parameters_mainstem.internode_radius_initial = 0.003;
-
1789 shoot_parameters_mainstem.phyllochron = 1;
-
1790 shoot_parameters_mainstem.elongation_rate = 0.15;
-
1791 shoot_parameters_mainstem.girth_area_factor = 5.f;
-
1792 shoot_parameters_mainstem.internode_radius_max = 0.015;
-
1793 shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-1000,-400);
-
1794 shoot_parameters_mainstem.internode_length_max = 0.26;
-
1795 shoot_parameters_mainstem.internode_length_decay_rate = 0;
-
1796 shoot_parameters_mainstem.flowers_require_dormancy = false;
-
1797 shoot_parameters_mainstem.growth_requires_dormancy = false;
-
1798 shoot_parameters_mainstem.determinate_shoot_growth = false;
-
1799 shoot_parameters_mainstem.flower_bud_break_probability = 1.0;
-
1800 shoot_parameters_mainstem.fruit_set_probability = 1.0;
-
1801 shoot_parameters_mainstem.defineChildShootTypes({"mainstem"},{1.0});
-
1802 shoot_parameters_mainstem.max_nodes = 15;
-
1803 shoot_parameters_mainstem.max_terminal_floral_buds = 1;
-
1804
-
1805 defineShootType("mainstem",shoot_parameters_mainstem);
-
1806
-
1807}
-
1808
-
1809uint PlantArchitecture::buildSorghumPlant(const helios::vec3 &base_position) {
-
1810
-
1811 if (shoot_types.empty()) {
-
1812 //automatically initialize sorghum plant shoots
-
1813 initializeSorghumShoots();
-
1814 }
-
1815
-
1816 uint plantID = addPlantInstance(base_position - make_vec3(0,0,0.025), 0);
-
1817
-
1818 uint uID_stem = addBaseStemShoot(plantID, 1, make_AxisRotation(context_ptr->randu(0.f, 0.075f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI)), 0.003, 0.06, 0.01, 0.01, 0, "mainstem");
-
1819
-
1820 breakPlantDormancy(plantID);
-
1821
-
1822 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 2, 5, 100, false);
-
1823
-
1824 return plantID;
-
1825
-
1826}
-
1827
-
1828void PlantArchitecture::initializeSoybeanShoots() {
-
1829
-
1830 PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
-
1831
-
1832 phytomer_parameters_trifoliate.internode.pitch = 20;
-
1833 phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
-
1834 phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
-
1835 phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
-
1836 phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.2,0.25,0.05);
-
1837 phytomer_parameters_trifoliate.internode.length_segments = 5;
-
1838
-
1839 phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
-
1840 phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(25,50);
-
1841 phytomer_parameters_trifoliate.petiole.radius = 0.003;
-
1842 phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.12,0.16);
-
1843 phytomer_parameters_trifoliate.petiole.taper = 0.25;
-
1844 phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-250,450);
-
1845 phytomer_parameters_trifoliate.petiole.color = phytomer_parameters_trifoliate.internode.color;
-
1846 phytomer_parameters_trifoliate.petiole.length_segments = 5;
-
1847 phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
-
1848
-
1849 phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
-
1850 phytomer_parameters_trifoliate.leaf.pitch.uniformDistribution(-10, 20);
-
1851 phytomer_parameters_trifoliate.leaf.yaw = 10;
-
1852 phytomer_parameters_trifoliate.leaf.roll = -15;
-
1853 phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.5;
-
1854 phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
-
1855 phytomer_parameters_trifoliate.leaf.prototype_function = SoybeanLeafPrototype_trifoliate;
-
1856 phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.12,0.16);
-
1857 phytomer_parameters_trifoliate.leaf.subdivisions = 8;
-
1858 phytomer_parameters_trifoliate.leaf.unique_prototypes = 5;
-
1859
-
1860 phytomer_parameters_trifoliate.peduncle.length = 0.01;
-
1861 phytomer_parameters_trifoliate.peduncle.radius = 0.001;
-
1862 phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 40);
-
1863 phytomer_parameters_trifoliate.peduncle.roll = 90;
-
1864 phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(-500, 500);
-
1865 phytomer_parameters_trifoliate.peduncle.length_segments = 1;
-
1866 phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
-
1867
-
1868 phytomer_parameters_trifoliate.inflorescence.flowers_per_peduncle.uniformDistribution(1, 4);
-
1869 phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.2;
-
1870 phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
-
1871 phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
-
1872 phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.015;
-
1873 phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = SoybeanFlowerPrototype;
-
1874 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.08,0.1);
-
1875 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = SoybeanFruitPrototype;
-
1876 phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.8,1.0);
-
1877
-
1878 PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
-
1879 phytomer_parameters_unifoliate.internode.pitch = 0;
-
1880 phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 0;
-
1881 phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
-
1882 phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
-
1883 phytomer_parameters_unifoliate.petiole.length = 0.01;
-
1884 phytomer_parameters_unifoliate.petiole.radius = 0.001;
-
1885 phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(60,80);
-
1886 phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
-
1887 phytomer_parameters_unifoliate.leaf.prototype_scale = 0.02;
-
1888 phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
-
1889 phytomer_parameters_unifoliate.leaf.prototype_function = SoybeanLeafPrototype_unifoliate;
-
1890
-
1891 // ---- Shoot Parameters ---- //
-
1892
-
1893 ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
-
1894 shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
-
1895 shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = BeanPhytomerCreationFunction;
-
1896
-
1897 shoot_parameters_trifoliate.max_nodes = 20;
-
1898 shoot_parameters_trifoliate.internode_radius_initial = 0.001;
-
1899 shoot_parameters_trifoliate.internode_radius_max = 0.004;
-
1900 shoot_parameters_trifoliate.insertion_angle_tip.uniformDistribution(40,60);
-
1901// shoot_parameters_trifoliate.child_insertion_angle_decay_rate = 0; (default)
-
1902 shoot_parameters_trifoliate.internode_length_max = 0.035;
-
1903// shoot_parameters_trifoliate.child_internode_length_min = 0.0; (default)
-
1904// shoot_parameters_trifoliate.child_internode_length_decay_rate = 0; (default)
-
1905 shoot_parameters_trifoliate.base_roll = 90;
-
1906 shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
-
1907 shoot_parameters_trifoliate.gravitropic_curvature = 200;
-
1908
-
1909 shoot_parameters_trifoliate.phyllochron = 1;
-
1910// shoot_parameters_trifoliate.leaf_flush_count = 1; (default)
-
1911 shoot_parameters_trifoliate.elongation_rate = 0.15;
-
1912 shoot_parameters_trifoliate.girth_area_factor = 25.f;
-
1913 shoot_parameters_trifoliate.vegetative_bud_break_time = 3;
-
1914 shoot_parameters_trifoliate.vegetative_bud_break_probability = 0.25;
-
1915// shoot_parameters_trifoliate.max_terminal_floral_buds = 0; (default)
-
1916 shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.8,1.0);
-
1917 shoot_parameters_trifoliate.fruit_set_probability = 0.4;
-
1918// shoot_parameters_trifoliate.flowers_require_dormancy = false; (default)
-
1919// shoot_parameters_trifoliate.growth_requires_dormancy = false; (default)
-
1920// shoot_parameters_trifoliate.determinate_shoot_growth = true; (default)
-
1921
-
1922 shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
-
1923
+
1717
+
1718}
+
1719
+
1720uint PlantArchitecture::buildRomaineLettucePlant(const helios::vec3 &base_position) {
+
1721
+
1722 if (shoot_types.empty()) {
+
1723 //automatically initialize sugarbeet plant shoots
+
1724 initializeSugarbeetShoots();
+
1725 }
+
1726
+
1727 uint plantID = addPlantInstance(base_position, 0);
+
1728
+
1729 uint uID_stem = addBaseStemShoot(plantID, 3, make_AxisRotation(context_ptr->randu(0.f, 0.03f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), 0.25f * M_PI), 0.005, 0.001, 1, 1, 0, "mainstem");
+
1730
+
1731 breakPlantDormancy(plantID);
+
1732
+
1733 setPlantPhenologicalThresholds(plantID, 0, 1000, 10, 60, 5, 100, false);
+
1734
+
1735 return plantID;
+
1736
+
1737}
+
1738
+
1739void PlantArchitecture::initializeSorghumShoots() {
+
1740
+
1741 // ---- Phytomer Parameters ---- //
+
1742
+
1743 PhytomerParameters phytomer_parameters_sorghum(context_ptr->getRandomGenerator());
+
1744
+
1745 phytomer_parameters_sorghum.internode.pitch = 0;
+
1746 phytomer_parameters_sorghum.internode.phyllotactic_angle.uniformDistribution(170,190);
+
1747 phytomer_parameters_sorghum.internode.color = make_RGBcolor(0.09,0.13,0.06);
+
1748 phytomer_parameters_sorghum.internode.length_segments = 2;
+
1749 phytomer_parameters_sorghum.internode.radial_subdivisions = 10;
+
1750 phytomer_parameters_sorghum.internode.max_floral_buds_per_petiole = 0;
+
1751 phytomer_parameters_sorghum.internode.max_vegetative_buds_per_petiole = 0;
+
1752
+
1753 phytomer_parameters_sorghum.petiole.petioles_per_internode = 1;
+
1754 phytomer_parameters_sorghum.petiole.pitch.uniformDistribution(-40,-20);
+
1755 phytomer_parameters_sorghum.petiole.radius = 0.0;
+
1756 phytomer_parameters_sorghum.petiole.length = 0.05;
+
1757 phytomer_parameters_sorghum.petiole.taper = 0;
+
1758 phytomer_parameters_sorghum.petiole.curvature = 0;
+
1759 phytomer_parameters_sorghum.petiole.length_segments = 1;
+
1760
+
1761 phytomer_parameters_sorghum.leaf.leaves_per_petiole = 1;
+
1762 phytomer_parameters_sorghum.leaf.pitch = 0;
+
1763 phytomer_parameters_sorghum.leaf.yaw = 0;
+
1764 phytomer_parameters_sorghum.leaf.roll = 0;
+
1765 phytomer_parameters_sorghum.leaf.prototype_function = SorghumLeafPrototype;
+
1766 phytomer_parameters_sorghum.leaf.prototype_scale = 0.6;
+
1767 phytomer_parameters_sorghum.leaf.subdivisions = 50;
+
1768 phytomer_parameters_sorghum.leaf.unique_prototypes = 10;
+
1769
+
1770 phytomer_parameters_sorghum.peduncle.length = 0.3;
+
1771 phytomer_parameters_sorghum.peduncle.radius = 0.008;
+
1772 phytomer_parameters_sorghum.peduncle.color = phytomer_parameters_sorghum.internode.color;
+
1773 phytomer_parameters_sorghum.peduncle.radial_subdivisions = 10;
+
1774
+
1775 phytomer_parameters_sorghum.inflorescence.flowers_per_peduncle = 1;
+
1776 phytomer_parameters_sorghum.inflorescence.pitch = 0;
+
1777 phytomer_parameters_sorghum.inflorescence.roll = 0;
+
1778 phytomer_parameters_sorghum.inflorescence.fruit_prototype_scale = 0.16;
+
1779 phytomer_parameters_sorghum.inflorescence.fruit_prototype_function = SorghumPaniclePrototype;
+
1780
+
1781 phytomer_parameters_sorghum.phytomer_creation_function = SorghumPhytomerCreationFunction;
+
1782
+
1783 // ---- Shoot Parameters ---- //
+
1784
+
1785 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
+
1786 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_sorghum;
+
1787 shoot_parameters_mainstem.vegetative_bud_break_probability = 0;
+
1788 shoot_parameters_mainstem.flower_bud_break_probability = 1;
+
1789 shoot_parameters_mainstem.internode_radius_initial = 0.003;
+
1790 shoot_parameters_mainstem.phyllochron = 1;
+
1791 shoot_parameters_mainstem.elongation_rate = 0.15;
+
1792 shoot_parameters_mainstem.girth_area_factor = 5.f;
+
1793 shoot_parameters_mainstem.internode_radius_max = 0.015;
+
1794 shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-1000,-400);
+
1795 shoot_parameters_mainstem.internode_length_max = 0.26;
+
1796 shoot_parameters_mainstem.internode_length_decay_rate = 0;
+
1797 shoot_parameters_mainstem.flowers_require_dormancy = false;
+
1798 shoot_parameters_mainstem.growth_requires_dormancy = false;
+
1799 shoot_parameters_mainstem.determinate_shoot_growth = false;
+
1800 shoot_parameters_mainstem.flower_bud_break_probability = 1.0;
+
1801 shoot_parameters_mainstem.fruit_set_probability = 1.0;
+
1802 shoot_parameters_mainstem.defineChildShootTypes({"mainstem"},{1.0});
+
1803 shoot_parameters_mainstem.max_nodes = 15;
+
1804 shoot_parameters_mainstem.max_terminal_floral_buds = 1;
+
1805
+
1806 defineShootType("mainstem",shoot_parameters_mainstem);
+
1807
+
1808}
+
1809
+
1810uint PlantArchitecture::buildSorghumPlant(const helios::vec3 &base_position) {
+
1811
+
1812 if (shoot_types.empty()) {
+
1813 //automatically initialize sorghum plant shoots
+
1814 initializeSorghumShoots();
+
1815 }
+
1816
+
1817 uint plantID = addPlantInstance(base_position - make_vec3(0,0,0.025), 0);
+
1818
+
1819 uint uID_stem = addBaseStemShoot(plantID, 1, make_AxisRotation(context_ptr->randu(0.f, 0.075f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI)), 0.003, 0.06, 0.01, 0.01, 0, "mainstem");
+
1820
+
1821 breakPlantDormancy(plantID);
+
1822
+
1823 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 2, 5, 100, false);
+
1824
+
1825 return plantID;
+
1826
+
1827}
+
1828
+
1829void PlantArchitecture::initializeSoybeanShoots() {
+
1830
+
1831 PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
+
1832
+
1833 phytomer_parameters_trifoliate.internode.pitch = 20;
+
1834 phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
+
1835 phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
+
1836 phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
+
1837 phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.2,0.25,0.05);
+
1838 phytomer_parameters_trifoliate.internode.length_segments = 5;
+
1839
+
1840 phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
+
1841 phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(25,50);
+
1842 phytomer_parameters_trifoliate.petiole.radius = 0.003;
+
1843 phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.12,0.16);
+
1844 phytomer_parameters_trifoliate.petiole.taper = 0.25;
+
1845 phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-250,450);
+
1846 phytomer_parameters_trifoliate.petiole.color = phytomer_parameters_trifoliate.internode.color;
+
1847 phytomer_parameters_trifoliate.petiole.length_segments = 5;
+
1848 phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
+
1849
+
1850 phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
+
1851 phytomer_parameters_trifoliate.leaf.pitch.uniformDistribution(-10, 20);
+
1852 phytomer_parameters_trifoliate.leaf.yaw = 10;
+
1853 phytomer_parameters_trifoliate.leaf.roll = -15;
+
1854 phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.5;
+
1855 phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
+
1856 phytomer_parameters_trifoliate.leaf.prototype_function = SoybeanLeafPrototype_trifoliate;
+
1857 phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.12,0.16);
+
1858 phytomer_parameters_trifoliate.leaf.subdivisions = 8;
+
1859 phytomer_parameters_trifoliate.leaf.unique_prototypes = 5;
+
1860
+
1861 phytomer_parameters_trifoliate.peduncle.length = 0.01;
+
1862 phytomer_parameters_trifoliate.peduncle.radius = 0.001;
+
1863 phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 40);
+
1864 phytomer_parameters_trifoliate.peduncle.roll = 90;
+
1865 phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(-500, 500);
+
1866 phytomer_parameters_trifoliate.peduncle.length_segments = 1;
+
1867 phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
+
1868
+
1869 phytomer_parameters_trifoliate.inflorescence.flowers_per_peduncle.uniformDistribution(1, 4);
+
1870 phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.2;
+
1871 phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
+
1872 phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
+
1873 phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.015;
+
1874 phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = SoybeanFlowerPrototype;
+
1875 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.08,0.1);
+
1876 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = SoybeanFruitPrototype;
+
1877 phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.8,1.0);
+
1878
+
1879 PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
+
1880 phytomer_parameters_unifoliate.internode.pitch = 0;
+
1881 phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 0;
+
1882 phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
+
1883 phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
+
1884 phytomer_parameters_unifoliate.petiole.length = 0.01;
+
1885 phytomer_parameters_unifoliate.petiole.radius = 0.001;
+
1886 phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(60,80);
+
1887 phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
+
1888 phytomer_parameters_unifoliate.leaf.prototype_scale = 0.02;
+
1889 phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
+
1890 phytomer_parameters_unifoliate.leaf.prototype_function = SoybeanLeafPrototype_unifoliate;
+
1891
+
1892 // ---- Shoot Parameters ---- //
+
1893
+
1894 ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
+
1895 shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
+
1896 shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = BeanPhytomerCreationFunction;
+
1897
+
1898 shoot_parameters_trifoliate.max_nodes = 20;
+
1899 shoot_parameters_trifoliate.internode_radius_initial = 0.001;
+
1900 shoot_parameters_trifoliate.internode_radius_max = 0.004;
+
1901 shoot_parameters_trifoliate.insertion_angle_tip.uniformDistribution(40,60);
+
1902// shoot_parameters_trifoliate.child_insertion_angle_decay_rate = 0; (default)
+
1903 shoot_parameters_trifoliate.internode_length_max = 0.035;
+
1904// shoot_parameters_trifoliate.child_internode_length_min = 0.0; (default)
+
1905// shoot_parameters_trifoliate.child_internode_length_decay_rate = 0; (default)
+
1906 shoot_parameters_trifoliate.base_roll = 90;
+
1907 shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
+
1908 shoot_parameters_trifoliate.gravitropic_curvature = 200;
+
1909
+
1910 shoot_parameters_trifoliate.phyllochron = 1;
+
1911// shoot_parameters_trifoliate.leaf_flush_count = 1; (default)
+
1912 shoot_parameters_trifoliate.elongation_rate = 0.15;
+
1913 shoot_parameters_trifoliate.girth_area_factor = 25.f;
+
1914 shoot_parameters_trifoliate.vegetative_bud_break_time = 3;
+
1915 shoot_parameters_trifoliate.vegetative_bud_break_probability = 0.25;
+
1916// shoot_parameters_trifoliate.max_terminal_floral_buds = 0; (default)
+
1917 shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.8,1.0);
+
1918 shoot_parameters_trifoliate.fruit_set_probability = 0.4;
+
1919// shoot_parameters_trifoliate.flowers_require_dormancy = false; (default)
+
1920// shoot_parameters_trifoliate.growth_requires_dormancy = false; (default)
+
1921// shoot_parameters_trifoliate.determinate_shoot_growth = true; (default)
+
1922
+
1923 shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
1924
-
1925 ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
-
1926 shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
-
1927 shoot_parameters_unifoliate.max_nodes = 1;
-
1928 shoot_parameters_unifoliate.vegetative_bud_break_probability = 0;
-
1929 shoot_parameters_unifoliate.flower_bud_break_probability = 0;
-
1930 shoot_parameters_unifoliate.insertion_angle_tip = 0;
-
1931 shoot_parameters_unifoliate.insertion_angle_decay_rate = 0;
-
1932 shoot_parameters_unifoliate.vegetative_bud_break_time = 1;
-
1933 shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
-
1934
-
1935 defineShootType("unifoliate",shoot_parameters_unifoliate);
-
1936 defineShootType("trifoliate",shoot_parameters_trifoliate);
-
1937
-
1938// PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
-
1939//
-
1940// phytomer_parameters_trifoliate.internode.pitch = 20;
-
1941// phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
-
1942// phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
-
1943// phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
-
1944// phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.2,0.25,0.05);
-
1945// phytomer_parameters_trifoliate.internode.length_segments = 5;
-
1946//
-
1947// phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
-
1948// phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(30,70);
-
1949// phytomer_parameters_trifoliate.petiole.radius = 0.003;
-
1950// phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.12,0.16);
-
1951// phytomer_parameters_trifoliate.petiole.taper = 0.25;
-
1952// phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-100,200);
-
1953// phytomer_parameters_trifoliate.petiole.color = make_RGBcolor(0.28,0.35,0.07);
-
1954// phytomer_parameters_trifoliate.petiole.length_segments = 5;
-
1955// phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
-
1956//
-
1957// phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
-
1958// phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(0, 10);
-
1959// phytomer_parameters_trifoliate.leaf.yaw = 10;
-
1960// phytomer_parameters_trifoliate.leaf.roll = -15;
-
1961// phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.2;
-
1962// phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
-
1963// phytomer_parameters_trifoliate.leaf.prototype_function = SoybeanLeafPrototype_trifoliate;
-
1964// phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.11,0.13);
-
1965// phytomer_parameters_trifoliate.leaf.subdivisions = 10;
-
1966// phytomer_parameters_trifoliate.leaf.unique_prototypes = 5;
-
1967//
-
1968// phytomer_parameters_trifoliate.peduncle.length = 0.04;
-
1969// phytomer_parameters_trifoliate.peduncle.radius = 0.001;
-
1970// phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 40);
-
1971// phytomer_parameters_trifoliate.peduncle.roll = 90;
-
1972// phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(-500, 500);
-
1973// phytomer_parameters_trifoliate.peduncle.length_segments = 1;
-
1974// phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
-
1975//
-
1976// phytomer_parameters_trifoliate.inflorescence.flowers_per_rachis.uniformDistribution(1, 4);
-
1977// phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.2;
-
1978// phytomer_parameters_trifoliate.inflorescence.flower_arrangement_pattern = "opposite";
-
1979// phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
-
1980// phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
-
1981// phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.015;
-
1982// phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = BeanFlowerPrototype;
-
1983// phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.08,0.1);
-
1984// phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = BeanFruitPrototype;
-
1985// phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.8,1.0);
-
1986//
-
1987// PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
-
1988// phytomer_parameters_unifoliate.internode.pitch = 0;
-
1989// phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 0;
-
1990// phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
-
1991// phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
-
1992// phytomer_parameters_unifoliate.petiole.length = 0.001;
-
1993// phytomer_parameters_unifoliate.petiole.radius = 0.0004;
-
1994// phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(60,80);
-
1995// phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
-
1996// phytomer_parameters_unifoliate.leaf.prototype_scale = 0.02;
-
1997// phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
-
1998// phytomer_parameters_unifoliate.leaf.prototype_function = BeanLeafPrototype_unifoliate;
-
1999//
-
2000// // ---- Shoot Parameters ---- //
-
2001//
-
2002// ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
-
2003// shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
-
2004// shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = BeanPhytomerCreationFunction;
-
2005//
-
2006// shoot_parameters_trifoliate.max_nodes = 25;
-
2007// shoot_parameters_trifoliate.internode_radius_initial = 0.0005;
-
2008// shoot_parameters_trifoliate.internode_radius_max = 0.003;
-
2009// shoot_parameters_trifoliate.insertion_angle_tip.uniformDistribution(40,60);
-
2011// shoot_parameters_trifoliate.internode_length_max = 0.03;
-
2014// shoot_parameters_trifoliate.base_roll = 90;
-
2015// shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
-
2016// shoot_parameters_trifoliate.gravitropic_curvature = 300;
-
2017//
-
2018// shoot_parameters_trifoliate.phyllochron = 1;
-
2020// shoot_parameters_trifoliate.elongation_rate = 0.1;
-
2021// shoot_parameters_trifoliate.girth_growth_rate = 0.00025;
-
2022// shoot_parameters_trifoliate.vegetative_bud_break_time = 3;
-
2023// shoot_parameters_trifoliate.vegetative_bud_break_probability = 0.25;
-
2025// shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.8,1.0);
-
2026// shoot_parameters_trifoliate.fruit_set_probability = 0.4;
-
2030//
-
2031// shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
-
2032//
+
1925
+
1926 ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
+
1927 shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
+
1928 shoot_parameters_unifoliate.max_nodes = 1;
+
1929 shoot_parameters_unifoliate.vegetative_bud_break_probability = 0;
+
1930 shoot_parameters_unifoliate.flower_bud_break_probability = 0;
+
1931 shoot_parameters_unifoliate.insertion_angle_tip = 0;
+
1932 shoot_parameters_unifoliate.insertion_angle_decay_rate = 0;
+
1933 shoot_parameters_unifoliate.vegetative_bud_break_time = 1;
+
1934 shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
+
1935
+
1936 defineShootType("unifoliate",shoot_parameters_unifoliate);
+
1937 defineShootType("trifoliate",shoot_parameters_trifoliate);
+
1938
+
1939// PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
+
1940//
+
1941// phytomer_parameters_trifoliate.internode.pitch = 20;
+
1942// phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
+
1943// phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
+
1944// phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
+
1945// phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.2,0.25,0.05);
+
1946// phytomer_parameters_trifoliate.internode.length_segments = 5;
+
1947//
+
1948// phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
+
1949// phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(30,70);
+
1950// phytomer_parameters_trifoliate.petiole.radius = 0.003;
+
1951// phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.12,0.16);
+
1952// phytomer_parameters_trifoliate.petiole.taper = 0.25;
+
1953// phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-100,200);
+
1954// phytomer_parameters_trifoliate.petiole.color = make_RGBcolor(0.28,0.35,0.07);
+
1955// phytomer_parameters_trifoliate.petiole.length_segments = 5;
+
1956// phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
+
1957//
+
1958// phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
+
1959// phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(0, 10);
+
1960// phytomer_parameters_trifoliate.leaf.yaw = 10;
+
1961// phytomer_parameters_trifoliate.leaf.roll = -15;
+
1962// phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.2;
+
1963// phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
+
1964// phytomer_parameters_trifoliate.leaf.prototype_function = SoybeanLeafPrototype_trifoliate;
+
1965// phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.11,0.13);
+
1966// phytomer_parameters_trifoliate.leaf.subdivisions = 10;
+
1967// phytomer_parameters_trifoliate.leaf.unique_prototypes = 5;
+
1968//
+
1969// phytomer_parameters_trifoliate.peduncle.length = 0.04;
+
1970// phytomer_parameters_trifoliate.peduncle.radius = 0.001;
+
1971// phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 40);
+
1972// phytomer_parameters_trifoliate.peduncle.roll = 90;
+
1973// phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(-500, 500);
+
1974// phytomer_parameters_trifoliate.peduncle.length_segments = 1;
+
1975// phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
+
1976//
+
1977// phytomer_parameters_trifoliate.inflorescence.flowers_per_rachis.uniformDistribution(1, 4);
+
1978// phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.2;
+
1979// phytomer_parameters_trifoliate.inflorescence.flower_arrangement_pattern = "opposite";
+
1980// phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
+
1981// phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
+
1982// phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.015;
+
1983// phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = BeanFlowerPrototype;
+
1984// phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.08,0.1);
+
1985// phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = BeanFruitPrototype;
+
1986// phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.8,1.0);
+
1987//
+
1988// PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
+
1989// phytomer_parameters_unifoliate.internode.pitch = 0;
+
1990// phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 0;
+
1991// phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
+
1992// phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
+
1993// phytomer_parameters_unifoliate.petiole.length = 0.001;
+
1994// phytomer_parameters_unifoliate.petiole.radius = 0.0004;
+
1995// phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(60,80);
+
1996// phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
+
1997// phytomer_parameters_unifoliate.leaf.prototype_scale = 0.02;
+
1998// phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
+
1999// phytomer_parameters_unifoliate.leaf.prototype_function = BeanLeafPrototype_unifoliate;
+
2000//
+
2001// // ---- Shoot Parameters ---- //
+
2002//
+
2003// ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
+
2004// shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
+
2005// shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = BeanPhytomerCreationFunction;
+
2006//
+
2007// shoot_parameters_trifoliate.max_nodes = 25;
+
2008// shoot_parameters_trifoliate.internode_radius_initial = 0.0005;
+
2009// shoot_parameters_trifoliate.internode_radius_max = 0.003;
+
2010// shoot_parameters_trifoliate.insertion_angle_tip.uniformDistribution(40,60);
+
2012// shoot_parameters_trifoliate.internode_length_max = 0.03;
+
2015// shoot_parameters_trifoliate.base_roll = 90;
+
2016// shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
+
2017// shoot_parameters_trifoliate.gravitropic_curvature = 300;
+
2018//
+
2019// shoot_parameters_trifoliate.phyllochron = 1;
+
2021// shoot_parameters_trifoliate.elongation_rate = 0.1;
+
2022// shoot_parameters_trifoliate.girth_growth_rate = 0.00025;
+
2023// shoot_parameters_trifoliate.vegetative_bud_break_time = 3;
+
2024// shoot_parameters_trifoliate.vegetative_bud_break_probability = 0.25;
+
2026// shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.8,1.0);
+
2027// shoot_parameters_trifoliate.fruit_set_probability = 0.4;
+
2031//
+
2032// shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
2033//
-
2034// ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
-
2035// shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
-
2036// shoot_parameters_unifoliate.max_nodes = 1;
-
2037// shoot_parameters_unifoliate.vegetative_bud_break_probability = 0;
-
2038// shoot_parameters_unifoliate.flower_bud_break_probability = 0;
-
2039// shoot_parameters_unifoliate.insertion_angle_tip = 0;
-
2040// shoot_parameters_unifoliate.insertion_angle_decay_rate = 0;
-
2041// shoot_parameters_unifoliate.vegetative_bud_break_time = 1;
-
2042// shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
-
2043//
-
2044// defineShootType("unifoliate",shoot_parameters_unifoliate);
-
2045// defineShootType("trifoliate",shoot_parameters_trifoliate);
-
2046
+
2034//
+
2035// ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
+
2036// shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
+
2037// shoot_parameters_unifoliate.max_nodes = 1;
+
2038// shoot_parameters_unifoliate.vegetative_bud_break_probability = 0;
+
2039// shoot_parameters_unifoliate.flower_bud_break_probability = 0;
+
2040// shoot_parameters_unifoliate.insertion_angle_tip = 0;
+
2041// shoot_parameters_unifoliate.insertion_angle_decay_rate = 0;
+
2042// shoot_parameters_unifoliate.vegetative_bud_break_time = 1;
+
2043// shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
+
2044//
+
2045// defineShootType("unifoliate",shoot_parameters_unifoliate);
+
2046// defineShootType("trifoliate",shoot_parameters_trifoliate);
2047
-
2048}
-
2049
-
2050uint PlantArchitecture::buildSoybeanPlant(const helios::vec3 &base_position) {
-
2051
-
2052 if (shoot_types.empty()) {
-
2053 //automatically initialize bean plant shoots
-
2054 initializeSoybeanShoots();
-
2055 }
-
2056
-
2057 uint plantID = addPlantInstance(base_position, 0);
-
2058
-
2059 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));
-
2060 uint uID_unifoliate = addBaseStemShoot(plantID, 1, base_rotation, 0.0005, 0.01, 0.01, 0.01, 0, "unifoliate");
-
2061
-
2062 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").internode_length_max.val(), 0.1, 0.1, 0, "trifoliate");
-
2063
-
2064 breakPlantDormancy(plantID);
-
2065
-
2066 setPlantPhenologicalThresholds(plantID, 0, 15, 3, 3, 5, 100, false);
-
2067
-
2068 return plantID;
-
2069
-
2070}
-
2071
-
2072void PlantArchitecture::initializeStrawberryShoots() {
-
2073
-
2074 // ---- Phytomer Parameters ---- //
-
2075
-
2076 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
-
2077
-
2078 phytomer_parameters.internode.pitch = 10;
-
2079 phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(80,100);
-
2080 phytomer_parameters.internode.color = make_RGBcolor(0.38, 0.48, 0.1);
-
2081 phytomer_parameters.internode.length_segments = 1;
-
2082
-
2083 phytomer_parameters.petiole.petioles_per_internode = 1;
-
2084 phytomer_parameters.petiole.pitch.uniformDistribution(10,45);
-
2085 phytomer_parameters.petiole.radius = 0.003;
-
2086 phytomer_parameters.petiole.length = 0.2;
-
2087 phytomer_parameters.petiole.taper = 0.5;
-
2088 phytomer_parameters.petiole.curvature.uniformDistribution(-200,100);
-
2089 phytomer_parameters.petiole.color = make_RGBcolor(0.24, 0.28, 0.08);
-
2090 phytomer_parameters.petiole.length_segments = 5;
-
2091
-
2092 phytomer_parameters.leaf.leaves_per_petiole = 3;
-
2093 phytomer_parameters.leaf.pitch.uniformDistribution(-30,-15);
-
2094 phytomer_parameters.leaf.yaw = 20;
-
2095 phytomer_parameters.leaf.roll = -30;
-
2096 phytomer_parameters.leaf.leaflet_offset = 0.01;
-
2097 phytomer_parameters.leaf.leaflet_scale = 1.0;
-
2098 phytomer_parameters.leaf.prototype_function = StrawberryLeafPrototype;
-
2099 phytomer_parameters.leaf.prototype_scale = 0.1;
-
2100 phytomer_parameters.leaf.subdivisions = 6;
-
2101 phytomer_parameters.leaf.unique_prototypes = 5;
-
2102
-
2103 phytomer_parameters.peduncle.length = 0.17;
-
2104 phytomer_parameters.peduncle.radius = 0.00075;
-
2105 phytomer_parameters.peduncle.pitch = 35;
-
2106 phytomer_parameters.peduncle.roll = 0;
-
2107 phytomer_parameters.peduncle.curvature = -200;
-
2108 phytomer_parameters.peduncle.length_segments = 5;
-
2109 phytomer_parameters.peduncle.radial_subdivisions = 6;
-
2110 phytomer_parameters.peduncle.color = phytomer_parameters.petiole.color;
-
2111
-
2112 phytomer_parameters.inflorescence.flowers_per_peduncle.uniformDistribution(1, 3);
-
2113 phytomer_parameters.inflorescence.flower_offset = 0.2;
-
2114 phytomer_parameters.inflorescence.pitch = 70;
-
2115 phytomer_parameters.inflorescence.roll = 90;
-
2116 phytomer_parameters.inflorescence.flower_prototype_scale = 0.04;
-
2117 phytomer_parameters.inflorescence.flower_prototype_function = StrawberryFlowerPrototype;
-
2118 phytomer_parameters.inflorescence.fruit_prototype_scale = 0.06;
-
2119 phytomer_parameters.inflorescence.fruit_prototype_function = StrawberryFruitPrototype;
-
2120 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction = 0.65;
-
2121
-
2122 // ---- Shoot Parameters ---- //
-
2123
-
2124 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
-
2125 shoot_parameters.phytomer_parameters = phytomer_parameters;
-
2126
-
2127 shoot_parameters.max_nodes = 15;
-
2128 shoot_parameters.internode_radius_initial = 0.001;
-
2129 shoot_parameters.internode_radius_max = 0.005;
-
2130 shoot_parameters.insertion_angle_tip = 40;
-
2131 shoot_parameters.insertion_angle_decay_rate = 0;
-
2132 shoot_parameters.internode_length_max = 0.01;
-
2133 shoot_parameters.internode_length_decay_rate = 0;
-
2134 shoot_parameters.internode_length_min = 0.0;
-
2135 shoot_parameters.base_roll = 90;
-
2136 shoot_parameters.base_yaw.uniformDistribution(-20,20);
-
2137 shoot_parameters.gravitropic_curvature.uniformDistribution(-10,0);
-
2138 shoot_parameters.tortuosity = 0;
-
2139
-
2140 shoot_parameters.phyllochron = 1.;
-
2141 shoot_parameters.leaf_flush_count = 1;
-
2142 shoot_parameters.elongation_rate = 0.1;
-
2143 shoot_parameters.girth_area_factor = 10.f;
-
2144 shoot_parameters.vegetative_bud_break_time = 3;
-
2145 shoot_parameters.vegetative_bud_break_probability = 0.25;
-
2146 shoot_parameters.flower_bud_break_probability = 1;
-
2147 shoot_parameters.fruit_set_probability = 0.5;
-
2148 shoot_parameters.flowers_require_dormancy = false;
-
2149 shoot_parameters.growth_requires_dormancy = false;
-
2150 shoot_parameters.determinate_shoot_growth = true;
-
2151
-
2152 shoot_parameters.defineChildShootTypes({"mainstem"},{1.0});
-
2153
-
2154 defineShootType("mainstem",shoot_parameters);
-
2155
-
2156}
-
2157
-
2158uint PlantArchitecture::buildStrawberryPlant(const helios::vec3 &base_position) {
-
2159
-
2160 if (shoot_types.empty()) {
-
2161 //automatically initialize strawberry plant shoots
-
2162 initializeStrawberryShoots();
-
2163 }
-
2164
-
2165 uint plantID = addPlantInstance(base_position, 0);
-
2166
-
2167 AxisRotation base_rotation = make_AxisRotation(0, context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
-
2168 uint uID_stem = addBaseStemShoot(plantID, 1, base_rotation, 0.001, 0.004, 0.01, 0.01, 0, "mainstem");
-
2169
-
2170 breakPlantDormancy(plantID);
-
2171
-
2172 setPlantPhenologicalThresholds(plantID, 0, -1, 10, 3, 1, 100, false);
-
2173
-
2174 return plantID;
-
2175
-
2176}
-
2177
-
2178void PlantArchitecture::initializeSugarbeetShoots() {
-
2179
-
2180 // ---- Phytomer Parameters ---- //
-
2181
-
2182 PhytomerParameters phytomer_parameters_sugarbeet(context_ptr->getRandomGenerator());
-
2183
-
2184 phytomer_parameters_sugarbeet.internode.pitch = 0;
-
2185 phytomer_parameters_sugarbeet.internode.phyllotactic_angle = 137.5;
-
2186 phytomer_parameters_sugarbeet.internode.color = make_RGBcolor(0.44,0.58,0.19);
-
2187 phytomer_parameters_sugarbeet.internode.length_segments = 2;
-
2188
-
2189 phytomer_parameters_sugarbeet.petiole.petioles_per_internode = 1;
-
2190 phytomer_parameters_sugarbeet.petiole.pitch.uniformDistribution(0,40);
-
2191 phytomer_parameters_sugarbeet.petiole.radius = 0.005;
-
2192 phytomer_parameters_sugarbeet.petiole.length.uniformDistribution(0.15,0.2);
-
2193 phytomer_parameters_sugarbeet.petiole.taper = 0.6;
-
2194 phytomer_parameters_sugarbeet.petiole.curvature.uniformDistribution(-300,100);
-
2195 phytomer_parameters_sugarbeet.petiole.color = phytomer_parameters_sugarbeet.internode.color;
-
2196 phytomer_parameters_sugarbeet.petiole.length_segments = 8;
-
2197
-
2198 phytomer_parameters_sugarbeet.leaf.leaves_per_petiole = 1;
-
2199 phytomer_parameters_sugarbeet.leaf.pitch.uniformDistribution(-10,0);
-
2200 phytomer_parameters_sugarbeet.leaf.yaw.uniformDistribution(-5,5);
-
2201 phytomer_parameters_sugarbeet.leaf.roll.uniformDistribution(-15,15);
-
2202 phytomer_parameters_sugarbeet.leaf.prototype_function = SugarbeetLeafPrototype;
-
2203 phytomer_parameters_sugarbeet.leaf.prototype_scale.uniformDistribution(0.15,0.25);
-
2204 phytomer_parameters_sugarbeet.leaf.subdivisions = 40;
-
2205
-
2206 // ---- Shoot Parameters ---- //
-
2207
-
2208 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
-
2209 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_sugarbeet;
-
2210 shoot_parameters_mainstem.vegetative_bud_break_probability = 0;
-
2211 shoot_parameters_mainstem.internode_radius_initial = 0.005;
-
2212 shoot_parameters_mainstem.phyllochron = 1;
-
2213 shoot_parameters_mainstem.elongation_rate = 0.25;
-
2214 shoot_parameters_mainstem.girth_area_factor = 20.f;
-
2215 shoot_parameters_mainstem.gravitropic_curvature = 10;
-
2216 shoot_parameters_mainstem.internode_length_max = 0.001;
-
2217 shoot_parameters_mainstem.internode_length_decay_rate = 0;
-
2218 shoot_parameters_mainstem.flowers_require_dormancy = false;
-
2219 shoot_parameters_mainstem.growth_requires_dormancy = false;
-
2220 shoot_parameters_mainstem.flower_bud_break_probability = 0.0;
-
2221 shoot_parameters_mainstem.max_nodes = 30;
-
2222
-
2223 defineShootType("mainstem",shoot_parameters_mainstem);
-
2224
+
2048
+
2049}
+
2050
+
2051uint PlantArchitecture::buildSoybeanPlant(const helios::vec3 &base_position) {
+
2052
+
2053 if (shoot_types.empty()) {
+
2054 //automatically initialize bean plant shoots
+
2055 initializeSoybeanShoots();
+
2056 }
+
2057
+
2058 uint plantID = addPlantInstance(base_position, 0);
+
2059
+
2060 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));
+
2061 uint uID_unifoliate = addBaseStemShoot(plantID, 1, base_rotation, 0.0005, 0.01, 0.01, 0.01, 0, "unifoliate");
+
2062
+
2063 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").internode_length_max.val(), 0.1, 0.1, 0, "trifoliate");
+
2064
+
2065 breakPlantDormancy(plantID);
+
2066
+
2067 setPlantPhenologicalThresholds(plantID, 0, 15, 3, 3, 5, 100, false);
+
2068
+
2069 return plantID;
+
2070
+
2071}
+
2072
+
2073void PlantArchitecture::initializeStrawberryShoots() {
+
2074
+
2075 // ---- Phytomer Parameters ---- //
+
2076
+
2077 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
+
2078
+
2079 phytomer_parameters.internode.pitch = 10;
+
2080 phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(80,100);
+
2081 phytomer_parameters.internode.color = make_RGBcolor(0.38, 0.48, 0.1);
+
2082 phytomer_parameters.internode.length_segments = 1;
+
2083
+
2084 phytomer_parameters.petiole.petioles_per_internode = 1;
+
2085 phytomer_parameters.petiole.pitch.uniformDistribution(10,45);
+
2086 phytomer_parameters.petiole.radius = 0.003;
+
2087 phytomer_parameters.petiole.length = 0.2;
+
2088 phytomer_parameters.petiole.taper = 0.5;
+
2089 phytomer_parameters.petiole.curvature.uniformDistribution(-200,100);
+
2090 phytomer_parameters.petiole.color = make_RGBcolor(0.24, 0.28, 0.08);
+
2091 phytomer_parameters.petiole.length_segments = 5;
+
2092
+
2093 phytomer_parameters.leaf.leaves_per_petiole = 3;
+
2094 phytomer_parameters.leaf.pitch.uniformDistribution(-30,-15);
+
2095 phytomer_parameters.leaf.yaw = 20;
+
2096 phytomer_parameters.leaf.roll = -30;
+
2097 phytomer_parameters.leaf.leaflet_offset = 0.01;
+
2098 phytomer_parameters.leaf.leaflet_scale = 1.0;
+
2099 phytomer_parameters.leaf.prototype_function = StrawberryLeafPrototype;
+
2100 phytomer_parameters.leaf.prototype_scale = 0.1;
+
2101 phytomer_parameters.leaf.subdivisions = 6;
+
2102 phytomer_parameters.leaf.unique_prototypes = 5;
+
2103
+
2104 phytomer_parameters.peduncle.length = 0.17;
+
2105 phytomer_parameters.peduncle.radius = 0.00075;
+
2106 phytomer_parameters.peduncle.pitch = 35;
+
2107 phytomer_parameters.peduncle.roll = 0;
+
2108 phytomer_parameters.peduncle.curvature = -200;
+
2109 phytomer_parameters.peduncle.length_segments = 5;
+
2110 phytomer_parameters.peduncle.radial_subdivisions = 6;
+
2111 phytomer_parameters.peduncle.color = phytomer_parameters.petiole.color;
+
2112
+
2113 phytomer_parameters.inflorescence.flowers_per_peduncle.uniformDistribution(1, 3);
+
2114 phytomer_parameters.inflorescence.flower_offset = 0.2;
+
2115 phytomer_parameters.inflorescence.pitch = 70;
+
2116 phytomer_parameters.inflorescence.roll = 90;
+
2117 phytomer_parameters.inflorescence.flower_prototype_scale = 0.04;
+
2118 phytomer_parameters.inflorescence.flower_prototype_function = StrawberryFlowerPrototype;
+
2119 phytomer_parameters.inflorescence.fruit_prototype_scale = 0.06;
+
2120 phytomer_parameters.inflorescence.fruit_prototype_function = StrawberryFruitPrototype;
+
2121 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction = 0.65;
+
2122
+
2123 // ---- Shoot Parameters ---- //
+
2124
+
2125 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
+
2126 shoot_parameters.phytomer_parameters = phytomer_parameters;
+
2127
+
2128 shoot_parameters.max_nodes = 15;
+
2129 shoot_parameters.internode_radius_initial = 0.001;
+
2130 shoot_parameters.internode_radius_max = 0.005;
+
2131 shoot_parameters.insertion_angle_tip = 40;
+
2132 shoot_parameters.insertion_angle_decay_rate = 0;
+
2133 shoot_parameters.internode_length_max = 0.01;
+
2134 shoot_parameters.internode_length_decay_rate = 0;
+
2135 shoot_parameters.internode_length_min = 0.0;
+
2136 shoot_parameters.base_roll = 90;
+
2137 shoot_parameters.base_yaw.uniformDistribution(-20,20);
+
2138 shoot_parameters.gravitropic_curvature.uniformDistribution(-10,0);
+
2139 shoot_parameters.tortuosity = 0;
+
2140
+
2141 shoot_parameters.phyllochron = 1.;
+
2142 shoot_parameters.leaf_flush_count = 1;
+
2143 shoot_parameters.elongation_rate = 0.1;
+
2144 shoot_parameters.girth_area_factor = 10.f;
+
2145 shoot_parameters.vegetative_bud_break_time = 3;
+
2146 shoot_parameters.vegetative_bud_break_probability = 0.25;
+
2147 shoot_parameters.flower_bud_break_probability = 1;
+
2148 shoot_parameters.fruit_set_probability = 0.5;
+
2149 shoot_parameters.flowers_require_dormancy = false;
+
2150 shoot_parameters.growth_requires_dormancy = false;
+
2151 shoot_parameters.determinate_shoot_growth = true;
+
2152
+
2153 shoot_parameters.defineChildShootTypes({"mainstem"},{1.0});
+
2154
+
2155 defineShootType("mainstem",shoot_parameters);
+
2156
+
2157}
+
2158
+
2159uint PlantArchitecture::buildStrawberryPlant(const helios::vec3 &base_position) {
+
2160
+
2161 if (shoot_types.empty()) {
+
2162 //automatically initialize strawberry plant shoots
+
2163 initializeStrawberryShoots();
+
2164 }
+
2165
+
2166 uint plantID = addPlantInstance(base_position, 0);
+
2167
+
2168 AxisRotation base_rotation = make_AxisRotation(0, context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
+
2169 uint uID_stem = addBaseStemShoot(plantID, 1, base_rotation, 0.001, 0.004, 0.01, 0.01, 0, "mainstem");
+
2170
+
2171 breakPlantDormancy(plantID);
+
2172
+
2173 setPlantPhenologicalThresholds(plantID, 0, -1, 10, 3, 1, 100, false);
+
2174
+
2175 return plantID;
+
2176
+
2177}
+
2178
+
2179void PlantArchitecture::initializeSugarbeetShoots() {
+
2180
+
2181 // ---- Phytomer Parameters ---- //
+
2182
+
2183 PhytomerParameters phytomer_parameters_sugarbeet(context_ptr->getRandomGenerator());
+
2184
+
2185 phytomer_parameters_sugarbeet.internode.pitch = 0;
+
2186 phytomer_parameters_sugarbeet.internode.phyllotactic_angle = 137.5;
+
2187 phytomer_parameters_sugarbeet.internode.color = make_RGBcolor(0.44,0.58,0.19);
+
2188 phytomer_parameters_sugarbeet.internode.length_segments = 2;
+
2189
+
2190 phytomer_parameters_sugarbeet.petiole.petioles_per_internode = 1;
+
2191 phytomer_parameters_sugarbeet.petiole.pitch.uniformDistribution(0,40);
+
2192 phytomer_parameters_sugarbeet.petiole.radius = 0.005;
+
2193 phytomer_parameters_sugarbeet.petiole.length.uniformDistribution(0.15,0.2);
+
2194 phytomer_parameters_sugarbeet.petiole.taper = 0.6;
+
2195 phytomer_parameters_sugarbeet.petiole.curvature.uniformDistribution(-300,100);
+
2196 phytomer_parameters_sugarbeet.petiole.color = phytomer_parameters_sugarbeet.internode.color;
+
2197 phytomer_parameters_sugarbeet.petiole.length_segments = 8;
+
2198
+
2199 phytomer_parameters_sugarbeet.leaf.leaves_per_petiole = 1;
+
2200 phytomer_parameters_sugarbeet.leaf.pitch.uniformDistribution(-10,0);
+
2201 phytomer_parameters_sugarbeet.leaf.yaw.uniformDistribution(-5,5);
+
2202 phytomer_parameters_sugarbeet.leaf.roll.uniformDistribution(-15,15);
+
2203 phytomer_parameters_sugarbeet.leaf.prototype_function = SugarbeetLeafPrototype;
+
2204 phytomer_parameters_sugarbeet.leaf.prototype_scale.uniformDistribution(0.15,0.25);
+
2205 phytomer_parameters_sugarbeet.leaf.subdivisions = 40;
+
2206
+
2207 // ---- Shoot Parameters ---- //
+
2208
+
2209 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
+
2210 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_sugarbeet;
+
2211 shoot_parameters_mainstem.vegetative_bud_break_probability = 0;
+
2212 shoot_parameters_mainstem.internode_radius_initial = 0.005;
+
2213 shoot_parameters_mainstem.phyllochron = 1;
+
2214 shoot_parameters_mainstem.elongation_rate = 0.25;
+
2215 shoot_parameters_mainstem.girth_area_factor = 20.f;
+
2216 shoot_parameters_mainstem.gravitropic_curvature = 10;
+
2217 shoot_parameters_mainstem.internode_length_max = 0.001;
+
2218 shoot_parameters_mainstem.internode_length_decay_rate = 0;
+
2219 shoot_parameters_mainstem.flowers_require_dormancy = false;
+
2220 shoot_parameters_mainstem.growth_requires_dormancy = false;
+
2221 shoot_parameters_mainstem.flower_bud_break_probability = 0.0;
+
2222 shoot_parameters_mainstem.max_nodes = 30;
+
2223
+
2224 defineShootType("mainstem",shoot_parameters_mainstem);
2225
-
2226}
-
2227
-
2228uint PlantArchitecture::buildSugarbeetPlant(const helios::vec3 &base_position) {
-
2229
-
2230 if (shoot_types.empty()) {
-
2231 //automatically initialize sugarbeet plant shoots
-
2232 initializeSugarbeetShoots();
-
2233 }
-
2234
-
2235 uint plantID = addPlantInstance(base_position, 0);
-
2236
-
2237 uint uID_stem = addBaseStemShoot(plantID, 3, 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.005, 0.001, 1, 1, 0, "mainstem");
-
2238
-
2239 breakPlantDormancy(plantID);
-
2240
-
2241 setPlantPhenologicalThresholds(plantID, 0, 1000, 10, 60, 5, 100, false);
-
2242
-
2243 return plantID;
-
2244
-
2245}
-
2246
-
2247void PlantArchitecture::initializeTomatoShoots() {
-
2248
-
2249 // ---- Phytomer Parameters ---- //
-
2250
-
2251 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
-
2252
-
2253 phytomer_parameters.internode.pitch = 10;
-
2254 phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(145, 215);
-
2255 phytomer_parameters.internode.color = make_RGBcolor(0.213, 0.270, 0.056);
-
2256 phytomer_parameters.internode.length_segments = 1;
-
2257
-
2258 phytomer_parameters.petiole.petioles_per_internode = 1;
-
2259 phytomer_parameters.petiole.pitch.uniformDistribution(45,60);
-
2260 phytomer_parameters.petiole.radius = 0.002;
-
2261 phytomer_parameters.petiole.length = 0.2;
-
2262 phytomer_parameters.petiole.taper = 0.15;
-
2263 phytomer_parameters.petiole.curvature.uniformDistribution(-150,-50);
-
2264 phytomer_parameters.petiole.color = phytomer_parameters.internode.color;
-
2265 phytomer_parameters.petiole.length_segments = 5;
-
2266
-
2267 phytomer_parameters.leaf.leaves_per_petiole = 7;
-
2268 phytomer_parameters.leaf.pitch.uniformDistribution(-30, 5);
-
2269 phytomer_parameters.leaf.yaw = 10;
-
2270 phytomer_parameters.leaf.roll = 0;
-
2271 phytomer_parameters.leaf.leaflet_offset = 0.15;
-
2272 phytomer_parameters.leaf.leaflet_scale = 0.7;
-
2273 phytomer_parameters.leaf.prototype_function = TomatoLeafPrototype;
-
2274 phytomer_parameters.leaf.prototype_scale.uniformDistribution(0.1,0.14);
-
2275 phytomer_parameters.leaf.subdivisions = 6;
-
2276 phytomer_parameters.leaf.unique_prototypes = 5;
-
2277
-
2278 phytomer_parameters.peduncle.length = 0.16;
-
2279 phytomer_parameters.peduncle.radius = 0.0015;
-
2280 phytomer_parameters.peduncle.pitch = 20;
-
2281 phytomer_parameters.peduncle.roll = 0;
-
2282 phytomer_parameters.peduncle.curvature = -700;
-
2283 phytomer_parameters.peduncle.color = phytomer_parameters.internode.color;
-
2284 phytomer_parameters.peduncle.length_segments = 5;
-
2285 phytomer_parameters.peduncle.radial_subdivisions = 8;
-
2286
-
2287 phytomer_parameters.inflorescence.flowers_per_peduncle = 8;
-
2288 phytomer_parameters.inflorescence.flower_offset = 0.15;
-
2289 phytomer_parameters.inflorescence.pitch = 90;
-
2290 phytomer_parameters.inflorescence.roll.uniformDistribution(-30,30);
-
2291 phytomer_parameters.inflorescence.flower_prototype_scale = 0.03;
-
2292 phytomer_parameters.inflorescence.flower_prototype_function = TomatoFlowerPrototype;
-
2293 phytomer_parameters.inflorescence.fruit_prototype_scale = 0.04;
-
2294 phytomer_parameters.inflorescence.fruit_prototype_function = TomatoFruitPrototype;
-
2295 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction = 0.5;
-
2296
-
2297 // ---- Shoot Parameters ---- //
-
2298
-
2299 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
-
2300 shoot_parameters.phytomer_parameters = phytomer_parameters;
-
2301 shoot_parameters.phytomer_parameters.phytomer_creation_function = TomatoPhytomerCreationFunction;
-
2302
-
2303 shoot_parameters.max_nodes = 20;
-
2304 shoot_parameters.internode_radius_initial = 0.001;
-
2305 shoot_parameters.internode_radius_max = 0.009;
-
2306 shoot_parameters.insertion_angle_tip = 30;
-
2307 shoot_parameters.insertion_angle_decay_rate = 0;
-
2308 shoot_parameters.internode_length_max = 0.04;
-
2309 shoot_parameters.internode_length_min = 0.0;
-
2310 shoot_parameters.internode_length_decay_rate = 0;
-
2311 shoot_parameters.base_roll = 90;
-
2312 shoot_parameters.base_yaw.uniformDistribution(-20,20);
-
2313 shoot_parameters.gravitropic_curvature = -20;
-
2314 shoot_parameters.tortuosity = 0;
-
2315
-
2316 shoot_parameters.phyllochron = 1;
-
2317 shoot_parameters.leaf_flush_count = 1;
-
2318 shoot_parameters.elongation_rate = 0.1;
-
2319 shoot_parameters.girth_area_factor = 3.f;
-
2320 shoot_parameters.vegetative_bud_break_time = 3;
-
2321 shoot_parameters.vegetative_bud_break_probability = 0.6;
-
2322 shoot_parameters.flower_bud_break_probability = 0.5;
-
2323 shoot_parameters.fruit_set_probability = 0.5;
-
2324 shoot_parameters.flowers_require_dormancy = false;
-
2325 shoot_parameters.growth_requires_dormancy = false;
-
2326 shoot_parameters.determinate_shoot_growth = true;
-
2327
-
2328 shoot_parameters.defineChildShootTypes({"mainstem"},{1.0});
-
2329
-
2330 defineShootType("mainstem",shoot_parameters);
-
2331
-
2332}
-
2333
-
2334uint PlantArchitecture::buildTomatoPlant(const helios::vec3 &base_position) {
-
2335
-
2336 if (shoot_types.empty()) {
-
2337 //automatically initialize tomato plant shoots
-
2338 initializeTomatoShoots();
-
2339 }
-
2340
-
2341 uint plantID = addPlantInstance(base_position, 0);
-
2342
-
2343 AxisRotation base_rotation = make_AxisRotation(0, context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
-
2344 uint uID_stem = addBaseStemShoot(plantID, 1, base_rotation, 0.002, 0.04, 0.01, 0.01, 0, "mainstem");
-
2345
-
2346 breakPlantDormancy(plantID);
-
2347
-
2348 setPlantPhenologicalThresholds(plantID, 0, -1, 10, 3, 2, 100, false);
-
2349
-
2350 return plantID;
-
2351
-
2352}
-
2353
-
2354void PlantArchitecture::initializeWheatShoots() {
-
2355
-
2356 // ---- Phytomer Parameters ---- //
-
2357
-
2358 PhytomerParameters phytomer_parameters_wheat(context_ptr->getRandomGenerator());
-
2359
-
2360 phytomer_parameters_wheat.internode.pitch = 0;
-
2361 phytomer_parameters_wheat.internode.phyllotactic_angle.uniformDistribution(67,77);
-
2362 phytomer_parameters_wheat.internode.color = make_RGBcolor(0.27,0.31,0.16);
-
2363 phytomer_parameters_wheat.internode.length_segments = 1;
-
2364 phytomer_parameters_wheat.internode.radial_subdivisions = 6;
-
2365 phytomer_parameters_wheat.internode.max_floral_buds_per_petiole = 0;
-
2366 phytomer_parameters_wheat.internode.max_vegetative_buds_per_petiole = 0;
-
2367
-
2368 phytomer_parameters_wheat.petiole.petioles_per_internode = 1;
-
2369 phytomer_parameters_wheat.petiole.pitch.uniformDistribution(-40,-20);
-
2370 phytomer_parameters_wheat.petiole.radius = 0.0;
-
2371 phytomer_parameters_wheat.petiole.length = 0.01;
-
2372 phytomer_parameters_wheat.petiole.taper = 0;
-
2373 phytomer_parameters_wheat.petiole.curvature = 0;
-
2374 phytomer_parameters_wheat.petiole.length_segments = 1;
-
2375
-
2376 phytomer_parameters_wheat.leaf.leaves_per_petiole = 1;
-
2377 phytomer_parameters_wheat.leaf.pitch = 0;
-
2378 phytomer_parameters_wheat.leaf.yaw = 0;
-
2379 phytomer_parameters_wheat.leaf.roll = 0;
-
2380 phytomer_parameters_wheat.leaf.prototype_function = WheatLeafPrototype;
-
2381 phytomer_parameters_wheat.leaf.prototype_scale = 0.1;
-
2382 phytomer_parameters_wheat.leaf.subdivisions = 20;
-
2383 phytomer_parameters_wheat.leaf.unique_prototypes = 10;
-
2384
-
2385 phytomer_parameters_wheat.peduncle.length = 0.07;
-
2386 phytomer_parameters_wheat.peduncle.radius = 0.002;
-
2387 phytomer_parameters_wheat.peduncle.color = phytomer_parameters_wheat.internode.color;
-
2388 phytomer_parameters_wheat.peduncle.curvature = -200;
-
2389 phytomer_parameters_wheat.peduncle.radial_subdivisions = 6;
-
2390
-
2391 phytomer_parameters_wheat.inflorescence.flowers_per_peduncle = 1;
-
2392 phytomer_parameters_wheat.inflorescence.pitch = 0;
-
2393 phytomer_parameters_wheat.inflorescence.roll = 0;
-
2394 phytomer_parameters_wheat.inflorescence.fruit_prototype_scale = 0.1;
-
2395 phytomer_parameters_wheat.inflorescence.fruit_prototype_function = WheatSpikePrototype;
-
2396
-
2397 phytomer_parameters_wheat.phytomer_creation_function = WheatPhytomerCreationFunction;
-
2398
-
2399 // ---- Shoot Parameters ---- //
-
2400
-
2401 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
-
2402 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_wheat;
-
2403 shoot_parameters_mainstem.vegetative_bud_break_probability = 0;
-
2404 shoot_parameters_mainstem.flower_bud_break_probability = 1;
-
2405 shoot_parameters_mainstem.internode_radius_initial = 0.001;
-
2406 shoot_parameters_mainstem.phyllochron = 1;
-
2407 shoot_parameters_mainstem.elongation_rate = 0.15;
-
2408 shoot_parameters_mainstem.girth_area_factor = 7.f;
-
2409 shoot_parameters_mainstem.internode_radius_max = 0.0025;
-
2410 shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-2000,-800);
-
2411 shoot_parameters_mainstem.internode_length_max = 0.025;
-
2412 shoot_parameters_mainstem.internode_length_decay_rate = 0;
-
2413 shoot_parameters_mainstem.flowers_require_dormancy = false;
-
2414 shoot_parameters_mainstem.growth_requires_dormancy = false;
-
2415 shoot_parameters_mainstem.determinate_shoot_growth = false;
-
2416 shoot_parameters_mainstem.flower_bud_break_probability = 1.0;
-
2417 shoot_parameters_mainstem.fruit_set_probability = 1.0;
-
2418 shoot_parameters_mainstem.defineChildShootTypes({"mainstem"},{1.0});
-
2419 shoot_parameters_mainstem.max_nodes = 15;
-
2420 shoot_parameters_mainstem.max_terminal_floral_buds = 1;
-
2421
-
2422 defineShootType("mainstem",shoot_parameters_mainstem);
-
2423
-
2424}
-
2425
-
2426uint PlantArchitecture::buildWheatPlant(const helios::vec3 &base_position) {
-
2427
-
2428 if (shoot_types.empty()) {
-
2429 //automatically initialize wheat plant shoots
-
2430 initializeWheatShoots();
-
2431 }
-
2432
-
2433 uint plantID = addPlantInstance(base_position - make_vec3(0,0,0.025), 0);
-
2434
-
2435 uint uID_stem = addBaseStemShoot(plantID, 1, make_AxisRotation(context_ptr->randu(0.f, 0.1f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI)), 0.001, 0.025, 0.01, 0.01, 0, "mainstem");
-
2436
-
2437 breakPlantDormancy(plantID);
-
2438
-
2439 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 2, 5, 100, false);
-
2440
-
2441 return plantID;
-
2442
-
2443}
+
2226
+
2227}
+
2228
+
2229uint PlantArchitecture::buildSugarbeetPlant(const helios::vec3 &base_position) {
+
2230
+
2231 if (shoot_types.empty()) {
+
2232 //automatically initialize sugarbeet plant shoots
+
2233 initializeSugarbeetShoots();
+
2234 }
+
2235
+
2236 uint plantID = addPlantInstance(base_position, 0);
+
2237
+
2238 uint uID_stem = addBaseStemShoot(plantID, 3, 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.005, 0.001, 1, 1, 0, "mainstem");
+
2239
+
2240 breakPlantDormancy(plantID);
+
2241
+
2242 setPlantPhenologicalThresholds(plantID, 0, 1000, 10, 60, 5, 100, false);
+
2243
+
2244 return plantID;
+
2245
+
2246}
+
2247
+
2248void PlantArchitecture::initializeTomatoShoots() {
+
2249
+
2250 // ---- Phytomer Parameters ---- //
+
2251
+
2252 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
+
2253
+
2254 phytomer_parameters.internode.pitch = 10;
+
2255 phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(145, 215);
+
2256 phytomer_parameters.internode.color = make_RGBcolor(0.213, 0.270, 0.056);
+
2257 phytomer_parameters.internode.length_segments = 1;
+
2258
+
2259 phytomer_parameters.petiole.petioles_per_internode = 1;
+
2260 phytomer_parameters.petiole.pitch.uniformDistribution(45,60);
+
2261 phytomer_parameters.petiole.radius = 0.002;
+
2262 phytomer_parameters.petiole.length = 0.2;
+
2263 phytomer_parameters.petiole.taper = 0.15;
+
2264 phytomer_parameters.petiole.curvature.uniformDistribution(-150,-50);
+
2265 phytomer_parameters.petiole.color = phytomer_parameters.internode.color;
+
2266 phytomer_parameters.petiole.length_segments = 5;
+
2267
+
2268 phytomer_parameters.leaf.leaves_per_petiole = 7;
+
2269 phytomer_parameters.leaf.pitch.uniformDistribution(-30, 5);
+
2270 phytomer_parameters.leaf.yaw = 10;
+
2271 phytomer_parameters.leaf.roll = 0;
+
2272 phytomer_parameters.leaf.leaflet_offset = 0.15;
+
2273 phytomer_parameters.leaf.leaflet_scale = 0.7;
+
2274 phytomer_parameters.leaf.prototype_function = TomatoLeafPrototype;
+
2275 phytomer_parameters.leaf.prototype_scale.uniformDistribution(0.1,0.14);
+
2276 phytomer_parameters.leaf.subdivisions = 6;
+
2277 phytomer_parameters.leaf.unique_prototypes = 5;
+
2278
+
2279 phytomer_parameters.peduncle.length = 0.16;
+
2280 phytomer_parameters.peduncle.radius = 0.0015;
+
2281 phytomer_parameters.peduncle.pitch = 20;
+
2282 phytomer_parameters.peduncle.roll = 0;
+
2283 phytomer_parameters.peduncle.curvature = -700;
+
2284 phytomer_parameters.peduncle.color = phytomer_parameters.internode.color;
+
2285 phytomer_parameters.peduncle.length_segments = 5;
+
2286 phytomer_parameters.peduncle.radial_subdivisions = 8;
+
2287
+
2288 phytomer_parameters.inflorescence.flowers_per_peduncle = 8;
+
2289 phytomer_parameters.inflorescence.flower_offset = 0.15;
+
2290 phytomer_parameters.inflorescence.pitch = 90;
+
2291 phytomer_parameters.inflorescence.roll.uniformDistribution(-30,30);
+
2292 phytomer_parameters.inflorescence.flower_prototype_scale = 0.03;
+
2293 phytomer_parameters.inflorescence.flower_prototype_function = TomatoFlowerPrototype;
+
2294 phytomer_parameters.inflorescence.fruit_prototype_scale = 0.04;
+
2295 phytomer_parameters.inflorescence.fruit_prototype_function = TomatoFruitPrototype;
+
2296 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction = 0.5;
+
2297
+
2298 // ---- Shoot Parameters ---- //
+
2299
+
2300 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
+
2301 shoot_parameters.phytomer_parameters = phytomer_parameters;
+
2302 shoot_parameters.phytomer_parameters.phytomer_creation_function = TomatoPhytomerCreationFunction;
+
2303
+
2304 shoot_parameters.max_nodes = 20;
+
2305 shoot_parameters.internode_radius_initial = 0.001;
+
2306 shoot_parameters.internode_radius_max = 0.009;
+
2307 shoot_parameters.insertion_angle_tip = 30;
+
2308 shoot_parameters.insertion_angle_decay_rate = 0;
+
2309 shoot_parameters.internode_length_max = 0.04;
+
2310 shoot_parameters.internode_length_min = 0.0;
+
2311 shoot_parameters.internode_length_decay_rate = 0;
+
2312 shoot_parameters.base_roll = 90;
+
2313 shoot_parameters.base_yaw.uniformDistribution(-20,20);
+
2314 shoot_parameters.gravitropic_curvature = -20;
+
2315 shoot_parameters.tortuosity = 0;
+
2316
+
2317 shoot_parameters.phyllochron = 1;
+
2318 shoot_parameters.leaf_flush_count = 1;
+
2319 shoot_parameters.elongation_rate = 0.1;
+
2320 shoot_parameters.girth_area_factor = 3.f;
+
2321 shoot_parameters.vegetative_bud_break_time = 3;
+
2322 shoot_parameters.vegetative_bud_break_probability = 0.6;
+
2323 shoot_parameters.flower_bud_break_probability = 0.5;
+
2324 shoot_parameters.fruit_set_probability = 0.5;
+
2325 shoot_parameters.flowers_require_dormancy = false;
+
2326 shoot_parameters.growth_requires_dormancy = false;
+
2327 shoot_parameters.determinate_shoot_growth = true;
+
2328
+
2329 shoot_parameters.defineChildShootTypes({"mainstem"},{1.0});
+
2330
+
2331 defineShootType("mainstem",shoot_parameters);
+
2332
+
2333}
+
2334
+
2335uint PlantArchitecture::buildTomatoPlant(const helios::vec3 &base_position) {
+
2336
+
2337 if (shoot_types.empty()) {
+
2338 //automatically initialize tomato plant shoots
+
2339 initializeTomatoShoots();
+
2340 }
+
2341
+
2342 uint plantID = addPlantInstance(base_position, 0);
+
2343
+
2344 AxisRotation base_rotation = make_AxisRotation(0, context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
+
2345 uint uID_stem = addBaseStemShoot(plantID, 1, base_rotation, 0.002, 0.04, 0.01, 0.01, 0, "mainstem");
+
2346
+
2347 breakPlantDormancy(plantID);
+
2348
+
2349 setPlantPhenologicalThresholds(plantID, 0, -1, 10, 3, 2, 100, false);
+
2350
+
2351 return plantID;
+
2352
+
2353}
+
2354
+
2355void PlantArchitecture::initializeWheatShoots() {
+
2356
+
2357 // ---- Phytomer Parameters ---- //
+
2358
+
2359 PhytomerParameters phytomer_parameters_wheat(context_ptr->getRandomGenerator());
+
2360
+
2361 phytomer_parameters_wheat.internode.pitch = 0;
+
2362 phytomer_parameters_wheat.internode.phyllotactic_angle.uniformDistribution(67,77);
+
2363 phytomer_parameters_wheat.internode.color = make_RGBcolor(0.27,0.31,0.16);
+
2364 phytomer_parameters_wheat.internode.length_segments = 1;
+
2365 phytomer_parameters_wheat.internode.radial_subdivisions = 6;
+
2366 phytomer_parameters_wheat.internode.max_floral_buds_per_petiole = 0;
+
2367 phytomer_parameters_wheat.internode.max_vegetative_buds_per_petiole = 0;
+
2368
+
2369 phytomer_parameters_wheat.petiole.petioles_per_internode = 1;
+
2370 phytomer_parameters_wheat.petiole.pitch.uniformDistribution(-40,-20);
+
2371 phytomer_parameters_wheat.petiole.radius = 0.0;
+
2372 phytomer_parameters_wheat.petiole.length = 0.01;
+
2373 phytomer_parameters_wheat.petiole.taper = 0;
+
2374 phytomer_parameters_wheat.petiole.curvature = 0;
+
2375 phytomer_parameters_wheat.petiole.length_segments = 1;
+
2376
+
2377 phytomer_parameters_wheat.leaf.leaves_per_petiole = 1;
+
2378 phytomer_parameters_wheat.leaf.pitch = 0;
+
2379 phytomer_parameters_wheat.leaf.yaw = 0;
+
2380 phytomer_parameters_wheat.leaf.roll = 0;
+
2381 phytomer_parameters_wheat.leaf.prototype_function = WheatLeafPrototype;
+
2382 phytomer_parameters_wheat.leaf.prototype_scale = 0.1;
+
2383 phytomer_parameters_wheat.leaf.subdivisions = 20;
+
2384 phytomer_parameters_wheat.leaf.unique_prototypes = 10;
+
2385
+
2386 phytomer_parameters_wheat.peduncle.length = 0.07;
+
2387 phytomer_parameters_wheat.peduncle.radius = 0.002;
+
2388 phytomer_parameters_wheat.peduncle.color = phytomer_parameters_wheat.internode.color;
+
2389 phytomer_parameters_wheat.peduncle.curvature = -200;
+
2390 phytomer_parameters_wheat.peduncle.radial_subdivisions = 6;
+
2391
+
2392 phytomer_parameters_wheat.inflorescence.flowers_per_peduncle = 1;
+
2393 phytomer_parameters_wheat.inflorescence.pitch = 0;
+
2394 phytomer_parameters_wheat.inflorescence.roll = 0;
+
2395 phytomer_parameters_wheat.inflorescence.fruit_prototype_scale = 0.1;
+
2396 phytomer_parameters_wheat.inflorescence.fruit_prototype_function = WheatSpikePrototype;
+
2397
+
2398 phytomer_parameters_wheat.phytomer_creation_function = WheatPhytomerCreationFunction;
+
2399
+
2400 // ---- Shoot Parameters ---- //
+
2401
+
2402 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
+
2403 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_wheat;
+
2404 shoot_parameters_mainstem.vegetative_bud_break_probability = 0;
+
2405 shoot_parameters_mainstem.flower_bud_break_probability = 1;
+
2406 shoot_parameters_mainstem.internode_radius_initial = 0.001;
+
2407 shoot_parameters_mainstem.phyllochron = 1;
+
2408 shoot_parameters_mainstem.elongation_rate = 0.15;
+
2409 shoot_parameters_mainstem.girth_area_factor = 7.f;
+
2410 shoot_parameters_mainstem.internode_radius_max = 0.0025;
+
2411 shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-2000,-800);
+
2412 shoot_parameters_mainstem.internode_length_max = 0.025;
+
2413 shoot_parameters_mainstem.internode_length_decay_rate = 0;
+
2414 shoot_parameters_mainstem.flowers_require_dormancy = false;
+
2415 shoot_parameters_mainstem.growth_requires_dormancy = false;
+
2416 shoot_parameters_mainstem.determinate_shoot_growth = false;
+
2417 shoot_parameters_mainstem.flower_bud_break_probability = 1.0;
+
2418 shoot_parameters_mainstem.fruit_set_probability = 1.0;
+
2419 shoot_parameters_mainstem.defineChildShootTypes({"mainstem"},{1.0});
+
2420 shoot_parameters_mainstem.max_nodes = 15;
+
2421 shoot_parameters_mainstem.max_terminal_floral_buds = 1;
+
2422
+
2423 defineShootType("mainstem",shoot_parameters_mainstem);
+
2424
+
2425}
+
2426
+
2427uint PlantArchitecture::buildWheatPlant(const helios::vec3 &base_position) {
+
2428
+
2429 if (shoot_types.empty()) {
+
2430 //automatically initialize wheat plant shoots
+
2431 initializeWheatShoots();
+
2432 }
+
2433
+
2434 uint plantID = addPlantInstance(base_position - make_vec3(0,0,0.025), 0);
+
2435
+
2436 uint uID_stem = addBaseStemShoot(plantID, 1, make_AxisRotation(context_ptr->randu(0.f, 0.1f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI)), 0.001, 0.025, 0.01, 0.01, 0, "mainstem");
+
2437
+
2438 breakPlantDormancy(plantID);
+
2439
+
2440 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 2, 5, 100, false);
+
2441
+
2442 return plantID;
+
2443
+
2444}
-
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
-
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, float radius_taper, const std::string &shoot_type_label, uint petiole_index=0)
Manually add a child shoot at the axillary bud of a phytomer.
-
int appendPhytomerToShoot(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.
+
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
+
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, float radius_taper, const std::string &shoot_type_label, uint petiole_index=0)
Manually add a child shoot at the axillary bud of a phytomer.
+
int appendPhytomerToShoot(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.
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.
-
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, float radius_taper, 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...
-
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, float radius_taper, 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 ...
-
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, bool is_evergreen=false)
Specify the threshold values for plant phenological stages.
+
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, float radius_taper, 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...
+
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, float radius_taper, 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 ...
+
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, bool is_evergreen=false)
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 buildPlantInstanceFromLibrary(const helios::vec3 &base_position, float age)
Build a plant instance based on the model currently loaded from the library.
void loadPlantModelFromLibrary(const std::string &plant_label)
Load an existing plant model from the library.
-
void advanceTime(float dt)
Advance plant growth by a specified time interval for all plants.
+
void advanceTime(float dt)
Advance plant growth by a specified time interval for all plants.
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1168
std::minstd_rand0 * getRandomGenerator()
Get the random number generator engine.
Definition Context.cpp:47
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
diff --git a/doc/html/_plug_ins.html b/doc/html/_plug_ins.html index fa1454138..2806f1edf 100644 --- a/doc/html/_plug_ins.html +++ b/doc/html/_plug_ins.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_plugins.html b/doc/html/_plugins.html index c58a4a5f6..71b5f11c2 100644 --- a/doc/html/_plugins.html +++ b/doc/html/_plugins.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_radiation_doc.html b/doc/html/_radiation_doc.html index a97aa650e..8d80f4376 100644 --- a/doc/html/_radiation_doc.html +++ b/doc/html/_radiation_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -812,7 +812,7 @@

return 0;
}
-
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...
+
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...
std::vector< uint > loadXML(const char *filename, bool quiet=false)
Load inputs specified in an XML file.
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
float focal_plane_distance
Distance from the viewing plane to the focal plane.
diff --git a/doc/html/_radiation_model_8cpp.html b/doc/html/_radiation_model_8cpp.html index 9b85bbaf8..4c2dd3372 100644 --- a/doc/html/_radiation_model_8cpp.html +++ b/doc/html/_radiation_model_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -112,9 +112,6 @@ - - - @@ -157,7 +154,7 @@

-

Definition at line 5745 of file RadiationModel.cpp.

+

Definition at line 5759 of file RadiationModel.cpp.

@@ -176,35 +173,7 @@

-

Definition at line 5755 of file RadiationModel.cpp.

- - - - -

◆ validateOutputPath()

- -
-
-

Functions

bool validateOutputPath (std::ostringstream &output_directory)
 Validates the file path for output file writing by 1) making sure the directory string has a trailing slash, 2) creating the output directory if it does not exist.
 
void sutilHandleError (RTcontext context, RTresult code, const char *file, int line)
 
void sutilReportError (const char *message)
- - - - - - -
bool validateOutputPath (std::ostringstream & output_directory)
-
- -

Validates the file path for output file writing by 1) making sure the directory string has a trailing slash, 2) creating the output directory if it does not exist.

-
Parameters
- - -
[in,out]output_directoryPath to the directory where output files will be written. If the directory does not exist, it will be created.
-
-
-
Returns
True if the output directory is valid, false otherwise.
- -

Definition at line 5727 of file RadiationModel.cpp.

+

Definition at line 5769 of file RadiationModel.cpp.

diff --git a/doc/html/_radiation_model_8cpp_source.html b/doc/html/_radiation_model_8cpp_source.html index 6eda15a53..8e22f9bf9 100644 --- a/doc/html/_radiation_model_8cpp_source.html +++ b/doc/html/_radiation_model_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -1583,4476 +1583,4488 @@
1340 frame_str = std::to_string(frame);
1341 }
1342
-
1343 std::ostringstream outfile;
-
1344
-
1345 if( !validateOutputPath(outfile) ){
-
1346 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission.");
-
1347 }
-
1348
-
1349 if( frame>=0 ) {
-
1350 outfile << camera << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".jpeg";
-
1351 }else{
-
1352 outfile << camera << "_" << imagefile_base << ".jpeg";
-
1353 }
-
1354 std::ofstream testfile(outfile.str());
-
1355
-
1356 if( !testfile.is_open() ){
-
1357 std::cout << "ERROR (RadiationModel::writeCameraImage): image file " << outfile.str() << " could not be opened. Check that the path exists and that you have write permission. Skipping image write for this camera." << std::endl;
-
1358 return;
-
1359 }
-
1360 testfile.close();
-
1361
-
1362 int2 camera_resolution = cameras.at(camera).resolution;
-
1363
-
1364 std::vector<RGBcolor> pixel_data(camera_resolution.x*camera_resolution.y);
+
1343 std::string output_path = image_path;
+
1344 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
1345 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
1346 }else if( !getFileName(output_path).empty() ){
+
1347 helios_runtime_error("ERROR(RadiationModel::writeCameraImage): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
1348 }
+
1349
+
1350 std::ostringstream outfile;
+
1351 outfile << output_path;
+
1352
+
1353 if( frame>=0 ) {
+
1354 outfile << camera << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".jpeg";
+
1355 }else{
+
1356 outfile << camera << "_" << imagefile_base << ".jpeg";
+
1357 }
+
1358 std::ofstream testfile(outfile.str());
+
1359
+
1360 if( !testfile.is_open() ){
+
1361 std::cout << "ERROR (RadiationModel::writeCameraImage): image file " << outfile.str() << " could not be opened. Check that the path exists and that you have write permission. Skipping image write for this camera." << std::endl;
+
1362 return;
+
1363 }
+
1364 testfile.close();
1365
-
1366 RGBcolor pixel_color;
-
1367 for (uint j = 0; j < camera_resolution.y; j++) {
-
1368 for (uint i=0; i < camera_resolution.x; i++) {
-
1369 if( camera_data.size()==1 ){
-
1370 float c = camera_data.front().at(j * camera_resolution.x + i);
-
1371 pixel_color = make_RGBcolor(c,c,c);
-
1372 }else{
-
1373 pixel_color = make_RGBcolor(camera_data.at(0).at(j * camera_resolution.x + i),camera_data.at(1).at(j * camera_resolution.x + i),camera_data.at(2).at(j * camera_resolution.x + i));
-
1374 }
-
1375 pixel_color.scale( flux_to_pixel_conversion );
-
1376 uint ii = camera_resolution.x - i -1;
-
1377 uint jj = camera_resolution.y - j - 1;
-
1378 pixel_data.at(jj * camera_resolution.x + ii) = pixel_color;
-
1379 }
-
1380 }
-
1381
-
1382 writeJPEG( outfile.str(), camera_resolution.x, camera_resolution.y, pixel_data );
-
1383
-
1384}
-
+
1366 int2 camera_resolution = cameras.at(camera).resolution;
+
1367
+
1368 std::vector<RGBcolor> pixel_data(camera_resolution.x*camera_resolution.y);
+
1369
+
1370 RGBcolor pixel_color;
+
1371 for (uint j = 0; j < camera_resolution.y; j++) {
+
1372 for (uint i=0; i < camera_resolution.x; i++) {
+
1373 if( camera_data.size()==1 ){
+
1374 float c = camera_data.front().at(j * camera_resolution.x + i);
+
1375 pixel_color = make_RGBcolor(c,c,c);
+
1376 }else{
+
1377 pixel_color = make_RGBcolor(camera_data.at(0).at(j * camera_resolution.x + i),camera_data.at(1).at(j * camera_resolution.x + i),camera_data.at(2).at(j * camera_resolution.x + i));
+
1378 }
+
1379 pixel_color.scale( flux_to_pixel_conversion );
+
1380 uint ii = camera_resolution.x - i -1;
+
1381 uint jj = camera_resolution.y - j - 1;
+
1382 pixel_data.at(jj * camera_resolution.x + ii) = pixel_color;
+
1383 }
+
1384 }
1385
-
-
1386void RadiationModel::writeNormCameraImage(const std::string &camera, const std::vector<std::string> &bands, const std::string &imagefile_base, const std::string &image_path, int frame){
-
1387 float maxval = 0;
-
1388 // Find maximum mean value over all bands
-
1389 for (const std::string& band: bands){
-
1390 std::string global_data_label = "camera_" + camera + "_" + band;
-
1391 if (std::find(cameras.at(camera).band_labels.begin(), cameras.at(camera).band_labels.end(), band ) == cameras.at(camera).band_labels.end()) {
-
1392 std::cout << "ERROR (RadiationModel::writeNormCameraImage): camera " << camera << " band with label " << band << " does not exist. Skipping image write for this camera." << std::endl;
-
1393 return;
-
1394 }else if (!context->doesGlobalDataExist(global_data_label.c_str())) {
-
1395 std::cout << "ERROR (RadiationModel::writeNormCameraImage): image data for camera " << camera << ", band " << band << " has not been created. Did you run the radiation model? Skipping image write for this camera." << std::endl;
-
1396 return;
-
1397 }
-
1398 std::vector<float> cameradata;
-
1399 context->getGlobalData(global_data_label.c_str(), cameradata);
-
1400 for (float val: cameradata){
-
1401 if (val > maxval){
-
1402 maxval = val;
-
1403 }
-
1404 }
-
1405 }
-
1406 // Normalize all bands
-
1407 for (const std::string& band: bands) {
-
1408 std::string global_data_label = "camera_" + camera + "_" + band;
-
1409 std::vector<float> cameradata;
-
1410 context->getGlobalData(global_data_label.c_str(), cameradata);
-
1411 for (float &val: cameradata) {
-
1412 val = val / maxval;
-
1413 }
-
1414 context->setGlobalData(global_data_label.c_str(), HELIOS_TYPE_FLOAT, cameradata.size(), &cameradata[0]);
-
1415 }
-
1416
-
1417 RadiationModel::writeCameraImage(camera, bands, imagefile_base, image_path, frame);
-
1418}
+
1386 writeJPEG( outfile.str(), camera_resolution.x, camera_resolution.y, pixel_data );
+
1387
+
1388}
-
1419
-
-
1420void RadiationModel::writeCameraImageData(const std::string &camera, const std::string &band, const std::string &imagefile_base, const std::string &image_path, int frame){
-
1421
-
1422 //check if camera exists
-
1423 if( cameras.find(camera)==cameras.end() ){
-
1424 std::cout << "ERROR (RadiationModel::writeCameraImageData): camera with label " << camera << " does not exist. Skipping image write for this camera." << std::endl;
-
1425 return;
-
1426 }
-
1427
-
1428 std::vector<float> camera_data;
-
1429
-
1430 //check if band exists
-
1431 if (std::find(cameras.at(camera).band_labels.begin(), cameras.at(camera).band_labels.end(), band) == cameras.at(camera).band_labels.end()) {
-
1432 std::cout << "ERROR (RadiationModel::writeCameraImageData): camera " << camera << " band with label " << band << " does not exist. Skipping image write for this camera." << std::endl;
-
1433 return;
-
1434 }
-
1435
-
1436 std::string global_data_label = "camera_" + camera + "_" + band;
-
1437
-
1438 if (!context->doesGlobalDataExist(global_data_label.c_str())) {
-
1439 std::cout << "ERROR (RadiationModel::writeCameraImageData): image data for camera " << camera << ", band " << band << " has not been created. Did you run the radiation model? Skipping image write for this camera." << std::endl;
-
1440 return;
-
1441 }
-
1442
-
1443 context->getGlobalData(global_data_label.c_str(), camera_data );
-
1444
-
1445 std::string frame_str;
-
1446 if( frame>=0 ) {
-
1447 frame_str = std::to_string(frame);
-
1448 }
-
1449
-
1450 std::ostringstream outfile;
-
1451
-
1452 if( !validateOutputPath(outfile) ){
-
1453 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission.");
-
1454 }
-
1455
-
1456 if( frame>=0 ) {
-
1457 outfile << camera << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
-
1458 }else{
-
1459 outfile << camera << "_" << imagefile_base << ".txt";
-
1460 }
-
1461
-
1462 std::ofstream outfilestream(outfile.str());
-
1463
-
1464 if( !outfilestream.is_open() ){
-
1465 std::cout << "ERROR (RadiationModel::writeCameraImageData): image file " << outfile.str() << " could not be opened. Check that the path exists and that you have write permission. Skipping image write for this camera." << std::endl;
-
1466 return;
-
1467 }
-
1468
-
1469 int2 camera_resolution = cameras.at(camera).resolution;
-
1470
-
1471 for ( int j = 0; j<camera_resolution.y; j++ ) {
-
1472 for ( int i = camera_resolution.x-1; i >= 0; i-- ) {
-
1473 outfilestream << camera_data.at(j*camera_resolution.x + i ) << " ";
-
1474 }
-
1475 outfilestream << "\n";
-
1476 }
-
1477
-
1478 outfilestream.close();
-
1479
-
1480}
+
1389
+
+
1390void RadiationModel::writeNormCameraImage(const std::string &camera, const std::vector<std::string> &bands, const std::string &imagefile_base, const std::string &image_path, int frame){
+
1391 float maxval = 0;
+
1392 // Find maximum mean value over all bands
+
1393 for (const std::string& band: bands){
+
1394 std::string global_data_label = "camera_" + camera + "_" + band;
+
1395 if (std::find(cameras.at(camera).band_labels.begin(), cameras.at(camera).band_labels.end(), band ) == cameras.at(camera).band_labels.end()) {
+
1396 std::cout << "ERROR (RadiationModel::writeNormCameraImage): camera " << camera << " band with label " << band << " does not exist. Skipping image write for this camera." << std::endl;
+
1397 return;
+
1398 }else if (!context->doesGlobalDataExist(global_data_label.c_str())) {
+
1399 std::cout << "ERROR (RadiationModel::writeNormCameraImage): image data for camera " << camera << ", band " << band << " has not been created. Did you run the radiation model? Skipping image write for this camera." << std::endl;
+
1400 return;
+
1401 }
+
1402 std::vector<float> cameradata;
+
1403 context->getGlobalData(global_data_label.c_str(), cameradata);
+
1404 for (float val: cameradata){
+
1405 if (val > maxval){
+
1406 maxval = val;
+
1407 }
+
1408 }
+
1409 }
+
1410 // Normalize all bands
+
1411 for (const std::string& band: bands) {
+
1412 std::string global_data_label = "camera_" + camera + "_" + band;
+
1413 std::vector<float> cameradata;
+
1414 context->getGlobalData(global_data_label.c_str(), cameradata);
+
1415 for (float &val: cameradata) {
+
1416 val = val / maxval;
+
1417 }
+
1418 context->setGlobalData(global_data_label.c_str(), HELIOS_TYPE_FLOAT, cameradata.size(), &cameradata[0]);
+
1419 }
+
1420
+
1421 RadiationModel::writeCameraImage(camera, bands, imagefile_base, image_path, frame);
+
1422}
-
1481
-
1482void RadiationModel::initializeOptiX() {
-
1483
-
1484 /* Context */
-
1485 RT_CHECK_ERROR( rtContextCreate( &OptiX_Context ) );
-
1486 RT_CHECK_ERROR( rtContextSetPrintEnabled( OptiX_Context, 1 ) );
+
1423
+
+
1424void RadiationModel::writeCameraImageData(const std::string &camera, const std::string &band, const std::string &imagefile_base, const std::string &image_path, int frame){
+
1425
+
1426 //check if camera exists
+
1427 if( cameras.find(camera)==cameras.end() ){
+
1428 std::cout << "ERROR (RadiationModel::writeCameraImageData): camera with label " << camera << " does not exist. Skipping image write for this camera." << std::endl;
+
1429 return;
+
1430 }
+
1431
+
1432 std::vector<float> camera_data;
+
1433
+
1434 //check if band exists
+
1435 if (std::find(cameras.at(camera).band_labels.begin(), cameras.at(camera).band_labels.end(), band) == cameras.at(camera).band_labels.end()) {
+
1436 std::cout << "ERROR (RadiationModel::writeCameraImageData): camera " << camera << " band with label " << band << " does not exist. Skipping image write for this camera." << std::endl;
+
1437 return;
+
1438 }
+
1439
+
1440 std::string global_data_label = "camera_" + camera + "_" + band;
+
1441
+
1442 if (!context->doesGlobalDataExist(global_data_label.c_str())) {
+
1443 std::cout << "ERROR (RadiationModel::writeCameraImageData): image data for camera " << camera << ", band " << band << " has not been created. Did you run the radiation model? Skipping image write for this camera." << std::endl;
+
1444 return;
+
1445 }
+
1446
+
1447 context->getGlobalData(global_data_label.c_str(), camera_data );
+
1448
+
1449 std::string frame_str;
+
1450 if( frame>=0 ) {
+
1451 frame_str = std::to_string(frame);
+
1452 }
+
1453
+
1454 std::string output_path = image_path;
+
1455 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
1456 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
1457 }else if( !getFileName(output_path).empty() ){
+
1458 helios_runtime_error("ERROR(RadiationModel::writeCameraImage): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
1459 }
+
1460
+
1461 std::ostringstream outfile;
+
1462 outfile << output_path;
+
1463
+
1464 if( frame>=0 ) {
+
1465 outfile << camera << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
+
1466 }else{
+
1467 outfile << camera << "_" << imagefile_base << ".txt";
+
1468 }
+
1469
+
1470 std::ofstream outfilestream(outfile.str());
+
1471
+
1472 if( !outfilestream.is_open() ){
+
1473 std::cout << "ERROR (RadiationModel::writeCameraImageData): image file " << outfile.str() << " could not be opened. Check that the path exists and that you have write permission. Skipping image write for this camera." << std::endl;
+
1474 return;
+
1475 }
+
1476
+
1477 int2 camera_resolution = cameras.at(camera).resolution;
+
1478
+
1479 for ( int j = 0; j<camera_resolution.y; j++ ) {
+
1480 for ( int i = camera_resolution.x-1; i >= 0; i-- ) {
+
1481 outfilestream << camera_data.at(j*camera_resolution.x + i ) << " ";
+
1482 }
+
1483 outfilestream << "\n";
+
1484 }
+
1485
+
1486 outfilestream.close();
1487
-
1488 RT_CHECK_ERROR( rtContextSetRayTypeCount( OptiX_Context, 4 ) );
-
1489 //ray types are:
-
1490 // 0: direct_ray_type
-
1491 // 1: diffuse_ray_type
-
1492 // 2: camera_ray_type
-
1493 // 3: pixel_label_ray_type
-
1494
-
1495 RT_CHECK_ERROR( rtContextSetEntryPointCount( OptiX_Context, 4 ) );
-
1496 //ray entery points are
-
1497 // 0: direct_raygen
-
1498 // 1: diffuse_raygen
-
1499 // 2: camera_raygen
-
1500 // 3: pixel_label_raygen
-
1501
-
1502 /* Ray Types */
-
1503 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "direct_ray_type", &direct_ray_type_RTvariable ) );
-
1504 RT_CHECK_ERROR( rtVariableSet1ui( direct_ray_type_RTvariable, RAYTYPE_DIRECT ) );
-
1505 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "diffuse_ray_type", &diffuse_ray_type_RTvariable ) );
-
1506 RT_CHECK_ERROR( rtVariableSet1ui( diffuse_ray_type_RTvariable, RAYTYPE_DIFFUSE ) );
-
1507 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_ray_type", &camera_ray_type_RTvariable ) );
-
1508 RT_CHECK_ERROR( rtVariableSet1ui( camera_ray_type_RTvariable, RAYTYPE_CAMERA ) );
-
1509 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "pixel_label_ray_type", &pixel_label_ray_type_RTvariable ) );
-
1510 RT_CHECK_ERROR( rtVariableSet1ui( pixel_label_ray_type_RTvariable, RAYTYPE_PIXEL_LABEL ) );
-
1511
-
1512 /* Ray Generation Program */
-
1513
-
1514 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "direct_raygen", &direct_raygen ) );
-
1515 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_DIRECT, direct_raygen ) );
-
1516 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "diffuse_raygen", &diffuse_raygen ) );
-
1517 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_DIFFUSE, diffuse_raygen ) );
-
1518 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "camera_raygen", &camera_raygen ) );
-
1519 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_CAMERA, camera_raygen ) );
-
1520 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "pixel_label_raygen", &pixel_label_raygen ) );
-
1521 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_PIXEL_LABEL, pixel_label_raygen ) );
-
1522
-
1523 /* Declare Buffers and Variables */
-
1524
-
1525 //primitive reflectivity buffer
-
1526 addBuffer( "rho", rho_RTbuffer, rho_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1527 //primitive transmissivity buffer
-
1528 addBuffer( "tau", tau_RTbuffer, tau_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1529
-
1530 //primitive reflectivity buffer
-
1531 addBuffer( "rho_cam", rho_cam_RTbuffer, rho_cam_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1532 //primitive transmissivity buffer
-
1533 addBuffer( "tau_cam", tau_cam_RTbuffer, tau_cam_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1534
-
1535 //primitive transformation matrix buffer
-
1536 addBuffer( "transform_matrix", transform_matrix_RTbuffer, transform_matrix_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 2 );
+
1488}
+
+
1489
+
1490void RadiationModel::initializeOptiX() {
+
1491
+
1492 /* Context */
+
1493 RT_CHECK_ERROR( rtContextCreate( &OptiX_Context ) );
+
1494 RT_CHECK_ERROR( rtContextSetPrintEnabled( OptiX_Context, 1 ) );
+
1495
+
1496 RT_CHECK_ERROR( rtContextSetRayTypeCount( OptiX_Context, 4 ) );
+
1497 //ray types are:
+
1498 // 0: direct_ray_type
+
1499 // 1: diffuse_ray_type
+
1500 // 2: camera_ray_type
+
1501 // 3: pixel_label_ray_type
+
1502
+
1503 RT_CHECK_ERROR( rtContextSetEntryPointCount( OptiX_Context, 4 ) );
+
1504 //ray entery points are
+
1505 // 0: direct_raygen
+
1506 // 1: diffuse_raygen
+
1507 // 2: camera_raygen
+
1508 // 3: pixel_label_raygen
+
1509
+
1510 /* Ray Types */
+
1511 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "direct_ray_type", &direct_ray_type_RTvariable ) );
+
1512 RT_CHECK_ERROR( rtVariableSet1ui( direct_ray_type_RTvariable, RAYTYPE_DIRECT ) );
+
1513 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "diffuse_ray_type", &diffuse_ray_type_RTvariable ) );
+
1514 RT_CHECK_ERROR( rtVariableSet1ui( diffuse_ray_type_RTvariable, RAYTYPE_DIFFUSE ) );
+
1515 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_ray_type", &camera_ray_type_RTvariable ) );
+
1516 RT_CHECK_ERROR( rtVariableSet1ui( camera_ray_type_RTvariable, RAYTYPE_CAMERA ) );
+
1517 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "pixel_label_ray_type", &pixel_label_ray_type_RTvariable ) );
+
1518 RT_CHECK_ERROR( rtVariableSet1ui( pixel_label_ray_type_RTvariable, RAYTYPE_PIXEL_LABEL ) );
+
1519
+
1520 /* Ray Generation Program */
+
1521
+
1522 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "direct_raygen", &direct_raygen ) );
+
1523 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_DIRECT, direct_raygen ) );
+
1524 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "diffuse_raygen", &diffuse_raygen ) );
+
1525 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_DIFFUSE, diffuse_raygen ) );
+
1526 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "camera_raygen", &camera_raygen ) );
+
1527 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_CAMERA, camera_raygen ) );
+
1528 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "pixel_label_raygen", &pixel_label_raygen ) );
+
1529 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_PIXEL_LABEL, pixel_label_raygen ) );
+
1530
+
1531 /* Declare Buffers and Variables */
+
1532
+
1533 //primitive reflectivity buffer
+
1534 addBuffer( "rho", rho_RTbuffer, rho_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1535 //primitive transmissivity buffer
+
1536 addBuffer( "tau", tau_RTbuffer, tau_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
1537
-
1538 //primitive type buffer
-
1539 addBuffer( "primitive_type", primitive_type_RTbuffer, primitive_type_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1540
-
1541 //primitive area buffer
-
1542 addBuffer( "primitive_area", primitive_area_RTbuffer, primitive_area_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1543
-
1544 //primitive UUID buffers
-
1545 addBuffer( "patch_UUID", patch_UUID_RTbuffer, patch_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1546 addBuffer( "triangle_UUID", triangle_UUID_RTbuffer, triangle_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1547 addBuffer( "disk_UUID", disk_UUID_RTbuffer, disk_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1548 addBuffer( "tile_UUID", tile_UUID_RTbuffer, tile_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1549 addBuffer( "voxel_UUID", voxel_UUID_RTbuffer, voxel_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1550
-
1551 //Object ID Buffer
-
1552 addBuffer( "objectID", objectID_RTbuffer, objectID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1553
-
1554 //Primitive ID Buffer
-
1555 addBuffer( "primitiveID", primitiveID_RTbuffer, primitiveID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1556
-
1557 //primitive two-sided flag buffer
-
1558 addBuffer( "twosided_flag", twosided_flag_RTbuffer, twosided_flag_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_BYTE, 1 );
-
1559
-
1560 //patch buffers
-
1561 addBuffer( "patch_vertices", patch_vertices_RTbuffer, patch_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
-
1562
-
1563 //triangle buffers
-
1564 addBuffer( "triangle_vertices", triangle_vertices_RTbuffer, triangle_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
-
1565
-
1566 //disk buffers
-
1567 addBuffer( "disk_centers", disk_centers_RTbuffer, disk_centers_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
-
1568 addBuffer( "disk_radii", disk_radii_RTbuffer, disk_radii_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1569 addBuffer( "disk_normals", disk_normals_RTbuffer, disk_normals_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
+
1538 //primitive reflectivity buffer
+
1539 addBuffer( "rho_cam", rho_cam_RTbuffer, rho_cam_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1540 //primitive transmissivity buffer
+
1541 addBuffer( "tau_cam", tau_cam_RTbuffer, tau_cam_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1542
+
1543 //primitive transformation matrix buffer
+
1544 addBuffer( "transform_matrix", transform_matrix_RTbuffer, transform_matrix_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 2 );
+
1545
+
1546 //primitive type buffer
+
1547 addBuffer( "primitive_type", primitive_type_RTbuffer, primitive_type_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1548
+
1549 //primitive area buffer
+
1550 addBuffer( "primitive_area", primitive_area_RTbuffer, primitive_area_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1551
+
1552 //primitive UUID buffers
+
1553 addBuffer( "patch_UUID", patch_UUID_RTbuffer, patch_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1554 addBuffer( "triangle_UUID", triangle_UUID_RTbuffer, triangle_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1555 addBuffer( "disk_UUID", disk_UUID_RTbuffer, disk_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1556 addBuffer( "tile_UUID", tile_UUID_RTbuffer, tile_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1557 addBuffer( "voxel_UUID", voxel_UUID_RTbuffer, voxel_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1558
+
1559 //Object ID Buffer
+
1560 addBuffer( "objectID", objectID_RTbuffer, objectID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1561
+
1562 //Primitive ID Buffer
+
1563 addBuffer( "primitiveID", primitiveID_RTbuffer, primitiveID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1564
+
1565 //primitive two-sided flag buffer
+
1566 addBuffer( "twosided_flag", twosided_flag_RTbuffer, twosided_flag_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_BYTE, 1 );
+
1567
+
1568 //patch buffers
+
1569 addBuffer( "patch_vertices", patch_vertices_RTbuffer, patch_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
1570
-
1571 //tile buffers
-
1572 addBuffer( "tile_vertices", tile_vertices_RTbuffer, tile_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
+
1571 //triangle buffers
+
1572 addBuffer( "triangle_vertices", triangle_vertices_RTbuffer, triangle_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
1573
-
1574 //voxel buffers
-
1575 addBuffer( "voxel_vertices", voxel_vertices_RTbuffer, voxel_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
-
1576
-
1577 //object buffers
-
1578 addBuffer( "object_subdivisions", object_subdivisions_RTbuffer, object_subdivisions_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT2, 1 );
-
1579
-
1580 //radiation energy rate data buffers
-
1581 // - in - //
-
1582 addBuffer( "radiation_in", radiation_in_RTbuffer, radiation_in_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1583 // - out,top - //
-
1584 addBuffer( "radiation_out_top", radiation_out_top_RTbuffer, radiation_out_top_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1585 // - out,bottom - //
-
1586 addBuffer( "radiation_out_bottom", radiation_out_bottom_RTbuffer, radiation_out_bottom_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1587 // - camera - //
-
1588 addBuffer( "radiation_in_camera", radiation_in_camera_RTbuffer, radiation_in_camera_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1589 addBuffer( "camera_pixel_label", camera_pixel_label_RTbuffer, camera_pixel_label_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1590 addBuffer( "camera_pixel_depth", camera_pixel_depth_RTbuffer, camera_pixel_depth_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1591
-
1592 //primitive scattering buffers
-
1593 // - top - //
-
1594 addBuffer( "scatter_buff_top", scatter_buff_top_RTbuffer, scatter_buff_top_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1595 // - bottom - //
-
1596 addBuffer( "scatter_buff_bottom", scatter_buff_bottom_RTbuffer, scatter_buff_bottom_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1597
-
1598 //Energy absorbed by "sky"
-
1599 addBuffer( "Rsky", Rsky_RTbuffer, Rsky_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1600
-
1601 //number of external radiation sources
-
1602 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nsources", &Nsources_RTvariable ) );
-
1603 RT_CHECK_ERROR( rtVariableSet1ui( Nsources_RTvariable,0 ) );
-
1604
-
1605 //External radiation source positions
-
1606 addBuffer( "source_positions", source_positions_RTbuffer, source_positions_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
-
1607
-
1608 //External radiation source widths
-
1609 addBuffer( "source_widths", source_widths_RTbuffer, source_widths_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT2, 1 );
-
1610
-
1611 //External radiation source rotations
-
1612 addBuffer( "source_rotations", source_rotations_RTbuffer, source_rotations_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
-
1613
-
1614 //External radiation source types
-
1615 addBuffer( "source_types", source_types_RTbuffer, source_types_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1616
-
1617 //External radiation source fluxes
-
1618 addBuffer( "source_fluxes", source_fluxes_RTbuffer, source_fluxes_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1619
-
1620 //number of radiation bands
-
1621 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nbands", &Nbands_RTvariable ) );
-
1622 RT_CHECK_ERROR( rtVariableSet1ui( Nbands_RTvariable,0 ) );
-
1623
-
1624 //flag to disable launches for certain bands
-
1625 addBuffer( "band_launch_flag", band_launch_flag_RTbuffer, band_launch_flag_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_BYTE, 1 );
-
1626
-
1627 //number of Context primitives
-
1628 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nprimitives", &Nprimitives_RTvariable ) );
-
1629 RT_CHECK_ERROR( rtVariableSet1ui( Nprimitives_RTvariable,0 ) );
-
1630
-
1631 //Flux of diffuse radiation
-
1632 addBuffer( "diffuse_flux", diffuse_flux_RTbuffer, diffuse_flux_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1633
-
1634 //Diffuse distribution extinction coefficient of ambient diffuse radiation
-
1635 addBuffer( "diffuse_extinction", diffuse_extinction_RTbuffer, diffuse_extinction_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1636
-
1637 //Direction of peak diffuse radiation
-
1638 addBuffer( "diffuse_peak_dir", diffuse_peak_dir_RTbuffer, diffuse_peak_dir_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
-
1639
-
1640 //Diffuse distribution normalization factor
-
1641 addBuffer( "diffuse_dist_norm", diffuse_dist_norm_RTbuffer, diffuse_dist_norm_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1642
-
1643 //Bounding sphere radius and center
-
1644 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "bound_sphere_radius", &bound_sphere_radius_RTvariable ) );
-
1645 RT_CHECK_ERROR( rtVariableSet1f( bound_sphere_radius_RTvariable, 0.f ));
-
1646 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "bound_sphere_center", &bound_sphere_center_RTvariable ) );
-
1647 RT_CHECK_ERROR( rtVariableSet3f( bound_sphere_center_RTvariable, 0.f, 0.f, 0.f ));
-
1648
-
1649 //Bounding Box
-
1650 addBuffer( "bbox_UUID", bbox_UUID_RTbuffer, bbox_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1651 addBuffer( "bbox_vertices", bbox_vertices_RTbuffer, bbox_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
-
1652
-
1653 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "periodic_flag", &periodic_flag_RTvariable ) );
-
1654 RT_CHECK_ERROR( rtVariableSet2f( periodic_flag_RTvariable, 0.f, 0.f ));
-
1655
-
1656 //Texture mask data
-
1657 RT_CHECK_ERROR( rtBufferCreate( OptiX_Context, RT_BUFFER_INPUT, &maskdata_RTbuffer ) );
-
1658 RT_CHECK_ERROR( rtBufferSetFormat( maskdata_RTbuffer, RT_FORMAT_BYTE ) );
-
1659 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "maskdata", &maskdata_RTvariable ) );
-
1660 RT_CHECK_ERROR( rtVariableSetObject( maskdata_RTvariable, maskdata_RTbuffer ) );
-
1661 std::vector<std::vector<std::vector<bool> > > dummydata;
-
1662 initializeBuffer3D( maskdata_RTbuffer, dummydata );
+
1574 //disk buffers
+
1575 addBuffer( "disk_centers", disk_centers_RTbuffer, disk_centers_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
+
1576 addBuffer( "disk_radii", disk_radii_RTbuffer, disk_radii_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1577 addBuffer( "disk_normals", disk_normals_RTbuffer, disk_normals_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
+
1578
+
1579 //tile buffers
+
1580 addBuffer( "tile_vertices", tile_vertices_RTbuffer, tile_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
+
1581
+
1582 //voxel buffers
+
1583 addBuffer( "voxel_vertices", voxel_vertices_RTbuffer, voxel_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
+
1584
+
1585 //object buffers
+
1586 addBuffer( "object_subdivisions", object_subdivisions_RTbuffer, object_subdivisions_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT2, 1 );
+
1587
+
1588 //radiation energy rate data buffers
+
1589 // - in - //
+
1590 addBuffer( "radiation_in", radiation_in_RTbuffer, radiation_in_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1591 // - out,top - //
+
1592 addBuffer( "radiation_out_top", radiation_out_top_RTbuffer, radiation_out_top_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1593 // - out,bottom - //
+
1594 addBuffer( "radiation_out_bottom", radiation_out_bottom_RTbuffer, radiation_out_bottom_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1595 // - camera - //
+
1596 addBuffer( "radiation_in_camera", radiation_in_camera_RTbuffer, radiation_in_camera_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1597 addBuffer( "camera_pixel_label", camera_pixel_label_RTbuffer, camera_pixel_label_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1598 addBuffer( "camera_pixel_depth", camera_pixel_depth_RTbuffer, camera_pixel_depth_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1599
+
1600 //primitive scattering buffers
+
1601 // - top - //
+
1602 addBuffer( "scatter_buff_top", scatter_buff_top_RTbuffer, scatter_buff_top_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1603 // - bottom - //
+
1604 addBuffer( "scatter_buff_bottom", scatter_buff_bottom_RTbuffer, scatter_buff_bottom_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1605
+
1606 //Energy absorbed by "sky"
+
1607 addBuffer( "Rsky", Rsky_RTbuffer, Rsky_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1608
+
1609 //number of external radiation sources
+
1610 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nsources", &Nsources_RTvariable ) );
+
1611 RT_CHECK_ERROR( rtVariableSet1ui( Nsources_RTvariable,0 ) );
+
1612
+
1613 //External radiation source positions
+
1614 addBuffer( "source_positions", source_positions_RTbuffer, source_positions_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
+
1615
+
1616 //External radiation source widths
+
1617 addBuffer( "source_widths", source_widths_RTbuffer, source_widths_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT2, 1 );
+
1618
+
1619 //External radiation source rotations
+
1620 addBuffer( "source_rotations", source_rotations_RTbuffer, source_rotations_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
+
1621
+
1622 //External radiation source types
+
1623 addBuffer( "source_types", source_types_RTbuffer, source_types_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1624
+
1625 //External radiation source fluxes
+
1626 addBuffer( "source_fluxes", source_fluxes_RTbuffer, source_fluxes_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1627
+
1628 //number of radiation bands
+
1629 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nbands", &Nbands_RTvariable ) );
+
1630 RT_CHECK_ERROR( rtVariableSet1ui( Nbands_RTvariable,0 ) );
+
1631
+
1632 //flag to disable launches for certain bands
+
1633 addBuffer( "band_launch_flag", band_launch_flag_RTbuffer, band_launch_flag_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_BYTE, 1 );
+
1634
+
1635 //number of Context primitives
+
1636 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nprimitives", &Nprimitives_RTvariable ) );
+
1637 RT_CHECK_ERROR( rtVariableSet1ui( Nprimitives_RTvariable,0 ) );
+
1638
+
1639 //Flux of diffuse radiation
+
1640 addBuffer( "diffuse_flux", diffuse_flux_RTbuffer, diffuse_flux_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1641
+
1642 //Diffuse distribution extinction coefficient of ambient diffuse radiation
+
1643 addBuffer( "diffuse_extinction", diffuse_extinction_RTbuffer, diffuse_extinction_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1644
+
1645 //Direction of peak diffuse radiation
+
1646 addBuffer( "diffuse_peak_dir", diffuse_peak_dir_RTbuffer, diffuse_peak_dir_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
+
1647
+
1648 //Diffuse distribution normalization factor
+
1649 addBuffer( "diffuse_dist_norm", diffuse_dist_norm_RTbuffer, diffuse_dist_norm_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1650
+
1651 //Bounding sphere radius and center
+
1652 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "bound_sphere_radius", &bound_sphere_radius_RTvariable ) );
+
1653 RT_CHECK_ERROR( rtVariableSet1f( bound_sphere_radius_RTvariable, 0.f ));
+
1654 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "bound_sphere_center", &bound_sphere_center_RTvariable ) );
+
1655 RT_CHECK_ERROR( rtVariableSet3f( bound_sphere_center_RTvariable, 0.f, 0.f, 0.f ));
+
1656
+
1657 //Bounding Box
+
1658 addBuffer( "bbox_UUID", bbox_UUID_RTbuffer, bbox_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1659 addBuffer( "bbox_vertices", bbox_vertices_RTbuffer, bbox_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
+
1660
+
1661 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "periodic_flag", &periodic_flag_RTvariable ) );
+
1662 RT_CHECK_ERROR( rtVariableSet2f( periodic_flag_RTvariable, 0.f, 0.f ));
1663
-
1664 //Texture mask size
-
1665 addBuffer( "masksize", masksize_RTbuffer, masksize_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT2, 1 );
-
1666
-
1667 //Texture mask ID
-
1668 addBuffer( "maskID", maskID_RTbuffer, maskID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT, 1 );
-
1669
-
1670 //Texture u,v data
-
1671 addBuffer( "uvdata", uvdata_RTbuffer, uvdata_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT2, 2 );
-
1672
-
1673 //Texture u,v ID
-
1674 addBuffer( "uvID", uvID_RTbuffer, uvID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT, 1 );
-
1675
-
1676 // Radiation Camera Variables
-
1677 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_position", &camera_position_RTvariable ) );
-
1678 RT_CHECK_ERROR( rtVariableSet3f( camera_position_RTvariable, 0.f, 0.f, 0.f ));
-
1679 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_direction", &camera_direction_RTvariable ) );
-
1680 RT_CHECK_ERROR( rtVariableSet2f( camera_direction_RTvariable, 0.f, 0.f ));
-
1681 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_lens_diameter", &camera_lens_diameter_RTvariable ) );
-
1682 RT_CHECK_ERROR( rtVariableSet1f( camera_lens_diameter_RTvariable, 0.f ));
-
1683 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "FOV_aspect_ratio", &FOV_aspect_RTvariable ) );
-
1684 RT_CHECK_ERROR( rtVariableSet1f( FOV_aspect_RTvariable, 1.f ));
-
1685 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_focal_length", &camera_focal_length_RTvariable ) );
-
1686 RT_CHECK_ERROR( rtVariableSet1f( camera_focal_length_RTvariable, 0.f ));
-
1687 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_viewplane_length", &camera_viewplane_length_RTvariable ) );
-
1688 RT_CHECK_ERROR( rtVariableSet1f( camera_viewplane_length_RTvariable, 0.f ));
-
1689 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Ncameras", &Ncameras_RTvariable ) );
-
1690 RT_CHECK_ERROR( rtVariableSet1ui( Ncameras_RTvariable, 0 ));
-
1691 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_ID", &camera_ID_RTvariable ) );
-
1692 RT_CHECK_ERROR( rtVariableSet1ui( camera_ID_RTvariable, 0 ));
-
1693
-
1694 // primitive scattering buffers (cameras)
-
1695 addBuffer( "scatter_buff_top_cam", scatter_buff_top_cam_RTbuffer, scatter_buff_top_cam_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1696 addBuffer( "scatter_buff_bottom_cam", scatter_buff_bottom_cam_RTbuffer, scatter_buff_bottom_cam_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1697
-
1698 /* Hit Programs */
-
1699 RTprogram closest_hit_direct;
-
1700 RTprogram closest_hit_diffuse;
-
1701 RTprogram closest_hit_camera;
-
1702 RTprogram closest_hit_pixel_label;
-
1703 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_direct", &closest_hit_direct ) );
-
1704 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_diffuse", &closest_hit_diffuse ) );
-
1705 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_camera", &closest_hit_camera ) );
-
1706 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_pixel_label", &closest_hit_pixel_label ) );
-
1707
-
1708 /* Initialize Patch Geometry */
-
1709
-
1710 RTprogram patch_intersection_program;
-
1711 RTprogram patch_bounding_box_program;
-
1712
-
1713 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &patch ) );
-
1714
-
1715 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "rectangle_bounds", &patch_bounding_box_program ) );
-
1716 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( patch, patch_bounding_box_program ) );
-
1717 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "rectangle_intersect", &patch_intersection_program ) );
-
1718 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( patch, patch_intersection_program ) );
-
1719
-
1720 /* Create Patch Material */
-
1721
-
1722 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &patch_material ) );
-
1723
-
1724 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_DIRECT, closest_hit_direct ) );
-
1725 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
-
1726 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_CAMERA, closest_hit_camera ) );
-
1727 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
-
1728
-
1729 /* Initialize Triangle Geometry */
-
1730
-
1731 RTprogram triangle_intersection_program;
-
1732 RTprogram triangle_bounding_box_program;
-
1733
-
1734 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &triangle ) );
-
1735
-
1736 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "triangle_bounds", &triangle_bounding_box_program ) );
-
1737 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( triangle, triangle_bounding_box_program ) );
-
1738 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "triangle_intersect", &triangle_intersection_program ) );
-
1739 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( triangle, triangle_intersection_program ) );
-
1740
-
1741 /* Create Triangle Material */
-
1742
-
1743 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &triangle_material ) );
-
1744
-
1745 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_DIRECT, closest_hit_direct ) );
-
1746 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
-
1747 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_CAMERA, closest_hit_camera ) );
-
1748 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
-
1749
-
1750 /* Initialize Disk Geometry */
-
1751
-
1752 RTprogram disk_intersection_program;
-
1753 RTprogram disk_bounding_box_program;
-
1754
-
1755 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &disk ) );
-
1756
-
1757 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "disk_bounds", &disk_bounding_box_program ) );
-
1758 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( disk, disk_bounding_box_program ) );
-
1759 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "disk_intersect", &disk_intersection_program ) );
-
1760 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( disk, disk_intersection_program ) );
-
1761
-
1762 /* Create Disk Material */
-
1763
-
1764 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &disk_material ) );
-
1765
-
1766 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_DIRECT, closest_hit_direct ) );
-
1767 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
-
1768 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_CAMERA, closest_hit_camera ) );
-
1769 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
-
1770
-
1771 /* Initialize Tile Geometry */
-
1772
-
1773 RTprogram tile_intersection_program;
-
1774 RTprogram tile_bounding_box_program;
-
1775
-
1776 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &tile ) );
-
1777
-
1778 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "tile_bounds", &tile_bounding_box_program ) );
-
1779 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( tile, tile_bounding_box_program ) );
-
1780 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "tile_intersect", &tile_intersection_program ) );
-
1781 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( tile, tile_intersection_program ) );
-
1782
-
1783 /* Create Tile Material */
-
1784
-
1785 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &tile_material ) );
-
1786
-
1787 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_DIRECT, closest_hit_direct ) );
-
1788 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
-
1789 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_CAMERA, closest_hit_camera) );
-
1790 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
-
1791
-
1792 /* Initialize Voxel Geometry */
-
1793
-
1794 RTprogram voxel_intersection_program;
-
1795 RTprogram voxel_bounding_box_program;
-
1796
-
1797 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &voxel ) );
-
1798
-
1799 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "voxel_bounds", &voxel_bounding_box_program ) );
-
1800 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( voxel, voxel_bounding_box_program ) );
-
1801 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "voxel_intersect", &voxel_intersection_program ) );
-
1802 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( voxel, voxel_intersection_program ) );
-
1803
-
1804 /* Create Voxel Material */
-
1805
-
1806 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &voxel_material ) );
-
1807
-
1808 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_DIRECT, closest_hit_direct ) );
-
1809 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
-
1810 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_CAMERA, closest_hit_camera ) );
-
1811 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
-
1812
-
1813 /* Initialize Bounding Box Geometry */
-
1814
-
1815 RTprogram bbox_intersection_program;
-
1816 RTprogram bbox_bounding_box_program;
-
1817
-
1818 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &bbox ) );
-
1819
-
1820 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "bbox_bounds", &bbox_bounding_box_program ) );
-
1821 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( bbox, bbox_bounding_box_program ) );
-
1822 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "bbox_intersect", &bbox_intersection_program ) );
-
1823 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( bbox, bbox_intersection_program ) );
-
1824
-
1825 /* Create Bounding Box Material */
-
1826
-
1827 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &bbox_material ) );
-
1828
-
1829 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_DIRECT, closest_hit_direct ) );
-
1830 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
-
1831 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_CAMERA, closest_hit_camera ) );
-
1832 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
-
1833
-
1834 /* Miss Program */
-
1835 RTprogram miss_program_direct;
-
1836 RTprogram miss_program_diffuse;
-
1837 RTprogram miss_program_camera;
-
1838 RTprogram miss_program_pixel_label;
-
1839 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_direct", &miss_program_direct ) );
-
1840 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_DIRECT, miss_program_direct ) );
-
1841 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_diffuse", &miss_program_diffuse ) );
-
1842 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_DIFFUSE, miss_program_diffuse ) );
-
1843 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_camera", &miss_program_camera ) );
-
1844 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_CAMERA, miss_program_camera ) );
-
1845 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_pixel_label", &miss_program_pixel_label ) );
-
1846 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_PIXEL_LABEL, miss_program_pixel_label ) );
-
1847
-
1848 /* Create OptiX Geometry Structures */
-
1849
-
1850 RTtransform transform;
-
1851
-
1852 RTgeometrygroup geometry_group;
-
1853
-
1854 RTgeometryinstance patch_instance;
-
1855 RTgeometryinstance triangle_instance;
-
1856 RTgeometryinstance disk_instance;
-
1857 RTgeometryinstance tile_instance;
-
1858 RTgeometryinstance voxel_instance;
-
1859 RTgeometryinstance bbox_instance;
-
1860
-
1861 /* Create top level group and associated (dummy) acceleration */
-
1862 RT_CHECK_ERROR( rtGroupCreate( OptiX_Context, &top_level_group ) );
-
1863 RT_CHECK_ERROR( rtGroupSetChildCount( top_level_group, 1 ) );
-
1864
-
1865 RT_CHECK_ERROR( rtAccelerationCreate( OptiX_Context, &top_level_acceleration ) );
-
1866 RT_CHECK_ERROR( rtAccelerationSetBuilder(top_level_acceleration,"NoAccel") );
-
1867 RT_CHECK_ERROR( rtAccelerationSetTraverser(top_level_acceleration,"NoAccel") );
-
1868 RT_CHECK_ERROR( rtGroupSetAcceleration( top_level_group, top_level_acceleration) );
-
1869
-
1870 /* mark acceleration as dirty */
-
1871 RT_CHECK_ERROR( rtAccelerationMarkDirty( top_level_acceleration ) );
+
1664 //Texture mask data
+
1665 RT_CHECK_ERROR( rtBufferCreate( OptiX_Context, RT_BUFFER_INPUT, &maskdata_RTbuffer ) );
+
1666 RT_CHECK_ERROR( rtBufferSetFormat( maskdata_RTbuffer, RT_FORMAT_BYTE ) );
+
1667 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "maskdata", &maskdata_RTvariable ) );
+
1668 RT_CHECK_ERROR( rtVariableSetObject( maskdata_RTvariable, maskdata_RTbuffer ) );
+
1669 std::vector<std::vector<std::vector<bool> > > dummydata;
+
1670 initializeBuffer3D( maskdata_RTbuffer, dummydata );
+
1671
+
1672 //Texture mask size
+
1673 addBuffer( "masksize", masksize_RTbuffer, masksize_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT2, 1 );
+
1674
+
1675 //Texture mask ID
+
1676 addBuffer( "maskID", maskID_RTbuffer, maskID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT, 1 );
+
1677
+
1678 //Texture u,v data
+
1679 addBuffer( "uvdata", uvdata_RTbuffer, uvdata_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT2, 2 );
+
1680
+
1681 //Texture u,v ID
+
1682 addBuffer( "uvID", uvID_RTbuffer, uvID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT, 1 );
+
1683
+
1684 // Radiation Camera Variables
+
1685 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_position", &camera_position_RTvariable ) );
+
1686 RT_CHECK_ERROR( rtVariableSet3f( camera_position_RTvariable, 0.f, 0.f, 0.f ));
+
1687 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_direction", &camera_direction_RTvariable ) );
+
1688 RT_CHECK_ERROR( rtVariableSet2f( camera_direction_RTvariable, 0.f, 0.f ));
+
1689 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_lens_diameter", &camera_lens_diameter_RTvariable ) );
+
1690 RT_CHECK_ERROR( rtVariableSet1f( camera_lens_diameter_RTvariable, 0.f ));
+
1691 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "FOV_aspect_ratio", &FOV_aspect_RTvariable ) );
+
1692 RT_CHECK_ERROR( rtVariableSet1f( FOV_aspect_RTvariable, 1.f ));
+
1693 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_focal_length", &camera_focal_length_RTvariable ) );
+
1694 RT_CHECK_ERROR( rtVariableSet1f( camera_focal_length_RTvariable, 0.f ));
+
1695 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_viewplane_length", &camera_viewplane_length_RTvariable ) );
+
1696 RT_CHECK_ERROR( rtVariableSet1f( camera_viewplane_length_RTvariable, 0.f ));
+
1697 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Ncameras", &Ncameras_RTvariable ) );
+
1698 RT_CHECK_ERROR( rtVariableSet1ui( Ncameras_RTvariable, 0 ));
+
1699 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_ID", &camera_ID_RTvariable ) );
+
1700 RT_CHECK_ERROR( rtVariableSet1ui( camera_ID_RTvariable, 0 ));
+
1701
+
1702 // primitive scattering buffers (cameras)
+
1703 addBuffer( "scatter_buff_top_cam", scatter_buff_top_cam_RTbuffer, scatter_buff_top_cam_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1704 addBuffer( "scatter_buff_bottom_cam", scatter_buff_bottom_cam_RTbuffer, scatter_buff_bottom_cam_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1705
+
1706 /* Hit Programs */
+
1707 RTprogram closest_hit_direct;
+
1708 RTprogram closest_hit_diffuse;
+
1709 RTprogram closest_hit_camera;
+
1710 RTprogram closest_hit_pixel_label;
+
1711 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_direct", &closest_hit_direct ) );
+
1712 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_diffuse", &closest_hit_diffuse ) );
+
1713 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_camera", &closest_hit_camera ) );
+
1714 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_pixel_label", &closest_hit_pixel_label ) );
+
1715
+
1716 /* Initialize Patch Geometry */
+
1717
+
1718 RTprogram patch_intersection_program;
+
1719 RTprogram patch_bounding_box_program;
+
1720
+
1721 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &patch ) );
+
1722
+
1723 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "rectangle_bounds", &patch_bounding_box_program ) );
+
1724 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( patch, patch_bounding_box_program ) );
+
1725 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "rectangle_intersect", &patch_intersection_program ) );
+
1726 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( patch, patch_intersection_program ) );
+
1727
+
1728 /* Create Patch Material */
+
1729
+
1730 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &patch_material ) );
+
1731
+
1732 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_DIRECT, closest_hit_direct ) );
+
1733 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
+
1734 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_CAMERA, closest_hit_camera ) );
+
1735 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
+
1736
+
1737 /* Initialize Triangle Geometry */
+
1738
+
1739 RTprogram triangle_intersection_program;
+
1740 RTprogram triangle_bounding_box_program;
+
1741
+
1742 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &triangle ) );
+
1743
+
1744 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "triangle_bounds", &triangle_bounding_box_program ) );
+
1745 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( triangle, triangle_bounding_box_program ) );
+
1746 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "triangle_intersect", &triangle_intersection_program ) );
+
1747 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( triangle, triangle_intersection_program ) );
+
1748
+
1749 /* Create Triangle Material */
+
1750
+
1751 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &triangle_material ) );
+
1752
+
1753 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_DIRECT, closest_hit_direct ) );
+
1754 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
+
1755 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_CAMERA, closest_hit_camera ) );
+
1756 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
+
1757
+
1758 /* Initialize Disk Geometry */
+
1759
+
1760 RTprogram disk_intersection_program;
+
1761 RTprogram disk_bounding_box_program;
+
1762
+
1763 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &disk ) );
+
1764
+
1765 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "disk_bounds", &disk_bounding_box_program ) );
+
1766 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( disk, disk_bounding_box_program ) );
+
1767 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "disk_intersect", &disk_intersection_program ) );
+
1768 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( disk, disk_intersection_program ) );
+
1769
+
1770 /* Create Disk Material */
+
1771
+
1772 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &disk_material ) );
+
1773
+
1774 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_DIRECT, closest_hit_direct ) );
+
1775 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
+
1776 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_CAMERA, closest_hit_camera ) );
+
1777 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
+
1778
+
1779 /* Initialize Tile Geometry */
+
1780
+
1781 RTprogram tile_intersection_program;
+
1782 RTprogram tile_bounding_box_program;
+
1783
+
1784 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &tile ) );
+
1785
+
1786 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "tile_bounds", &tile_bounding_box_program ) );
+
1787 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( tile, tile_bounding_box_program ) );
+
1788 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "tile_intersect", &tile_intersection_program ) );
+
1789 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( tile, tile_intersection_program ) );
+
1790
+
1791 /* Create Tile Material */
+
1792
+
1793 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &tile_material ) );
+
1794
+
1795 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_DIRECT, closest_hit_direct ) );
+
1796 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
+
1797 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_CAMERA, closest_hit_camera) );
+
1798 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
+
1799
+
1800 /* Initialize Voxel Geometry */
+
1801
+
1802 RTprogram voxel_intersection_program;
+
1803 RTprogram voxel_bounding_box_program;
+
1804
+
1805 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &voxel ) );
+
1806
+
1807 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "voxel_bounds", &voxel_bounding_box_program ) );
+
1808 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( voxel, voxel_bounding_box_program ) );
+
1809 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "voxel_intersect", &voxel_intersection_program ) );
+
1810 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( voxel, voxel_intersection_program ) );
+
1811
+
1812 /* Create Voxel Material */
+
1813
+
1814 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &voxel_material ) );
+
1815
+
1816 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_DIRECT, closest_hit_direct ) );
+
1817 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
+
1818 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_CAMERA, closest_hit_camera ) );
+
1819 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
+
1820
+
1821 /* Initialize Bounding Box Geometry */
+
1822
+
1823 RTprogram bbox_intersection_program;
+
1824 RTprogram bbox_bounding_box_program;
+
1825
+
1826 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &bbox ) );
+
1827
+
1828 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "bbox_bounds", &bbox_bounding_box_program ) );
+
1829 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( bbox, bbox_bounding_box_program ) );
+
1830 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "bbox_intersect", &bbox_intersection_program ) );
+
1831 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( bbox, bbox_intersection_program ) );
+
1832
+
1833 /* Create Bounding Box Material */
+
1834
+
1835 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &bbox_material ) );
+
1836
+
1837 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_DIRECT, closest_hit_direct ) );
+
1838 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
+
1839 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_CAMERA, closest_hit_camera ) );
+
1840 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
+
1841
+
1842 /* Miss Program */
+
1843 RTprogram miss_program_direct;
+
1844 RTprogram miss_program_diffuse;
+
1845 RTprogram miss_program_camera;
+
1846 RTprogram miss_program_pixel_label;
+
1847 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_direct", &miss_program_direct ) );
+
1848 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_DIRECT, miss_program_direct ) );
+
1849 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_diffuse", &miss_program_diffuse ) );
+
1850 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_DIFFUSE, miss_program_diffuse ) );
+
1851 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_camera", &miss_program_camera ) );
+
1852 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_CAMERA, miss_program_camera ) );
+
1853 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_pixel_label", &miss_program_pixel_label ) );
+
1854 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_PIXEL_LABEL, miss_program_pixel_label ) );
+
1855
+
1856 /* Create OptiX Geometry Structures */
+
1857
+
1858 RTtransform transform;
+
1859
+
1860 RTgeometrygroup geometry_group;
+
1861
+
1862 RTgeometryinstance patch_instance;
+
1863 RTgeometryinstance triangle_instance;
+
1864 RTgeometryinstance disk_instance;
+
1865 RTgeometryinstance tile_instance;
+
1866 RTgeometryinstance voxel_instance;
+
1867 RTgeometryinstance bbox_instance;
+
1868
+
1869 /* Create top level group and associated (dummy) acceleration */
+
1870 RT_CHECK_ERROR( rtGroupCreate( OptiX_Context, &top_level_group ) );
+
1871 RT_CHECK_ERROR( rtGroupSetChildCount( top_level_group, 1 ) );
1872
-
1873 /* Create transform node */
-
1874 RT_CHECK_ERROR( rtTransformCreate( OptiX_Context, &transform ) );
-
1875 float m[16];
-
1876 m[0] = 1.f; m[1] = 0; m[2] = 0; m[3] = 0;
-
1877 m[4] = 0.f; m[5] = 1.f; m[6] = 0; m[7] = 0;
-
1878 m[8] = 0.f; m[9] = 0; m[10] = 1.f; m[11] = 0;
-
1879 m[12] = 0.f; m[13] = 0; m[14] = 0; m[15] = 1.f;
-
1880 RT_CHECK_ERROR( rtTransformSetMatrix( transform, 0, m, nullptr ) );
-
1881 RT_CHECK_ERROR( rtGroupSetChild( top_level_group, 0, transform ) );
-
1882
-
1883 /* Create geometry group and associated acceleration*/
-
1884 RT_CHECK_ERROR( rtGeometryGroupCreate( OptiX_Context, &geometry_group ) );
-
1885 RT_CHECK_ERROR( rtGeometryGroupSetChildCount( geometry_group, 6 ) );
-
1886 RT_CHECK_ERROR( rtTransformSetChild( transform, geometry_group ) );
-
1887
-
1888 //create acceleration object for group and specify some build hints
-
1889 RT_CHECK_ERROR( rtAccelerationCreate(OptiX_Context,&geometry_acceleration) );
-
1890 RT_CHECK_ERROR( rtAccelerationSetBuilder(geometry_acceleration,"Trbvh") );
-
1891 RT_CHECK_ERROR( rtAccelerationSetTraverser(geometry_acceleration,"Bvh") );
-
1892 RT_CHECK_ERROR( rtGeometryGroupSetAcceleration( geometry_group, geometry_acceleration) );
-
1893 RT_CHECK_ERROR( rtAccelerationMarkDirty( geometry_acceleration ) );
-
1894
-
1895 /* Create geometry instances */
-
1896 //patches
-
1897 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &patch_instance ) );
-
1898 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( patch_instance, patch ) );
-
1899 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( patch_instance, 1 ) );
-
1900 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( patch_instance, 0, patch_material ) );
-
1901 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 0, patch_instance ) );
-
1902 //triangles
-
1903 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &triangle_instance ) );
-
1904 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( triangle_instance, triangle ) );
-
1905 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( triangle_instance, 1 ) );
-
1906 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( triangle_instance, 0, triangle_material ) );
-
1907 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 1, triangle_instance ) );
-
1908 //disks
-
1909 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &disk_instance ) );
-
1910 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( disk_instance, disk ) );
-
1911 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( disk_instance, 1 ) );
-
1912 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( disk_instance, 0, disk_material ) );
-
1913 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 2, disk_instance ) );
-
1914 //tiles
-
1915 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &tile_instance ) );
-
1916 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( tile_instance, tile ) );
-
1917 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( tile_instance, 1 ) );
-
1918 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( tile_instance, 0, tile_material ) );
-
1919 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 3, tile_instance ) );
-
1920 //voxels
-
1921 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &voxel_instance ) );
-
1922 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( voxel_instance, voxel ) );
-
1923 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( voxel_instance, 1 ) );
-
1924 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( voxel_instance, 0, voxel_material ) );
-
1925 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 4, voxel_instance ) );
-
1926
-
1927 //voxels
-
1928 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &bbox_instance ) );
-
1929 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( bbox_instance, bbox ) );
-
1930 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( bbox_instance, 1 ) );
-
1931 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( bbox_instance, 0, bbox_material ) );
-
1932 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 5, bbox_instance ) );
-
1933
-
1934 /* Set the top_object variable */
-
1935 //NOTE: Not sure exactly where this has to be set
-
1936 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "top_object", &top_object ) );
-
1937 RT_CHECK_ERROR( rtVariableSetObject( top_object, top_level_group ) );
-
1938
-
1939 //random number seed
-
1940 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "random_seed", &random_seed_RTvariable ) );
-
1941 RT_CHECK_ERROR( rtVariableSet1ui( random_seed_RTvariable, std::chrono::system_clock::now().time_since_epoch().count() ) );
-
1942
-
1943 //launch offset
-
1944 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "launch_offset", &launch_offset_RTvariable ) );
-
1945 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, 0 ) );
+
1873 RT_CHECK_ERROR( rtAccelerationCreate( OptiX_Context, &top_level_acceleration ) );
+
1874 RT_CHECK_ERROR( rtAccelerationSetBuilder(top_level_acceleration,"NoAccel") );
+
1875 RT_CHECK_ERROR( rtAccelerationSetTraverser(top_level_acceleration,"NoAccel") );
+
1876 RT_CHECK_ERROR( rtGroupSetAcceleration( top_level_group, top_level_acceleration) );
+
1877
+
1878 /* mark acceleration as dirty */
+
1879 RT_CHECK_ERROR( rtAccelerationMarkDirty( top_level_acceleration ) );
+
1880
+
1881 /* Create transform node */
+
1882 RT_CHECK_ERROR( rtTransformCreate( OptiX_Context, &transform ) );
+
1883 float m[16];
+
1884 m[0] = 1.f; m[1] = 0; m[2] = 0; m[3] = 0;
+
1885 m[4] = 0.f; m[5] = 1.f; m[6] = 0; m[7] = 0;
+
1886 m[8] = 0.f; m[9] = 0; m[10] = 1.f; m[11] = 0;
+
1887 m[12] = 0.f; m[13] = 0; m[14] = 0; m[15] = 1.f;
+
1888 RT_CHECK_ERROR( rtTransformSetMatrix( transform, 0, m, nullptr ) );
+
1889 RT_CHECK_ERROR( rtGroupSetChild( top_level_group, 0, transform ) );
+
1890
+
1891 /* Create geometry group and associated acceleration*/
+
1892 RT_CHECK_ERROR( rtGeometryGroupCreate( OptiX_Context, &geometry_group ) );
+
1893 RT_CHECK_ERROR( rtGeometryGroupSetChildCount( geometry_group, 6 ) );
+
1894 RT_CHECK_ERROR( rtTransformSetChild( transform, geometry_group ) );
+
1895
+
1896 //create acceleration object for group and specify some build hints
+
1897 RT_CHECK_ERROR( rtAccelerationCreate(OptiX_Context,&geometry_acceleration) );
+
1898 RT_CHECK_ERROR( rtAccelerationSetBuilder(geometry_acceleration,"Trbvh") );
+
1899 RT_CHECK_ERROR( rtAccelerationSetTraverser(geometry_acceleration,"Bvh") );
+
1900 RT_CHECK_ERROR( rtGeometryGroupSetAcceleration( geometry_group, geometry_acceleration) );
+
1901 RT_CHECK_ERROR( rtAccelerationMarkDirty( geometry_acceleration ) );
+
1902
+
1903 /* Create geometry instances */
+
1904 //patches
+
1905 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &patch_instance ) );
+
1906 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( patch_instance, patch ) );
+
1907 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( patch_instance, 1 ) );
+
1908 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( patch_instance, 0, patch_material ) );
+
1909 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 0, patch_instance ) );
+
1910 //triangles
+
1911 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &triangle_instance ) );
+
1912 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( triangle_instance, triangle ) );
+
1913 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( triangle_instance, 1 ) );
+
1914 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( triangle_instance, 0, triangle_material ) );
+
1915 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 1, triangle_instance ) );
+
1916 //disks
+
1917 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &disk_instance ) );
+
1918 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( disk_instance, disk ) );
+
1919 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( disk_instance, 1 ) );
+
1920 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( disk_instance, 0, disk_material ) );
+
1921 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 2, disk_instance ) );
+
1922 //tiles
+
1923 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &tile_instance ) );
+
1924 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( tile_instance, tile ) );
+
1925 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( tile_instance, 1 ) );
+
1926 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( tile_instance, 0, tile_material ) );
+
1927 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 3, tile_instance ) );
+
1928 //voxels
+
1929 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &voxel_instance ) );
+
1930 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( voxel_instance, voxel ) );
+
1931 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( voxel_instance, 1 ) );
+
1932 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( voxel_instance, 0, voxel_material ) );
+
1933 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 4, voxel_instance ) );
+
1934
+
1935 //voxels
+
1936 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &bbox_instance ) );
+
1937 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( bbox_instance, bbox ) );
+
1938 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( bbox_instance, 1 ) );
+
1939 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( bbox_instance, 0, bbox_material ) );
+
1940 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 5, bbox_instance ) );
+
1941
+
1942 /* Set the top_object variable */
+
1943 //NOTE: Not sure exactly where this has to be set
+
1944 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "top_object", &top_object ) );
+
1945 RT_CHECK_ERROR( rtVariableSetObject( top_object, top_level_group ) );
1946
-
1947 //maximum scattering depth
-
1948 RT_CHECK_ERROR( rtBufferCreate( OptiX_Context, RT_BUFFER_INPUT, &max_scatters_RTbuffer ) );
-
1949 RT_CHECK_ERROR( rtBufferSetFormat( max_scatters_RTbuffer, RT_FORMAT_UNSIGNED_INT ) );
-
1950 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "max_scatters", &max_scatters_RTvariable ) );
-
1951 RT_CHECK_ERROR( rtVariableSetObject( max_scatters_RTvariable, max_scatters_RTbuffer ) );
-
1952 zeroBuffer1D( max_scatters_RTbuffer, 1 );
-
1953
-
1954 // RTsize device_memory;
-
1955 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
-
1956
-
1957 // device_memory *= 1e-6;
-
1958 // if( device_memory < 1000 ){
-
1959 // printf("available device memory at end of OptiX initialization: %6.3f MB\n",device_memory);
-
1960 // }else{
-
1961 // printf("available device memory at end of OptiX initialization: %6.3f GB\n",device_memory*1e-3);
-
1962 // }
-
1963
-
1964}
-
1965
-
- -
1967 updateGeometry( context->getAllUUIDs() );
-
1968}
-
-
1969
-
-
1970void RadiationModel::updateGeometry( const std::vector<uint>& UUIDs ){
+
1947 //random number seed
+
1948 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "random_seed", &random_seed_RTvariable ) );
+
1949 RT_CHECK_ERROR( rtVariableSet1ui( random_seed_RTvariable, std::chrono::system_clock::now().time_since_epoch().count() ) );
+
1950
+
1951 //launch offset
+
1952 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "launch_offset", &launch_offset_RTvariable ) );
+
1953 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, 0 ) );
+
1954
+
1955 //maximum scattering depth
+
1956 RT_CHECK_ERROR( rtBufferCreate( OptiX_Context, RT_BUFFER_INPUT, &max_scatters_RTbuffer ) );
+
1957 RT_CHECK_ERROR( rtBufferSetFormat( max_scatters_RTbuffer, RT_FORMAT_UNSIGNED_INT ) );
+
1958 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "max_scatters", &max_scatters_RTvariable ) );
+
1959 RT_CHECK_ERROR( rtVariableSetObject( max_scatters_RTvariable, max_scatters_RTbuffer ) );
+
1960 zeroBuffer1D( max_scatters_RTbuffer, 1 );
+
1961
+
1962 // RTsize device_memory;
+
1963 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
+
1964
+
1965 // device_memory *= 1e-6;
+
1966 // if( device_memory < 1000 ){
+
1967 // printf("available device memory at end of OptiX initialization: %6.3f MB\n",device_memory);
+
1968 // }else{
+
1969 // printf("available device memory at end of OptiX initialization: %6.3f GB\n",device_memory*1e-3);
+
1970 // }
1971
-
1972 if( message_flag ){
-
1973 std::cout << "Updating geometry in radiation transport model..." << std::flush;
-
1974 }
-
1975
-
1976 for ( auto &band : radiation_bands ) {
-
1977 band.second.radiativepropertiesinitialized = false;
-
1978 }
+
1972}
+
1973
+
+ +
1975 updateGeometry( context->getAllUUIDs() );
+
1976}
+
+
1977
+
+
1978void RadiationModel::updateGeometry( const std::vector<uint>& UUIDs ){
1979
-
1980 context_UUIDs = UUIDs;
-
1981
-
1982 for( int u=context_UUIDs.size()-1; u>=0; u-- ){
-
1983 float area = context->getPrimitiveArea(context_UUIDs.at(u));
-
1984 if( !context->doesPrimitiveExist( context_UUIDs.at(u) ) ){
-
1985 context_UUIDs.erase( context_UUIDs.begin()+u );
-
1986 }else if( area==0 || area!=area ){
-
1987 context_UUIDs.erase( context_UUIDs.begin()+u );
-
1988 }
-
1989 }
-
1990
-
1991 //--- Make Bounding Patches ---//
-
1992
-
1993 //determine domain bounding sphere
-
1994 float sphere_radius;
-
1995 vec3 sphere_center;
-
1996 context->getDomainBoundingSphere( sphere_center, sphere_radius );
-
1997
-
1998 rtVariableSet1f( bound_sphere_radius_RTvariable, sphere_radius );
-
1999 rtVariableSet3f( bound_sphere_center_RTvariable, sphere_center.x, sphere_center.y, sphere_center.z );
+
1980 if( message_flag ){
+
1981 std::cout << "Updating geometry in radiation transport model..." << std::flush;
+
1982 }
+
1983
+
1984 for ( auto &band : radiation_bands ) {
+
1985 band.second.radiativepropertiesinitialized = false;
+
1986 }
+
1987
+
1988 context_UUIDs = UUIDs;
+
1989
+
1990 for( int u=context_UUIDs.size()-1; u>=0; u-- ){
+
1991 float area = context->getPrimitiveArea(context_UUIDs.at(u));
+
1992 if( !context->doesPrimitiveExist( context_UUIDs.at(u) ) ){
+
1993 context_UUIDs.erase( context_UUIDs.begin()+u );
+
1994 }else if( area==0 || area!=area ){
+
1995 context_UUIDs.erase( context_UUIDs.begin()+u );
+
1996 }
+
1997 }
+
1998
+
1999 //--- Make Bounding Patches ---//
2000
-
2001 //--- Populate Primitive Geometry Buffers ---//
-
2002
-
2003 size_t Nprimitives = context_UUIDs.size(); //Number of primitives
-
2004
-
2005 //transformation matrix buffer - size=Nobjects
-
2006 std::vector<std::vector<float> > m_global;
-
2007
-
2008 //primitive type buffer - size=Nobjects
-
2009 std::vector<uint> ptype_global;
+
2001 //determine domain bounding sphere
+
2002 float sphere_radius;
+
2003 vec3 sphere_center;
+
2004 context->getDomainBoundingSphere( sphere_center, sphere_radius );
+
2005
+
2006 rtVariableSet1f( bound_sphere_radius_RTvariable, sphere_radius );
+
2007 rtVariableSet3f( bound_sphere_center_RTvariable, sphere_center.x, sphere_center.y, sphere_center.z );
+
2008
+
2009 //--- Populate Primitive Geometry Buffers ---//
2010
-
2011 //primitive area buffer - size=Nobjects
-
2012 std::vector<float> area_global;
-
2013
-
2014 //primitive UUID buffers - total size of all combined is Nobjects
-
2015 std::vector<uint> patch_UUID;
-
2016 std::vector<uint> triangle_UUID;
-
2017 std::vector<uint> disk_UUID;
-
2018 std::vector<uint> tile_UUID;
-
2019 std::vector<uint> voxel_UUID;
-
2020
-
2021 //twosided flag buffer - size=Nobjects
-
2022 std::vector<char> twosided_flag_global;
-
2023
-
2024 //primitive geometry specification buffers
-
2025 std::vector<std::vector<optix::float3> > patch_vertices;
-
2026 std::vector<std::vector<optix::float3> > triangle_vertices;
-
2027 std::vector<std::vector<optix::float3> > disk_vertices;
-
2028 std::vector<std::vector<optix::float3> > tile_vertices;
-
2029 std::vector<std::vector<optix::float3> > voxel_vertices;
-
2030
-
2031 //number of patch subdivisions for each tile - size is same as tile_vertices
-
2032 std::vector<optix::int2> object_subdivisions;
-
2033
-
2034 std::vector<uint> objID_all = context->getAllObjectIDs();
-
2035
-
2036 //ID of object corresponding to each primitive - size Nprimitives
-
2037 std::vector<uint> objectID;
-
2038 objectID.resize(Nprimitives);
-
2039
-
2040 std::size_t patch_count = 0;
-
2041 std::size_t triangle_count = 0;
-
2042 std::size_t disk_count = 0;
-
2043 std::size_t tile_count = 0;
-
2044 std::size_t voxel_count = 0;
-
2045
-
2046 area_global.resize(Nprimitives);
+
2011 size_t Nprimitives = context_UUIDs.size(); //Number of primitives
+
2012
+
2013 //transformation matrix buffer - size=Nobjects
+
2014 std::vector<std::vector<float> > m_global;
+
2015
+
2016 //primitive type buffer - size=Nobjects
+
2017 std::vector<uint> ptype_global;
+
2018
+
2019 //primitive area buffer - size=Nobjects
+
2020 std::vector<float> area_global;
+
2021
+
2022 //primitive UUID buffers - total size of all combined is Nobjects
+
2023 std::vector<uint> patch_UUID;
+
2024 std::vector<uint> triangle_UUID;
+
2025 std::vector<uint> disk_UUID;
+
2026 std::vector<uint> tile_UUID;
+
2027 std::vector<uint> voxel_UUID;
+
2028
+
2029 //twosided flag buffer - size=Nobjects
+
2030 std::vector<char> twosided_flag_global;
+
2031
+
2032 //primitive geometry specification buffers
+
2033 std::vector<std::vector<optix::float3> > patch_vertices;
+
2034 std::vector<std::vector<optix::float3> > triangle_vertices;
+
2035 std::vector<std::vector<optix::float3> > disk_vertices;
+
2036 std::vector<std::vector<optix::float3> > tile_vertices;
+
2037 std::vector<std::vector<optix::float3> > voxel_vertices;
+
2038
+
2039 //number of patch subdivisions for each tile - size is same as tile_vertices
+
2040 std::vector<optix::int2> object_subdivisions;
+
2041
+
2042 std::vector<uint> objID_all = context->getAllObjectIDs();
+
2043
+
2044 //ID of object corresponding to each primitive - size Nprimitives
+
2045 std::vector<uint> objectID;
+
2046 objectID.resize(Nprimitives);
2047
-
2048 primitiveID.resize(0);
-
2049
-
2050 //Create a vector of primitive pointers 'primitives' (note: only add one pointer for compound objects)
-
2051 uint objID = 0;
-
2052 uint ID = 99999;
-
2053 for( std::size_t u=0; u<Nprimitives; u++ ){
-
2054
-
2055 uint p = context_UUIDs.at(u);
-
2056
-
2057 //primitve area
-
2058 area_global.at(u) = context->getPrimitiveArea(p);
-
2059
-
2060 uint parentID = context->getPrimitiveParentObjectID(p);
-
2061
-
2062 if( ID!=parentID || parentID==0 || context->getObjectPointer(parentID)->getObjectType()!=helios::OBJECT_TYPE_TILE ){//if this is a new object, or primitive does not belong to an object
-
2063 primitiveID.push_back( u );
-
2064 ID = parentID;
-
2065 objID++;
-
2066 }else{
-
2067 ID = parentID;
-
2068 }
+
2048 std::size_t patch_count = 0;
+
2049 std::size_t triangle_count = 0;
+
2050 std::size_t disk_count = 0;
+
2051 std::size_t tile_count = 0;
+
2052 std::size_t voxel_count = 0;
+
2053
+
2054 area_global.resize(Nprimitives);
+
2055
+
2056 primitiveID.resize(0);
+
2057
+
2058 //Create a vector of primitive pointers 'primitives' (note: only add one pointer for compound objects)
+
2059 uint objID = 0;
+
2060 uint ID = 99999;
+
2061 for( std::size_t u=0; u<Nprimitives; u++ ){
+
2062
+
2063 uint p = context_UUIDs.at(u);
+
2064
+
2065 //primitve area
+
2066 area_global.at(u) = context->getPrimitiveArea(p);
+
2067
+
2068 uint parentID = context->getPrimitiveParentObjectID(p);
2069
-
2070 assert(objID>0);
-
2071
-
2072 objectID.at(u) = objID-1;
-
2073
-
2074 }
-
2075
-
2076 //Nobjects is the number of isolated primitives plus the number of compound objects (all primitives inside and object combined only counts as one element)
-
2077 size_t Nobjects = primitiveID.size();
-
2078
-
2079 m_global.resize(Nobjects);
-
2080 ptype_global.resize(Nobjects);
-
2081 twosided_flag_global.resize(Nobjects);//initialize to be two-sided
-
2082 for( size_t i=0; i<Nobjects; i++ ){
-
2083 twosided_flag_global.at(i) = 1;
-
2084 }
-
2085
-
2086 //Populate attributes for each primitive in the pointer vector 'primitives'
-
2087 for( std::size_t u=0; u<Nobjects; u++ ){
-
2088
-
2089 uint p = context_UUIDs.at(primitiveID.at(u));
-
2090
-
2091 //transformation matrix
-
2092 float m[16];
+
2070 if( ID!=parentID || parentID==0 || context->getObjectPointer(parentID)->getObjectType()!=helios::OBJECT_TYPE_TILE ){//if this is a new object, or primitive does not belong to an object
+
2071 primitiveID.push_back( u );
+
2072 ID = parentID;
+
2073 objID++;
+
2074 }else{
+
2075 ID = parentID;
+
2076 }
+
2077
+
2078 assert(objID>0);
+
2079
+
2080 objectID.at(u) = objID-1;
+
2081
+
2082 }
+
2083
+
2084 //Nobjects is the number of isolated primitives plus the number of compound objects (all primitives inside and object combined only counts as one element)
+
2085 size_t Nobjects = primitiveID.size();
+
2086
+
2087 m_global.resize(Nobjects);
+
2088 ptype_global.resize(Nobjects);
+
2089 twosided_flag_global.resize(Nobjects);//initialize to be two-sided
+
2090 for( size_t i=0; i<Nobjects; i++ ){
+
2091 twosided_flag_global.at(i) = 1;
+
2092 }
2093
-
2094 //primitive type
-
2095 helios::PrimitiveType type = context->getPrimitiveType(p);
-
2096 ptype_global.at(u) = type;
-
2097
-
2098 assert( ptype_global.at(u)>=0 && ptype_global.at(u)<=4 );
-
2099
-
2100 //primitive twosided flag
-
2101 if( context->doesPrimitiveDataExist( p,"twosided_flag") ){
-
2102 uint flag;
-
2103 context->getPrimitiveData( p,"twosided_flag",flag);
-
2104 twosided_flag_global.at(u) = char(flag);
-
2105 }
-
2106
-
2107 uint parentID = context->getPrimitiveParentObjectID(p);
-
2108
-
2109 if( parentID>0 && context->getObjectPointer(parentID)->getObjectType()==helios::OBJECT_TYPE_TILE ){//tile objects
-
2110
-
2111 ptype_global.at(u) = 3;
-
2112
-
2113 context->getObjectPointer(parentID)->getTransformationMatrix(m);
+
2094 //Populate attributes for each primitive in the pointer vector 'primitives'
+
2095 for( std::size_t u=0; u<Nobjects; u++ ){
+
2096
+
2097 uint p = context_UUIDs.at(primitiveID.at(u));
+
2098
+
2099 //transformation matrix
+
2100 float m[16];
+
2101
+
2102 //primitive type
+
2103 helios::PrimitiveType type = context->getPrimitiveType(p);
+
2104 ptype_global.at(u) = type;
+
2105
+
2106 assert( ptype_global.at(u)>=0 && ptype_global.at(u)<=4 );
+
2107
+
2108 //primitive twosided flag
+
2109 if( context->doesPrimitiveDataExist( p,"twosided_flag") ){
+
2110 uint flag;
+
2111 context->getPrimitiveData( p,"twosided_flag",flag);
+
2112 twosided_flag_global.at(u) = char(flag);
+
2113 }
2114
-
2115 m_global.at(u).resize(16);
-
2116 for( uint i=0; i<16; i++ ){
-
2117 m_global.at(u).at(i) = m[i];
-
2118 }
-
2119
-
2120 std::vector<vec3> vertices = context->getTileObjectPointer(parentID)->getVertices();
-
2121 std::vector<optix::float3> v(4);
-
2122 v.at(0) = optix::make_float3(vertices.at(0).x,vertices.at(0).y,vertices.at(0).z);
-
2123 v.at(1) = optix::make_float3(vertices.at(1).x,vertices.at(1).y,vertices.at(1).z);
-
2124 v.at(2) = optix::make_float3(vertices.at(2).x,vertices.at(2).y,vertices.at(2).z);
-
2125 v.at(3) = optix::make_float3(vertices.at(3).x,vertices.at(3).y,vertices.at(3).z);
-
2126 tile_vertices.push_back(v);
+
2115 uint parentID = context->getPrimitiveParentObjectID(p);
+
2116
+
2117 if( parentID>0 && context->getObjectPointer(parentID)->getObjectType()==helios::OBJECT_TYPE_TILE ){//tile objects
+
2118
+
2119 ptype_global.at(u) = 3;
+
2120
+
2121 context->getObjectPointer(parentID)->getTransformationMatrix(m);
+
2122
+
2123 m_global.at(u).resize(16);
+
2124 for( uint i=0; i<16; i++ ){
+
2125 m_global.at(u).at(i) = m[i];
+
2126 }
2127
-
2128 helios::int2 subdiv = context->getTileObjectPointer(parentID)->getSubdivisionCount();
-
2129
-
2130 object_subdivisions.push_back( optix::make_int2(subdiv.x,subdiv.y) );
-
2131
-
2132 tile_UUID.push_back( primitiveID.at(u) );
-
2133 tile_count ++;
-
2134
-
2135 }else if( type == helios::PRIMITIVE_TYPE_PATCH ){ //patches
-
2136
-
2137 context->getPrimitiveTransformationMatrix( p,m);
-
2138
-
2139 m_global.at(u).resize(16);
-
2140 for( uint i=0; i<16; i++ ){
-
2141 m_global.at(u).at(i) = m[i];
-
2142 }
-
2143
-
2144 std::vector<vec3> vertices = context->getPrimitiveVertices(p);
-
2145 std::vector<optix::float3> v(4);
-
2146 v.at(0) = optix::make_float3(vertices.at(0).x,vertices.at(0).y,vertices.at(0).z);
-
2147 v.at(1) = optix::make_float3(vertices.at(1).x,vertices.at(1).y,vertices.at(1).z);
-
2148 v.at(2) = optix::make_float3(vertices.at(2).x,vertices.at(2).y,vertices.at(2).z);
-
2149 v.at(3) = optix::make_float3(vertices.at(3).x,vertices.at(3).y,vertices.at(3).z);
-
2150 patch_vertices.push_back(v);
-
2151 object_subdivisions.push_back( optix::make_int2(1,1) );
-
2152 patch_UUID.push_back( primitiveID.at(u) );
-
2153 patch_count ++;
-
2154 }else if( type == helios::PRIMITIVE_TYPE_TRIANGLE ){ //triangles
-
2155
- -
2157
-
2158 m_global.at(u).resize(16);
-
2159 for( uint i=0; i<16; i++ ){
-
2160 m_global.at(u).at(i) = m[i];
-
2161 }
-
2162
-
2163 std::vector<vec3> vertices = context->getPrimitiveVertices(p);
-
2164 std::vector<optix::float3> v(3);
-
2165 v.at(0) = optix::make_float3(vertices.at(0).x,vertices.at(0).y,vertices.at(0).z);
-
2166 v.at(1) = optix::make_float3(vertices.at(1).x,vertices.at(1).y,vertices.at(1).z);
-
2167 v.at(2) = optix::make_float3(vertices.at(2).x,vertices.at(2).y,vertices.at(2).z);
-
2168 triangle_vertices.push_back(v);
-
2169 object_subdivisions.push_back( optix::make_int2(1,1) );
-
2170 triangle_UUID.push_back( primitiveID.at(u) );
-
2171 triangle_count ++;
-
2172 }else if( type == helios::PRIMITIVE_TYPE_VOXEL ){ //voxels
-
2173
- -
2175
-
2176 m_global.at(u).resize(16);
-
2177 for( uint i=0; i<16; i++ ){
-
2178 m_global.at(u).at(i) = m[i];
-
2179 }
-
2180
-
2181 helios::vec3 center = context->getVoxelCenter(p);
-
2182 helios::vec3 size = context->getVoxelSize(p);
-
2183 std::vector<optix::float3> v;
-
2184 v.push_back( optix::make_float3(center.x-0.5f*size.x, center.y-0.5f*size.y, center.z-0.5f*size.z ) );
-
2185 v.push_back( optix::make_float3(center.x+0.5f*size.x, center.y+0.5f*size.y, center.z+0.5f*size.z ) );
-
2186 voxel_vertices.push_back(v);
-
2187 object_subdivisions.push_back( optix::make_int2(1,1) );
-
2188 voxel_UUID.push_back( primitiveID.at(u) );
-
2189 voxel_count ++;
-
2190 }
-
2191
-
2192 }
-
2193
-
2194 //Texture mask data
-
2195 std::vector<std::vector<std::vector<bool> > > maskdata;
-
2196 std::map<std::string,uint> maskname;
-
2197 std::vector<optix::int2> masksize;
-
2198 std::vector<int> maskID;
-
2199 std::vector<std::vector<optix::float2> > uvdata;
-
2200 std::vector<int> uvID;
-
2201 maskID.resize(Nobjects);
-
2202 uvID.resize(Nobjects);
-
2203
-
2204 for( size_t u=0; u<Nobjects; u++ ){
-
2205
-
2206 uint p = context_UUIDs.at(primitiveID.at(u));
-
2207
-
2208 std::string maskfile = context->getPrimitiveTextureFile(p);
-
2209
-
2210 uint parentID = context->getPrimitiveParentObjectID(p);
+
2128 std::vector<vec3> vertices = context->getTileObjectPointer(parentID)->getVertices();
+
2129 std::vector<optix::float3> v(4);
+
2130 v.at(0) = optix::make_float3(vertices.at(0).x,vertices.at(0).y,vertices.at(0).z);
+
2131 v.at(1) = optix::make_float3(vertices.at(1).x,vertices.at(1).y,vertices.at(1).z);
+
2132 v.at(2) = optix::make_float3(vertices.at(2).x,vertices.at(2).y,vertices.at(2).z);
+
2133 v.at(3) = optix::make_float3(vertices.at(3).x,vertices.at(3).y,vertices.at(3).z);
+
2134 tile_vertices.push_back(v);
+
2135
+
2136 helios::int2 subdiv = context->getTileObjectPointer(parentID)->getSubdivisionCount();
+
2137
+
2138 object_subdivisions.push_back( optix::make_int2(subdiv.x,subdiv.y) );
+
2139
+
2140 tile_UUID.push_back( primitiveID.at(u) );
+
2141 tile_count ++;
+
2142
+
2143 }else if( type == helios::PRIMITIVE_TYPE_PATCH ){ //patches
+
2144
+
2145 context->getPrimitiveTransformationMatrix( p,m);
+
2146
+
2147 m_global.at(u).resize(16);
+
2148 for( uint i=0; i<16; i++ ){
+
2149 m_global.at(u).at(i) = m[i];
+
2150 }
+
2151
+
2152 std::vector<vec3> vertices = context->getPrimitiveVertices(p);
+
2153 std::vector<optix::float3> v(4);
+
2154 v.at(0) = optix::make_float3(vertices.at(0).x,vertices.at(0).y,vertices.at(0).z);
+
2155 v.at(1) = optix::make_float3(vertices.at(1).x,vertices.at(1).y,vertices.at(1).z);
+
2156 v.at(2) = optix::make_float3(vertices.at(2).x,vertices.at(2).y,vertices.at(2).z);
+
2157 v.at(3) = optix::make_float3(vertices.at(3).x,vertices.at(3).y,vertices.at(3).z);
+
2158 patch_vertices.push_back(v);
+
2159 object_subdivisions.push_back( optix::make_int2(1,1) );
+
2160 patch_UUID.push_back( primitiveID.at(u) );
+
2161 patch_count ++;
+
2162 }else if( type == helios::PRIMITIVE_TYPE_TRIANGLE ){ //triangles
+
2163
+ +
2165
+
2166 m_global.at(u).resize(16);
+
2167 for( uint i=0; i<16; i++ ){
+
2168 m_global.at(u).at(i) = m[i];
+
2169 }
+
2170
+
2171 std::vector<vec3> vertices = context->getPrimitiveVertices(p);
+
2172 std::vector<optix::float3> v(3);
+
2173 v.at(0) = optix::make_float3(vertices.at(0).x,vertices.at(0).y,vertices.at(0).z);
+
2174 v.at(1) = optix::make_float3(vertices.at(1).x,vertices.at(1).y,vertices.at(1).z);
+
2175 v.at(2) = optix::make_float3(vertices.at(2).x,vertices.at(2).y,vertices.at(2).z);
+
2176 triangle_vertices.push_back(v);
+
2177 object_subdivisions.push_back( optix::make_int2(1,1) );
+
2178 triangle_UUID.push_back( primitiveID.at(u) );
+
2179 triangle_count ++;
+
2180 }else if( type == helios::PRIMITIVE_TYPE_VOXEL ){ //voxels
+
2181
+ +
2183
+
2184 m_global.at(u).resize(16);
+
2185 for( uint i=0; i<16; i++ ){
+
2186 m_global.at(u).at(i) = m[i];
+
2187 }
+
2188
+
2189 helios::vec3 center = context->getVoxelCenter(p);
+
2190 helios::vec3 size = context->getVoxelSize(p);
+
2191 std::vector<optix::float3> v;
+
2192 v.push_back( optix::make_float3(center.x-0.5f*size.x, center.y-0.5f*size.y, center.z-0.5f*size.z ) );
+
2193 v.push_back( optix::make_float3(center.x+0.5f*size.x, center.y+0.5f*size.y, center.z+0.5f*size.z ) );
+
2194 voxel_vertices.push_back(v);
+
2195 object_subdivisions.push_back( optix::make_int2(1,1) );
+
2196 voxel_UUID.push_back( primitiveID.at(u) );
+
2197 voxel_count ++;
+
2198 }
+
2199
+
2200 }
+
2201
+
2202 //Texture mask data
+
2203 std::vector<std::vector<std::vector<bool> > > maskdata;
+
2204 std::map<std::string,uint> maskname;
+
2205 std::vector<optix::int2> masksize;
+
2206 std::vector<int> maskID;
+
2207 std::vector<std::vector<optix::float2> > uvdata;
+
2208 std::vector<int> uvID;
+
2209 maskID.resize(Nobjects);
+
2210 uvID.resize(Nobjects);
2211
-
2212 if( context->getPrimitiveType(p)==PRIMITIVE_TYPE_VOXEL || maskfile.size()==0 || !context->primitiveTextureHasTransparencyChannel(p) ){ //does not have texture transparency
+
2212 for( size_t u=0; u<Nobjects; u++ ){
2213
-
2214 maskID.at(u) = -1;
-
2215 uvID.at(u) = -1;
-
2216
-
2217 }else{
-
2218
-
2219 // texture mask data //
-
2220
-
2221 //Check if this mask has already been added
-
2222 if( maskname.find(maskfile) != maskname.end() ){ //has already been added
-
2223 uint ID = maskname.at(maskfile);
-
2224 maskID.at(u) = ID;
-
2225 }else{ //mask has not been added
+
2214 uint p = context_UUIDs.at(primitiveID.at(u));
+
2215
+
2216 std::string maskfile = context->getPrimitiveTextureFile(p);
+
2217
+
2218 uint parentID = context->getPrimitiveParentObjectID(p);
+
2219
+
2220 if( context->getPrimitiveType(p)==PRIMITIVE_TYPE_VOXEL || maskfile.size()==0 || !context->primitiveTextureHasTransparencyChannel(p) ){ //does not have texture transparency
+
2221
+
2222 maskID.at(u) = -1;
+
2223 uvID.at(u) = -1;
+
2224
+
2225 }else{
2226
-
2227 uint ID = maskdata.size();
-
2228 maskID.at(u) = ID;
-
2229 maskname[maskfile] = maskdata.size();
-
2230 maskdata.push_back( *context->getPrimitiveTextureTransparencyData(p) );
-
2231 auto sy = maskdata.back().size();
-
2232 auto sx = maskdata.back().front().size();
-
2233 masksize.push_back( optix::make_int2(sx,sy) );
-
2234 }
-
2235
-
2236 // uv coordinates //
-
2237 std::vector<vec2> uv;
-
2238
-
2239 if( parentID==0 || context->getObjectPointer(parentID)->getObjectType()!=helios::OBJECT_TYPE_TILE ){ //primitives
-
2240 uv = context->getPrimitiveTextureUV(p);
-
2241 }
-
2242
-
2243 if( !uv.empty() ){ //has custom (u,v) coordinates
-
2244 std::vector<optix::float2> uvf2;
-
2245 uvf2.resize(4);
-
2246 //first index if uvf2 is the minimum (u,v) coordinate, second index is the size of the (u,v) rectangle in x- and y-directions.
-
2247
-
2248 for( int i=0; i<uv.size(); i++ ){
-
2249 uvf2.at(i) = optix::make_float2(uv.at(i).x, uv.at(i).y);
-
2250 }
-
2251 if( uv.size()==3 ){
-
2252 uvf2.at(3) = optix::make_float2(0,0);
-
2253 }
-
2254 uvdata.push_back( uvf2 );
-
2255 uvID.at(u) = uvdata.size()-1;
-
2256 }else{ //DOES NOT have custom (u,v) coordinates
-
2257 uvID.at(u) = -1;
-
2258 }
-
2259
-
2260 }
-
2261 }
-
2262
-
2263 int2 size_max(0,0);
-
2264 for( int t=0; t<maskdata.size(); t++ ){
-
2265 int2 sz( maskdata.at(t).front().size(), maskdata.at(t).size() );
-
2266 if( sz.x>size_max.x ){
-
2267 size_max.x = sz.x;
+
2227 // texture mask data //
+
2228
+
2229 //Check if this mask has already been added
+
2230 if( maskname.find(maskfile) != maskname.end() ){ //has already been added
+
2231 uint ID = maskname.at(maskfile);
+
2232 maskID.at(u) = ID;
+
2233 }else{ //mask has not been added
+
2234
+
2235 uint ID = maskdata.size();
+
2236 maskID.at(u) = ID;
+
2237 maskname[maskfile] = maskdata.size();
+
2238 maskdata.push_back( *context->getPrimitiveTextureTransparencyData(p) );
+
2239 auto sy = maskdata.back().size();
+
2240 auto sx = maskdata.back().front().size();
+
2241 masksize.push_back( optix::make_int2(sx,sy) );
+
2242 }
+
2243
+
2244 // uv coordinates //
+
2245 std::vector<vec2> uv;
+
2246
+
2247 if( parentID==0 || context->getObjectPointer(parentID)->getObjectType()!=helios::OBJECT_TYPE_TILE ){ //primitives
+
2248 uv = context->getPrimitiveTextureUV(p);
+
2249 }
+
2250
+
2251 if( !uv.empty() ){ //has custom (u,v) coordinates
+
2252 std::vector<optix::float2> uvf2;
+
2253 uvf2.resize(4);
+
2254 //first index if uvf2 is the minimum (u,v) coordinate, second index is the size of the (u,v) rectangle in x- and y-directions.
+
2255
+
2256 for( int i=0; i<uv.size(); i++ ){
+
2257 uvf2.at(i) = optix::make_float2(uv.at(i).x, uv.at(i).y);
+
2258 }
+
2259 if( uv.size()==3 ){
+
2260 uvf2.at(3) = optix::make_float2(0,0);
+
2261 }
+
2262 uvdata.push_back( uvf2 );
+
2263 uvID.at(u) = uvdata.size()-1;
+
2264 }else{ //DOES NOT have custom (u,v) coordinates
+
2265 uvID.at(u) = -1;
+
2266 }
+
2267
2268 }
-
2269 if( sz.y>size_max.y ){
-
2270 size_max.y = sz.y;
-
2271 }
-
2272 }
-
2273
-
2274 for( int t=0; t<maskdata.size(); t++ ){
-
2275 maskdata.at(t).resize(size_max.y);
-
2276 for( int j=0; j<size_max.y; j++ ){
-
2277 maskdata.at(t).at(j).resize(size_max.x);
-
2278 }
-
2279 }
-
2280
-
2281 initializeBuffer3D( maskdata_RTbuffer, maskdata );
-
2282 initializeBuffer1Dint2( masksize_RTbuffer, masksize );
-
2283 initializeBuffer1Di( maskID_RTbuffer, maskID );
-
2284
-
2285 initializeBuffer2Dfloat2( uvdata_RTbuffer, uvdata );
-
2286 initializeBuffer1Di( uvID_RTbuffer, uvID );
-
2287
-
2288 //Bounding box
-
2289 helios::vec2 xbounds, ybounds, zbounds;
-
2290 context->getDomainBoundingBox( xbounds, ybounds, zbounds );
-
2291
-
2292 if( periodic_flag.x==1 || periodic_flag.y ==1 ) {
-
2293 if (!cameras.empty()) {
-
2294 for (auto &camera: cameras) {
-
2295 vec3 camerapos = camera.second.position;
-
2296 if (camerapos.x < xbounds.x || camerapos.x > xbounds.y || camerapos.y < ybounds.x || camerapos.y > ybounds.y) {
-
2297 std::cout << "WARNING (RadiationModel::updateGeometry): camera position is outside of the domain bounding box. Disabling periodic boundary conditions." << std::endl;
-
2298 periodic_flag.x = 0;
-
2299 periodic_flag.y = 0;
-
2300 break;
-
2301 }
-
2302 if (camerapos.z < zbounds.x) {
-
2303 zbounds.x = camerapos.z;
-
2304 }
-
2305 if (camerapos.z > zbounds.y) {
-
2306 zbounds.y = camerapos.z;
-
2307 }
-
2308 }
-
2309 }
-
2310 }
-
2311
-
2312 xbounds.x -= 1e-5;
-
2313 xbounds.y += 1e-5;
-
2314 ybounds.x -= 1e-5;
-
2315 ybounds.y += 1e-5;
-
2316 zbounds.x -= 1e-5;
-
2317 zbounds.y += 1e-5;
-
2318
-
2319 std::vector<uint> bbox_UUID;
-
2320 int bbox_face_count = 0;
-
2321
-
2322 std::vector<std::vector<optix::float3> > bbox_vertices;
-
2323
-
2324 //primitive type
-
2325
-
2326 std::vector<optix::float3> v;
-
2327 v.resize(4);
-
2328
-
2329 if( periodic_flag.x==1 ){
-
2330
-
2331 // -x facing
-
2332 v.at(0) = optix::make_float3(xbounds.x,ybounds.x,zbounds.x);
-
2333 v.at(1) = optix::make_float3(xbounds.x,ybounds.y,zbounds.x);
-
2334 v.at(2) = optix::make_float3(xbounds.x,ybounds.y,zbounds.y);
-
2335 v.at(3) = optix::make_float3(xbounds.x,ybounds.x,zbounds.y);
-
2336 bbox_vertices.push_back(v);
-
2337 bbox_UUID.push_back(Nprimitives+bbox_face_count);
-
2338 objectID.push_back( Nobjects+bbox_face_count );
-
2339 ptype_global.push_back(5);
-
2340 bbox_face_count++;
-
2341
-
2342 // +x facing
-
2343 v.at(0) = optix::make_float3(xbounds.y,ybounds.x,zbounds.x);
-
2344 v.at(1) = optix::make_float3(xbounds.y,ybounds.y,zbounds.x);
-
2345 v.at(2) = optix::make_float3(xbounds.y,ybounds.y,zbounds.y);
-
2346 v.at(3) = optix::make_float3(xbounds.y,ybounds.x,zbounds.y);
-
2347 bbox_vertices.push_back(v);
-
2348 bbox_UUID.push_back(Nprimitives+bbox_face_count);
-
2349 objectID.push_back( Nobjects+bbox_face_count );
-
2350 ptype_global.push_back(5);
-
2351 bbox_face_count++;
-
2352
-
2353 }
-
2354 if( periodic_flag.y==1 ){
-
2355
-
2356 // -y facing
-
2357 v.at(0) = optix::make_float3(xbounds.x,ybounds.x,zbounds.x);
-
2358 v.at(1) = optix::make_float3(xbounds.y,ybounds.x,zbounds.x);
-
2359 v.at(2) = optix::make_float3(xbounds.y,ybounds.x,zbounds.y);
-
2360 v.at(3) = optix::make_float3(xbounds.x,ybounds.x,zbounds.y);
-
2361 bbox_vertices.push_back(v);
-
2362 bbox_UUID.push_back(Nprimitives+bbox_face_count);
-
2363 objectID.push_back( Nobjects+bbox_face_count );
-
2364 ptype_global.push_back(5);
-
2365 bbox_face_count++;
-
2366
-
2367 // +y facing
-
2368 v.at(0) = optix::make_float3(xbounds.x,ybounds.y,zbounds.x);
-
2369 v.at(1) = optix::make_float3(xbounds.y,ybounds.y,zbounds.x);
-
2370 v.at(2) = optix::make_float3(xbounds.y,ybounds.y,zbounds.y);
-
2371 v.at(3) = optix::make_float3(xbounds.x,ybounds.y,zbounds.y);
-
2372 bbox_vertices.push_back(v);
-
2373 bbox_UUID.push_back(Nprimitives+bbox_face_count);
-
2374 objectID.push_back( Nobjects+bbox_face_count );
-
2375 ptype_global.push_back(5);
-
2376 bbox_face_count++;
-
2377
-
2378 }
-
2379
-
2380 initializeBuffer2Df( transform_matrix_RTbuffer, m_global );
-
2381 initializeBuffer1Dui( primitive_type_RTbuffer, ptype_global );
-
2382 initializeBuffer1Df( primitive_area_RTbuffer, area_global );
-
2383 initializeBuffer1Dchar( twosided_flag_RTbuffer, twosided_flag_global );
-
2384 initializeBuffer2Dfloat3( patch_vertices_RTbuffer, patch_vertices );
-
2385 initializeBuffer2Dfloat3( triangle_vertices_RTbuffer, triangle_vertices );
-
2386 initializeBuffer2Dfloat3( tile_vertices_RTbuffer, tile_vertices );
-
2387 initializeBuffer2Dfloat3( voxel_vertices_RTbuffer, voxel_vertices );
-
2388 initializeBuffer2Dfloat3( bbox_vertices_RTbuffer, bbox_vertices );
-
2389
-
2390 initializeBuffer1Dint2( object_subdivisions_RTbuffer, object_subdivisions );
-
2391
-
2392 initializeBuffer1Dui( patch_UUID_RTbuffer, patch_UUID );
-
2393 initializeBuffer1Dui( triangle_UUID_RTbuffer, triangle_UUID );
-
2394 initializeBuffer1Dui( disk_UUID_RTbuffer, disk_UUID );
-
2395 initializeBuffer1Dui( tile_UUID_RTbuffer, tile_UUID );
-
2396 initializeBuffer1Dui( voxel_UUID_RTbuffer, voxel_UUID );
-
2397 initializeBuffer1Dui( bbox_UUID_RTbuffer, bbox_UUID );
-
2398
-
2399 initializeBuffer1Dui( objectID_RTbuffer, objectID );
-
2400 initializeBuffer1Dui( primitiveID_RTbuffer, primitiveID );
-
2401
-
2402 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( patch, patch_count ) );
-
2403 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( triangle, triangle_count ) );
-
2404 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( disk, disk_count ) );
-
2405 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( tile, tile_count ) );
-
2406 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( voxel, voxel_count ) );
-
2407 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( bbox, bbox_face_count ) );
-
2408
-
2409 RT_CHECK_ERROR( rtAccelerationMarkDirty( geometry_acceleration ) );
-
2410
-
2411 /* Set the top_object variable */
-
2412 //NOTE: not sure if this has to be set again or not..
-
2413 RT_CHECK_ERROR( rtVariableSetObject( top_object, top_level_group ) );
-
2414
-
2415 RTsize device_memory;
-
2416 RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
-
2417
-
2418 device_memory *= 1e-6;
-
2419
-
2420 if( device_memory<500 ){
-
2421 std::cout << "WARNING (RadiationModel): device memory is very low (" << device_memory << " MB)" << std::endl;
-
2422 }
-
2423
-
2424 /* Validate/Compile OptiX Context */
-
2425 RT_CHECK_ERROR( rtContextValidate( OptiX_Context ) );
-
2426 RT_CHECK_ERROR( rtContextCompile( OptiX_Context ) );
+
2269 }
+
2270
+
2271 int2 size_max(0,0);
+
2272 for( int t=0; t<maskdata.size(); t++ ){
+
2273 int2 sz( maskdata.at(t).front().size(), maskdata.at(t).size() );
+
2274 if( sz.x>size_max.x ){
+
2275 size_max.x = sz.x;
+
2276 }
+
2277 if( sz.y>size_max.y ){
+
2278 size_max.y = sz.y;
+
2279 }
+
2280 }
+
2281
+
2282 for( int t=0; t<maskdata.size(); t++ ){
+
2283 maskdata.at(t).resize(size_max.y);
+
2284 for( int j=0; j<size_max.y; j++ ){
+
2285 maskdata.at(t).at(j).resize(size_max.x);
+
2286 }
+
2287 }
+
2288
+
2289 initializeBuffer3D( maskdata_RTbuffer, maskdata );
+
2290 initializeBuffer1Dint2( masksize_RTbuffer, masksize );
+
2291 initializeBuffer1Di( maskID_RTbuffer, maskID );
+
2292
+
2293 initializeBuffer2Dfloat2( uvdata_RTbuffer, uvdata );
+
2294 initializeBuffer1Di( uvID_RTbuffer, uvID );
+
2295
+
2296 //Bounding box
+
2297 helios::vec2 xbounds, ybounds, zbounds;
+
2298 context->getDomainBoundingBox( xbounds, ybounds, zbounds );
+
2299
+
2300 if( periodic_flag.x==1 || periodic_flag.y ==1 ) {
+
2301 if (!cameras.empty()) {
+
2302 for (auto &camera: cameras) {
+
2303 vec3 camerapos = camera.second.position;
+
2304 if (camerapos.x < xbounds.x || camerapos.x > xbounds.y || camerapos.y < ybounds.x || camerapos.y > ybounds.y) {
+
2305 std::cout << "WARNING (RadiationModel::updateGeometry): camera position is outside of the domain bounding box. Disabling periodic boundary conditions." << std::endl;
+
2306 periodic_flag.x = 0;
+
2307 periodic_flag.y = 0;
+
2308 break;
+
2309 }
+
2310 if (camerapos.z < zbounds.x) {
+
2311 zbounds.x = camerapos.z;
+
2312 }
+
2313 if (camerapos.z > zbounds.y) {
+
2314 zbounds.y = camerapos.z;
+
2315 }
+
2316 }
+
2317 }
+
2318 }
+
2319
+
2320 xbounds.x -= 1e-5;
+
2321 xbounds.y += 1e-5;
+
2322 ybounds.x -= 1e-5;
+
2323 ybounds.y += 1e-5;
+
2324 zbounds.x -= 1e-5;
+
2325 zbounds.y += 1e-5;
+
2326
+
2327 std::vector<uint> bbox_UUID;
+
2328 int bbox_face_count = 0;
+
2329
+
2330 std::vector<std::vector<optix::float3> > bbox_vertices;
+
2331
+
2332 //primitive type
+
2333
+
2334 std::vector<optix::float3> v;
+
2335 v.resize(4);
+
2336
+
2337 if( periodic_flag.x==1 ){
+
2338
+
2339 // -x facing
+
2340 v.at(0) = optix::make_float3(xbounds.x,ybounds.x,zbounds.x);
+
2341 v.at(1) = optix::make_float3(xbounds.x,ybounds.y,zbounds.x);
+
2342 v.at(2) = optix::make_float3(xbounds.x,ybounds.y,zbounds.y);
+
2343 v.at(3) = optix::make_float3(xbounds.x,ybounds.x,zbounds.y);
+
2344 bbox_vertices.push_back(v);
+
2345 bbox_UUID.push_back(Nprimitives+bbox_face_count);
+
2346 objectID.push_back( Nobjects+bbox_face_count );
+
2347 ptype_global.push_back(5);
+
2348 bbox_face_count++;
+
2349
+
2350 // +x facing
+
2351 v.at(0) = optix::make_float3(xbounds.y,ybounds.x,zbounds.x);
+
2352 v.at(1) = optix::make_float3(xbounds.y,ybounds.y,zbounds.x);
+
2353 v.at(2) = optix::make_float3(xbounds.y,ybounds.y,zbounds.y);
+
2354 v.at(3) = optix::make_float3(xbounds.y,ybounds.x,zbounds.y);
+
2355 bbox_vertices.push_back(v);
+
2356 bbox_UUID.push_back(Nprimitives+bbox_face_count);
+
2357 objectID.push_back( Nobjects+bbox_face_count );
+
2358 ptype_global.push_back(5);
+
2359 bbox_face_count++;
+
2360
+
2361 }
+
2362 if( periodic_flag.y==1 ){
+
2363
+
2364 // -y facing
+
2365 v.at(0) = optix::make_float3(xbounds.x,ybounds.x,zbounds.x);
+
2366 v.at(1) = optix::make_float3(xbounds.y,ybounds.x,zbounds.x);
+
2367 v.at(2) = optix::make_float3(xbounds.y,ybounds.x,zbounds.y);
+
2368 v.at(3) = optix::make_float3(xbounds.x,ybounds.x,zbounds.y);
+
2369 bbox_vertices.push_back(v);
+
2370 bbox_UUID.push_back(Nprimitives+bbox_face_count);
+
2371 objectID.push_back( Nobjects+bbox_face_count );
+
2372 ptype_global.push_back(5);
+
2373 bbox_face_count++;
+
2374
+
2375 // +y facing
+
2376 v.at(0) = optix::make_float3(xbounds.x,ybounds.y,zbounds.x);
+
2377 v.at(1) = optix::make_float3(xbounds.y,ybounds.y,zbounds.x);
+
2378 v.at(2) = optix::make_float3(xbounds.y,ybounds.y,zbounds.y);
+
2379 v.at(3) = optix::make_float3(xbounds.x,ybounds.y,zbounds.y);
+
2380 bbox_vertices.push_back(v);
+
2381 bbox_UUID.push_back(Nprimitives+bbox_face_count);
+
2382 objectID.push_back( Nobjects+bbox_face_count );
+
2383 ptype_global.push_back(5);
+
2384 bbox_face_count++;
+
2385
+
2386 }
+
2387
+
2388 initializeBuffer2Df( transform_matrix_RTbuffer, m_global );
+
2389 initializeBuffer1Dui( primitive_type_RTbuffer, ptype_global );
+
2390 initializeBuffer1Df( primitive_area_RTbuffer, area_global );
+
2391 initializeBuffer1Dchar( twosided_flag_RTbuffer, twosided_flag_global );
+
2392 initializeBuffer2Dfloat3( patch_vertices_RTbuffer, patch_vertices );
+
2393 initializeBuffer2Dfloat3( triangle_vertices_RTbuffer, triangle_vertices );
+
2394 initializeBuffer2Dfloat3( tile_vertices_RTbuffer, tile_vertices );
+
2395 initializeBuffer2Dfloat3( voxel_vertices_RTbuffer, voxel_vertices );
+
2396 initializeBuffer2Dfloat3( bbox_vertices_RTbuffer, bbox_vertices );
+
2397
+
2398 initializeBuffer1Dint2( object_subdivisions_RTbuffer, object_subdivisions );
+
2399
+
2400 initializeBuffer1Dui( patch_UUID_RTbuffer, patch_UUID );
+
2401 initializeBuffer1Dui( triangle_UUID_RTbuffer, triangle_UUID );
+
2402 initializeBuffer1Dui( disk_UUID_RTbuffer, disk_UUID );
+
2403 initializeBuffer1Dui( tile_UUID_RTbuffer, tile_UUID );
+
2404 initializeBuffer1Dui( voxel_UUID_RTbuffer, voxel_UUID );
+
2405 initializeBuffer1Dui( bbox_UUID_RTbuffer, bbox_UUID );
+
2406
+
2407 initializeBuffer1Dui( objectID_RTbuffer, objectID );
+
2408 initializeBuffer1Dui( primitiveID_RTbuffer, primitiveID );
+
2409
+
2410 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( patch, patch_count ) );
+
2411 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( triangle, triangle_count ) );
+
2412 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( disk, disk_count ) );
+
2413 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( tile, tile_count ) );
+
2414 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( voxel, voxel_count ) );
+
2415 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( bbox, bbox_face_count ) );
+
2416
+
2417 RT_CHECK_ERROR( rtAccelerationMarkDirty( geometry_acceleration ) );
+
2418
+
2419 /* Set the top_object variable */
+
2420 //NOTE: not sure if this has to be set again or not..
+
2421 RT_CHECK_ERROR( rtVariableSetObject( top_object, top_level_group ) );
+
2422
+
2423 RTsize device_memory;
+
2424 RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
+
2425
+
2426 device_memory *= 1e-6;
2427
-
2428 // device_memory;
-
2429 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
-
2430
-
2431 // device_memory *= 1e-6;
-
2432 // if( device_memory < 1000 ){
-
2433 // printf("available device memory at end of OptiX context compile: %6.3f MB\n",device_memory);
-
2434 // }else{
-
2435 // printf("available device memory at end of OptiX context compile: %6.3f GB\n",device_memory*1e-3);
-
2436 // }
-
2437
-
2438 isgeometryinitialized = true;
-
2439
-
2440 // device_memory;
-
2441 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
-
2442
-
2443 // device_memory *= 1e-6;
-
2444 // if( device_memory < 1000 ){
-
2445 // printf("available device memory before acceleration build: %6.3f MB\n",device_memory);
-
2446 // }else{
-
2447 // printf("available device memory before acceleration build: %6.3f GB\n",device_memory*1e-3);
-
2448 // }
-
2449
-
2450 optix::int3 launch_dim_dummy = optix::make_int3( 1, 1, 1 );
-
2451 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIRECT , launch_dim_dummy.x, launch_dim_dummy.y, launch_dim_dummy.z ) );
-
2452
-
2453 RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
-
2454
-
2455 // device_memory;
-
2456 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
+
2428 if( device_memory<500 ){
+
2429 std::cout << "WARNING (RadiationModel): device memory is very low (" << device_memory << " MB)" << std::endl;
+
2430 }
+
2431
+
2432 /* Validate/Compile OptiX Context */
+
2433 RT_CHECK_ERROR( rtContextValidate( OptiX_Context ) );
+
2434 RT_CHECK_ERROR( rtContextCompile( OptiX_Context ) );
+
2435
+
2436 // device_memory;
+
2437 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
+
2438
+
2439 // device_memory *= 1e-6;
+
2440 // if( device_memory < 1000 ){
+
2441 // printf("available device memory at end of OptiX context compile: %6.3f MB\n",device_memory);
+
2442 // }else{
+
2443 // printf("available device memory at end of OptiX context compile: %6.3f GB\n",device_memory*1e-3);
+
2444 // }
+
2445
+
2446 isgeometryinitialized = true;
+
2447
+
2448 // device_memory;
+
2449 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
+
2450
+
2451 // device_memory *= 1e-6;
+
2452 // if( device_memory < 1000 ){
+
2453 // printf("available device memory before acceleration build: %6.3f MB\n",device_memory);
+
2454 // }else{
+
2455 // printf("available device memory before acceleration build: %6.3f GB\n",device_memory*1e-3);
+
2456 // }
2457
-
2458 // device_memory *= 1e-6;
-
2459 // if( device_memory < 1000 ){
-
2460 // printf("available device memory at end of acceleration build: %6.3f MB\n",device_memory);
-
2461 // }else{
-
2462 // printf("available device memory at end of acceleration build: %6.3f GB\n",device_memory*1e-3);
-
2463 // }
-
2464
-
2465 if( message_flag ){
-
2466 std::cout << "done." << std::endl;
-
2467 }
-
2468
-
2469}
-
-
2470
-
2471void RadiationModel::updateRadiativeProperties( const std::vector<std::string> &labels ) {
+
2458 optix::int3 launch_dim_dummy = optix::make_int3( 1, 1, 1 );
+
2459 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIRECT , launch_dim_dummy.x, launch_dim_dummy.y, launch_dim_dummy.z ) );
+
2460
+
2461 RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
+
2462
+
2463 // device_memory;
+
2464 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
+
2465
+
2466 // device_memory *= 1e-6;
+
2467 // if( device_memory < 1000 ){
+
2468 // printf("available device memory at end of acceleration build: %6.3f MB\n",device_memory);
+
2469 // }else{
+
2470 // printf("available device memory at end of acceleration build: %6.3f GB\n",device_memory*1e-3);
+
2471 // }
2472
-
2473 // Possible scenarios for specifying a primitive's radiative properties
-
2474 // 1. If primitive data of form reflectivity_band/transmissivity_band is given, this value is used and overrides any other option.
-
2475 // 2. If primitive data of form reflectivity_spectrum/transmissivity_spectrum is given that references global data containing spectral reflectivity/transmissivity:
-
2476 // 2a. If radiation source spectrum was not given, assume source spectral intensity is constant over band and calculate using primitive spectrum
-
2477 // 2b. If radiation source spectrum was given, calculate using both source and primitive spectrum.
+
2473 if( message_flag ){
+
2474 std::cout << "done." << std::endl;
+
2475 }
+
2476
+
2477}
+
2478
-
2479 if( message_flag ) {
-
2480 std::cout << "Updating radiative properties..." << std::flush;
-
2481 }
-
2482
-
2483 uint Nbands = labels.size();//number of radiative bands
-
2484 uint Nsources = radiation_sources.size();
-
2485 uint Ncameras = cameras.size();
-
2486 size_t Nobjects = primitiveID.size();
-
2487 size_t Nprimitives = context_UUIDs.size();
-
2488
-
2489 scattering_iterations_needed.resize(Nbands);
-
2490 for( int b=0; b<Nbands; b++ ){
-
2491 scattering_iterations_needed.at(b) = false;
-
2492 }
-
2493
-
2494 std::vector<std::vector<std::vector<float> > > rho, tau; //first index is the source, second index is the primitive, third index is the band
-
2495 std::vector<std::vector<std::vector<std::vector<float> > > > rho_cam, tau_cam; //Fourth index is the camera
-
2496 float eps;
-
2497
-
2498 std::string prop;
-
2499
-
2500 for( auto &label : radiation_bands){
-
2501 label.second.radiativepropertiesinitialized = false;
-
2502 }
-
2503 for ( const auto &label: labels) {
-
2504 radiation_bands.at(label).radiativepropertiesinitialized = true;
-
2505 }
-
2506
-
2507 rho.resize(Nsources);
-
2508 tau.resize(Nsources);
-
2509 for( size_t s=0; s<Nsources; s++ ){
-
2510 rho.at(s).resize(Nprimitives);
-
2511 tau.at(s).resize(Nprimitives);
-
2512 for ( size_t p=0; p<Nprimitives; p++ ) {
-
2513 rho.at(s).at(p).resize(Nbands);
-
2514 tau.at(s).at(p).resize(Nbands);
-
2515 }
-
2516 }
-
2517 if ( Ncameras ) {
-
2518 rho_cam.resize(Nsources);
-
2519 tau_cam.resize(Nsources);
-
2520 for( size_t s=0; s<Nsources; s++ ) {
-
2521 rho_cam.at(s).resize(Nprimitives);
-
2522 tau_cam.at(s).resize(Nprimitives);
-
2523 for (size_t p = 0; p < Nprimitives; p++) {
-
2524 rho_cam.at(s).at(p).resize(Nbands);
-
2525 tau_cam.at(s).at(p).resize(Nbands);
-
2526 for( size_t b=0; b<Nbands; b++ ){
-
2527 rho_cam.at(s).at(p).at(b).resize(Ncameras);
-
2528 tau_cam.at(s).at(p).at(b).resize(Ncameras);
-
2529 }
-
2530 }
-
2531 }
-
2532 }
-
2533
-
2534 //Pre-calculate all unique camera spectral responses for all cameras and bands
-
2535 std::vector<std::vector<std::vector<helios::vec2> > > camera_response_unique;
-
2536 camera_response_unique.resize(Ncameras);
-
2537 if (Ncameras > 0) {
-
2538 uint cam = 0;
-
2539 for (const auto &camera: cameras) {
-
2540
-
2541 camera_response_unique.at(cam).resize(Nbands);
-
2542
-
2543 for (uint b = 0; b < Nbands; b++) {
-
2544
-
2545 if( camera.second.band_spectral_response.find(labels.at(b)) == camera.second.band_spectral_response.end() ){
-
2546 continue;
-
2547 }
+
2479void RadiationModel::updateRadiativeProperties( const std::vector<std::string> &labels ) {
+
2480
+
2481 // Possible scenarios for specifying a primitive's radiative properties
+
2482 // 1. If primitive data of form reflectivity_band/transmissivity_band is given, this value is used and overrides any other option.
+
2483 // 2. If primitive data of form reflectivity_spectrum/transmissivity_spectrum is given that references global data containing spectral reflectivity/transmissivity:
+
2484 // 2a. If radiation source spectrum was not given, assume source spectral intensity is constant over band and calculate using primitive spectrum
+
2485 // 2b. If radiation source spectrum was given, calculate using both source and primitive spectrum.
+
2486
+
2487 if( message_flag ) {
+
2488 std::cout << "Updating radiative properties..." << std::flush;
+
2489 }
+
2490
+
2491 uint Nbands = labels.size();//number of radiative bands
+
2492 uint Nsources = radiation_sources.size();
+
2493 uint Ncameras = cameras.size();
+
2494 size_t Nobjects = primitiveID.size();
+
2495 size_t Nprimitives = context_UUIDs.size();
+
2496
+
2497 scattering_iterations_needed.resize(Nbands);
+
2498 for( int b=0; b<Nbands; b++ ){
+
2499 scattering_iterations_needed.at(b) = false;
+
2500 }
+
2501
+
2502 std::vector<std::vector<std::vector<float> > > rho, tau; //first index is the source, second index is the primitive, third index is the band
+
2503 std::vector<std::vector<std::vector<std::vector<float> > > > rho_cam, tau_cam; //Fourth index is the camera
+
2504 float eps;
+
2505
+
2506 std::string prop;
+
2507
+
2508 for( auto &label : radiation_bands){
+
2509 label.second.radiativepropertiesinitialized = false;
+
2510 }
+
2511 for ( const auto &label: labels) {
+
2512 radiation_bands.at(label).radiativepropertiesinitialized = true;
+
2513 }
+
2514
+
2515 rho.resize(Nsources);
+
2516 tau.resize(Nsources);
+
2517 for( size_t s=0; s<Nsources; s++ ){
+
2518 rho.at(s).resize(Nprimitives);
+
2519 tau.at(s).resize(Nprimitives);
+
2520 for ( size_t p=0; p<Nprimitives; p++ ) {
+
2521 rho.at(s).at(p).resize(Nbands);
+
2522 tau.at(s).at(p).resize(Nbands);
+
2523 }
+
2524 }
+
2525 if ( Ncameras ) {
+
2526 rho_cam.resize(Nsources);
+
2527 tau_cam.resize(Nsources);
+
2528 for( size_t s=0; s<Nsources; s++ ) {
+
2529 rho_cam.at(s).resize(Nprimitives);
+
2530 tau_cam.at(s).resize(Nprimitives);
+
2531 for (size_t p = 0; p < Nprimitives; p++) {
+
2532 rho_cam.at(s).at(p).resize(Nbands);
+
2533 tau_cam.at(s).at(p).resize(Nbands);
+
2534 for( size_t b=0; b<Nbands; b++ ){
+
2535 rho_cam.at(s).at(p).at(b).resize(Ncameras);
+
2536 tau_cam.at(s).at(p).at(b).resize(Ncameras);
+
2537 }
+
2538 }
+
2539 }
+
2540 }
+
2541
+
2542 //Pre-calculate all unique camera spectral responses for all cameras and bands
+
2543 std::vector<std::vector<std::vector<helios::vec2> > > camera_response_unique;
+
2544 camera_response_unique.resize(Ncameras);
+
2545 if (Ncameras > 0) {
+
2546 uint cam = 0;
+
2547 for (const auto &camera: cameras) {
2548
-
2549 std::string camera_response = camera.second.band_spectral_response.at(labels.at(b));
+
2549 camera_response_unique.at(cam).resize(Nbands);
2550
-
2551 if (!camera_response.empty()) {
+
2551 for (uint b = 0; b < Nbands; b++) {
2552
-
2553 if( !context->doesGlobalDataExist(camera_response.c_str()) ){
-
2554 if( camera_response!="uniform" ) {
-
2555 std::cerr << "WARNING (RadiationModel::updateRadiativeProperties): Camera spectral response \"" << camera_response << "\" does not exist. Assuming a uniform spectral response..." << std::flush;
-
2556 }
-
2557 }else if ( context->getGlobalDataType(camera_response.c_str()) == helios::HELIOS_TYPE_VEC2) {
+
2553 if( camera.second.band_spectral_response.find(labels.at(b)) == camera.second.band_spectral_response.end() ){
+
2554 continue;
+
2555 }
+
2556
+
2557 std::string camera_response = camera.second.band_spectral_response.at(labels.at(b));
2558
-
2559 std::vector<helios::vec2> data = loadSpectralData(camera_response.c_str());
+
2559 if (!camera_response.empty()) {
2560
-
2561 camera_response_unique.at(cam).at(b) = data;
-
2562
-
2563 }else if ( context->getGlobalDataType(camera_response.c_str()) != helios::HELIOS_TYPE_VEC2 && context->getGlobalDataType(camera_response.c_str()) != helios::HELIOS_TYPE_STRING ) {
-
2564 camera_response.clear();
-
2565 std::cout << "WARNING (RadiationModel::runBand): Camera spectral response \"" << camera_response << "\" is not of type HELIOS_TYPE_VEC2 or HELIOS_TYPE_STRING. Assuming a uniform spectral response..." << std::flush;
-
2566 }
-
2567
-
2568 }
-
2569
-
2570 }
-
2571 cam++;
-
2572 }
-
2573 }
-
2574
-
2575 //Pre-calculate all unique primitive reflectivity and transmissivity values before assigning to primitives
-
2576
-
2577 //first, figure out all of the spectra referenced by all primitives and store it in "surface_spectra" to avoid having to load it again
-
2578 std::map<std::string,std::vector<helios::vec2> > surface_spectra_rho;
-
2579 std::map<std::string,std::vector<helios::vec2> > surface_spectra_tau;
-
2580 for (size_t u = 0; u < Nprimitives; u++) {
-
2581
-
2582 uint UUID = context_UUIDs.at(u);
-
2583
-
2584 if (context->doesPrimitiveDataExist(UUID, "reflectivity_spectrum") ) {
-
2585 if (context->getPrimitiveDataType(UUID, "reflectivity_spectrum") == HELIOS_TYPE_STRING) {
-
2586 std::string spectrum_label;
-
2587 context->getPrimitiveData(UUID, "reflectivity_spectrum", spectrum_label);
-
2588
-
2589 //get the spectral reflectivity data and store it in surface_spectra to avoid having to load it again
-
2590 if (surface_spectra_rho.find(spectrum_label) == surface_spectra_rho.end() ){
-
2591 if( !context->doesGlobalDataExist(spectrum_label.c_str()) ){
-
2592 if (message_flag && !spectrum_label.empty() ) {
-
2593 std::cerr << "WARNING (RadiationModel::runBand): Primitive spectral reflectivity \"" << spectrum_label << "\" does not exist. Using default reflectivity of 0..." << std::flush;
-
2594 }
-
2595 std::vector<helios::vec2> data;
-
2596 surface_spectra_rho.emplace(spectrum_label, data);
-
2597 }else if( context->getGlobalDataType(spectrum_label.c_str() ) == HELIOS_TYPE_VEC2 ) {
-
2598
-
2599 std::vector<helios::vec2> data = loadSpectralData(spectrum_label.c_str());
-
2600 surface_spectra_rho.emplace(spectrum_label, data);
-
2601
-
2602 }else if ( context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_VEC2 && context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_STRING ) {
-
2603 spectrum_label.clear();
-
2604 std::cout << "WARNING (RadiationModel::runBand): Object spectral reflectivity \"" << spectrum_label << "\" is not of type HELIOS_TYPE_VEC2 or HELIOS_TYPE_STRING. Assuming a uniform spectral distribution..." << std::flush;
-
2605 }
+
2561 if( !context->doesGlobalDataExist(camera_response.c_str()) ){
+
2562 if( camera_response!="uniform" ) {
+
2563 std::cerr << "WARNING (RadiationModel::updateRadiativeProperties): Camera spectral response \"" << camera_response << "\" does not exist. Assuming a uniform spectral response..." << std::flush;
+
2564 }
+
2565 }else if ( context->getGlobalDataType(camera_response.c_str()) == helios::HELIOS_TYPE_VEC2) {
+
2566
+
2567 std::vector<helios::vec2> data = loadSpectralData(camera_response.c_str());
+
2568
+
2569 camera_response_unique.at(cam).at(b) = data;
+
2570
+
2571 }else if ( context->getGlobalDataType(camera_response.c_str()) != helios::HELIOS_TYPE_VEC2 && context->getGlobalDataType(camera_response.c_str()) != helios::HELIOS_TYPE_STRING ) {
+
2572 camera_response.clear();
+
2573 std::cout << "WARNING (RadiationModel::runBand): Camera spectral response \"" << camera_response << "\" is not of type HELIOS_TYPE_VEC2 or HELIOS_TYPE_STRING. Assuming a uniform spectral response..." << std::flush;
+
2574 }
+
2575
+
2576 }
+
2577
+
2578 }
+
2579 cam++;
+
2580 }
+
2581 }
+
2582
+
2583 //Pre-calculate all unique primitive reflectivity and transmissivity values before assigning to primitives
+
2584
+
2585 //first, figure out all of the spectra referenced by all primitives and store it in "surface_spectra" to avoid having to load it again
+
2586 std::map<std::string,std::vector<helios::vec2> > surface_spectra_rho;
+
2587 std::map<std::string,std::vector<helios::vec2> > surface_spectra_tau;
+
2588 for (size_t u = 0; u < Nprimitives; u++) {
+
2589
+
2590 uint UUID = context_UUIDs.at(u);
+
2591
+
2592 if (context->doesPrimitiveDataExist(UUID, "reflectivity_spectrum") ) {
+
2593 if (context->getPrimitiveDataType(UUID, "reflectivity_spectrum") == HELIOS_TYPE_STRING) {
+
2594 std::string spectrum_label;
+
2595 context->getPrimitiveData(UUID, "reflectivity_spectrum", spectrum_label);
+
2596
+
2597 //get the spectral reflectivity data and store it in surface_spectra to avoid having to load it again
+
2598 if (surface_spectra_rho.find(spectrum_label) == surface_spectra_rho.end() ){
+
2599 if( !context->doesGlobalDataExist(spectrum_label.c_str()) ){
+
2600 if (message_flag && !spectrum_label.empty() ) {
+
2601 std::cerr << "WARNING (RadiationModel::runBand): Primitive spectral reflectivity \"" << spectrum_label << "\" does not exist. Using default reflectivity of 0..." << std::flush;
+
2602 }
+
2603 std::vector<helios::vec2> data;
+
2604 surface_spectra_rho.emplace(spectrum_label, data);
+
2605 }else if( context->getGlobalDataType(spectrum_label.c_str() ) == HELIOS_TYPE_VEC2 ) {
2606
-
2607 }
-
2608
-
2609 }
-
2610 }
-
2611
-
2612 if (context->doesPrimitiveDataExist(UUID, "transmissivity_spectrum") ) {
-
2613 if (context->getPrimitiveDataType(UUID, "transmissivity_spectrum") == HELIOS_TYPE_STRING) {
-
2614 std::string spectrum_label;
-
2615 context->getPrimitiveData(UUID, "transmissivity_spectrum", spectrum_label);
+
2607 std::vector<helios::vec2> data = loadSpectralData(spectrum_label.c_str());
+
2608 surface_spectra_rho.emplace(spectrum_label, data);
+
2609
+
2610 }else if ( context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_VEC2 && context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_STRING ) {
+
2611 spectrum_label.clear();
+
2612 std::cout << "WARNING (RadiationModel::runBand): Object spectral reflectivity \"" << spectrum_label << "\" is not of type HELIOS_TYPE_VEC2 or HELIOS_TYPE_STRING. Assuming a uniform spectral distribution..." << std::flush;
+
2613 }
+
2614
+
2615 }
2616
-
2617 //get the spectral transmissivity data and store it in surface_spectra to avoid having to load it again
-
2618 if (surface_spectra_tau.find(spectrum_label) == surface_spectra_tau.end() ){
-
2619 if( !context->doesGlobalDataExist(spectrum_label.c_str()) ) {
-
2620 if (message_flag && !spectrum_label.empty() ){
-
2621 std::cerr << "WARNING (RadiationModel::runBand): Primitive spectral transmissivity \"" << spectrum_label << "\" does not exist. Using default transmissivity of 0..." << std::flush;
-
2622 }
-
2623 std::vector<helios::vec2> data;
-
2624 surface_spectra_tau.emplace(spectrum_label, data);
-
2625 }else if( context->getGlobalDataType(spectrum_label.c_str() ) == HELIOS_TYPE_VEC2 ) {
-
2626
-
2627 std::vector<helios::vec2> data = loadSpectralData(spectrum_label.c_str());
-
2628 surface_spectra_tau.emplace(spectrum_label, data);
-
2629
-
2630 }else if ( context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_VEC2 && context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_STRING ) {
-
2631 spectrum_label.clear();
-
2632 std::cout << "WARNING (RadiationModel::runBand): Object spectral transmissivity \"" << spectrum_label << "\" is not of type HELIOS_TYPE_VEC2 or HELIOS_TYPE_STRING. Assuming a uniform spectral distribution..." << std::flush;
-
2633 }
-
2634 }
-
2635
-
2636 }
-
2637 }
-
2638 }
-
2639
-
2640// printf("%d (rho) %d (tau) unique surface spectra loaded\n", surface_spectra_rho.size(),surface_spectra_tau.size());
-
2641
-
2642 //second, calculate unique values of rho and tau for all sources and bands
-
2643 std::map<std::string,std::vector<std::vector<float> > > rho_unique;
-
2644 std::map<std::string,std::vector<std::vector<float> > > tau_unique;
-
2645
-
2646 std::map<std::string,std::vector<std::vector<std::vector<float> > > > rho_cam_unique;
-
2647 std::map<std::string,std::vector<std::vector<std::vector<float> > > > tau_cam_unique;
-
2648
-
2649 std::vector<std::vector<float> > empty;
-
2650 empty.resize(Nbands);
-
2651 for( uint b=0; b<Nbands; b++ ) {
-
2652 empty.at(b).resize(Nsources,0);
-
2653 }
-
2654 std::vector<std::vector<std::vector<float> > > empty_cam;
-
2655 if (Ncameras > 0) {
-
2656 empty_cam.resize(Nbands);
-
2657 for (uint b = 0; b < Nbands; b++) {
-
2658 empty_cam.at(b).resize(Nsources);
-
2659 for (uint s = 0; s < Nsources; s++) {
-
2660 empty_cam.at(b).at(s).resize(Ncameras, 0);
-
2661 }
-
2662 }
-
2663 }
-
2664
-
2665 for( const auto &spectrum : surface_spectra_rho ) { //reflectivity
-
2666
-
2667 rho_unique.emplace(spectrum.first, empty);
-
2668 if (Ncameras > 0) {
-
2669 rho_cam_unique.emplace(spectrum.first, empty_cam);
+
2617 }
+
2618 }
+
2619
+
2620 if (context->doesPrimitiveDataExist(UUID, "transmissivity_spectrum") ) {
+
2621 if (context->getPrimitiveDataType(UUID, "transmissivity_spectrum") == HELIOS_TYPE_STRING) {
+
2622 std::string spectrum_label;
+
2623 context->getPrimitiveData(UUID, "transmissivity_spectrum", spectrum_label);
+
2624
+
2625 //get the spectral transmissivity data and store it in surface_spectra to avoid having to load it again
+
2626 if (surface_spectra_tau.find(spectrum_label) == surface_spectra_tau.end() ){
+
2627 if( !context->doesGlobalDataExist(spectrum_label.c_str()) ) {
+
2628 if (message_flag && !spectrum_label.empty() ){
+
2629 std::cerr << "WARNING (RadiationModel::runBand): Primitive spectral transmissivity \"" << spectrum_label << "\" does not exist. Using default transmissivity of 0..." << std::flush;
+
2630 }
+
2631 std::vector<helios::vec2> data;
+
2632 surface_spectra_tau.emplace(spectrum_label, data);
+
2633 }else if( context->getGlobalDataType(spectrum_label.c_str() ) == HELIOS_TYPE_VEC2 ) {
+
2634
+
2635 std::vector<helios::vec2> data = loadSpectralData(spectrum_label.c_str());
+
2636 surface_spectra_tau.emplace(spectrum_label, data);
+
2637
+
2638 }else if ( context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_VEC2 && context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_STRING ) {
+
2639 spectrum_label.clear();
+
2640 std::cout << "WARNING (RadiationModel::runBand): Object spectral transmissivity \"" << spectrum_label << "\" is not of type HELIOS_TYPE_VEC2 or HELIOS_TYPE_STRING. Assuming a uniform spectral distribution..." << std::flush;
+
2641 }
+
2642 }
+
2643
+
2644 }
+
2645 }
+
2646 }
+
2647
+
2648// printf("%d (rho) %d (tau) unique surface spectra loaded\n", surface_spectra_rho.size(),surface_spectra_tau.size());
+
2649
+
2650 //second, calculate unique values of rho and tau for all sources and bands
+
2651 std::map<std::string,std::vector<std::vector<float> > > rho_unique;
+
2652 std::map<std::string,std::vector<std::vector<float> > > tau_unique;
+
2653
+
2654 std::map<std::string,std::vector<std::vector<std::vector<float> > > > rho_cam_unique;
+
2655 std::map<std::string,std::vector<std::vector<std::vector<float> > > > tau_cam_unique;
+
2656
+
2657 std::vector<std::vector<float> > empty;
+
2658 empty.resize(Nbands);
+
2659 for( uint b=0; b<Nbands; b++ ) {
+
2660 empty.at(b).resize(Nsources,0);
+
2661 }
+
2662 std::vector<std::vector<std::vector<float> > > empty_cam;
+
2663 if (Ncameras > 0) {
+
2664 empty_cam.resize(Nbands);
+
2665 for (uint b = 0; b < Nbands; b++) {
+
2666 empty_cam.at(b).resize(Nsources);
+
2667 for (uint s = 0; s < Nsources; s++) {
+
2668 empty_cam.at(b).at(s).resize(Ncameras, 0);
+
2669 }
2670 }
-
2671
-
2672 for (uint b = 0; b < Nbands; b++) {
-
2673 std::string band = labels.at(b);
+
2671 }
+
2672
+
2673 for( const auto &spectrum : surface_spectra_rho ) { //reflectivity
2674
-
2675 for (uint s = 0; s < Nsources; s++) {
-
2676
-
2677 //integrate
-
2678 if( radiation_bands.at(band).wavebandBounds.x != 0 && radiation_bands.at(band).wavebandBounds.y != 0 && !spectrum.second.empty() ) {
-
2679 if (!radiation_sources.at(s).source_spectrum.empty()) {
-
2680 rho_unique.at(spectrum.first).at(b).at(s) = integrateSpectrum(s, spectrum.second, radiation_bands.at(band).wavebandBounds.x, radiation_bands.at(band).wavebandBounds.y);
-
2681 } else {
-
2682 //source spectrum not provided, assume source intensity is constant over the band
-
2683 rho_unique.at(spectrum.first).at(b).at(s) = integrateSpectrum(spectrum.second, radiation_bands.at(band).wavebandBounds.x, radiation_bands.at(band).wavebandBounds.y)/(radiation_bands.at(band).wavebandBounds.y-radiation_bands.at(band).wavebandBounds.x);
-
2684 }
-
2685 }else{
-
2686 rho_unique.at(spectrum.first).at(b).at(s) = rho_default;
-
2687 }
-
2688
-
2689 //cameras
-
2690 if (Ncameras > 0) {
-
2691 uint cam=0;
-
2692 for (const auto &camera: cameras) {
-
2693
-
2694 if( camera_response_unique.at(cam).at(b).empty() ){
-
2695 rho_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = rho_unique.at(spectrum.first).at(b).at(s);
+
2675 rho_unique.emplace(spectrum.first, empty);
+
2676 if (Ncameras > 0) {
+
2677 rho_cam_unique.emplace(spectrum.first, empty_cam);
+
2678 }
+
2679
+
2680 for (uint b = 0; b < Nbands; b++) {
+
2681 std::string band = labels.at(b);
+
2682
+
2683 for (uint s = 0; s < Nsources; s++) {
+
2684
+
2685 //integrate
+
2686 if( radiation_bands.at(band).wavebandBounds.x != 0 && radiation_bands.at(band).wavebandBounds.y != 0 && !spectrum.second.empty() ) {
+
2687 if (!radiation_sources.at(s).source_spectrum.empty()) {
+
2688 rho_unique.at(spectrum.first).at(b).at(s) = integrateSpectrum(s, spectrum.second, radiation_bands.at(band).wavebandBounds.x, radiation_bands.at(band).wavebandBounds.y);
+
2689 } else {
+
2690 //source spectrum not provided, assume source intensity is constant over the band
+
2691 rho_unique.at(spectrum.first).at(b).at(s) = integrateSpectrum(spectrum.second, radiation_bands.at(band).wavebandBounds.x, radiation_bands.at(band).wavebandBounds.y)/(radiation_bands.at(band).wavebandBounds.y-radiation_bands.at(band).wavebandBounds.x);
+
2692 }
+
2693 }else{
+
2694 rho_unique.at(spectrum.first).at(b).at(s) = rho_default;
+
2695 }
2696
-
2697 }else {
-
2698
-
2699 //integrate
-
2700 if( !spectrum.second.empty() ) {
-
2701 if (!radiation_sources.at(s).source_spectrum.empty()) {
-
2702 rho_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = integrateSpectrum(s, spectrum.second, camera_response_unique.at(cam).at(b));
-
2703 } else{
-
2704 rho_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = integrateSpectrum(spectrum.second, camera_response_unique.at(cam).at(b));
-
2705 }
-
2706 }else{
-
2707 rho_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = rho_default;
-
2708 }
-
2709
-
2710 }
-
2711
-
2712 cam++;
-
2713 }
-
2714 }
-
2715
-
2716 }
+
2697 //cameras
+
2698 if (Ncameras > 0) {
+
2699 uint cam=0;
+
2700 for (const auto &camera: cameras) {
+
2701
+
2702 if( camera_response_unique.at(cam).at(b).empty() ){
+
2703 rho_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = rho_unique.at(spectrum.first).at(b).at(s);
+
2704
+
2705 }else {
+
2706
+
2707 //integrate
+
2708 if( !spectrum.second.empty() ) {
+
2709 if (!radiation_sources.at(s).source_spectrum.empty()) {
+
2710 rho_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = integrateSpectrum(s, spectrum.second, camera_response_unique.at(cam).at(b));
+
2711 } else{
+
2712 rho_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = integrateSpectrum(spectrum.second, camera_response_unique.at(cam).at(b));
+
2713 }
+
2714 }else{
+
2715 rho_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = rho_default;
+
2716 }
2717
-
2718 }
+
2718 }
2719
-
2720 }
-
2721
-
2722
-
2723 for( const auto &spectrum : surface_spectra_tau ) {//transmissivity
-
2724
-
2725 tau_unique.emplace(spectrum.first, empty);
-
2726 if (Ncameras > 0) {
-
2727 tau_cam_unique.emplace(spectrum.first, empty_cam);
-
2728 }
+
2720 cam++;
+
2721 }
+
2722 }
+
2723
+
2724 }
+
2725
+
2726 }
+
2727
+
2728 }
2729
-
2730 for( uint b=0; b<Nbands; b++ ) {
-
2731 std::string band = labels.at(b);
+
2730
+
2731 for( const auto &spectrum : surface_spectra_tau ) {//transmissivity
2732
-
2733 for (uint s = 0; s < Nsources; s++) {
-
2734
-
2735 //integrate
-
2736 if( radiation_bands.at(band).wavebandBounds.x!=0 && radiation_bands.at(band).wavebandBounds.y!=0 && !spectrum.second.empty()) {
-
2737 if (!radiation_sources.at(s).source_spectrum.empty()) {
-
2738 tau_unique.at(spectrum.first).at(b).at(s) = integrateSpectrum(s, spectrum.second, radiation_bands.at(band).wavebandBounds.x, radiation_bands.at(band).wavebandBounds.y);
-
2739 } else{
-
2740 tau_unique.at(spectrum.first).at(b).at(s) = integrateSpectrum(spectrum.second, radiation_bands.at(band).wavebandBounds.x, radiation_bands.at(band).wavebandBounds.y)/(radiation_bands.at(band).wavebandBounds.y-radiation_bands.at(band).wavebandBounds.x);
-
2741 }
-
2742 }else{
-
2743 tau_unique.at(spectrum.first).at(b).at(s) = tau_default;
-
2744 }
-
2745
-
2746 //cameras
-
2747 if (Ncameras > 0) {
-
2748 uint cam=0;
-
2749 for (const auto &camera: cameras) {
-
2750
-
2751 if( camera_response_unique.at(cam).at(b).empty() ){
-
2752
-
2753 tau_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = tau_unique.at(spectrum.first).at(b).at(s);
-
2754
-
2755 }else {
-
2756
-
2757 //integrate
-
2758 if( !spectrum.second.empty() ) {
-
2759 if (!radiation_sources.at(s).source_spectrum.empty()) {
-
2760 tau_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = integrateSpectrum(s, spectrum.second, camera_response_unique.at(cam).at(b));
-
2761 } else{
-
2762 tau_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = integrateSpectrum(spectrum.second, camera_response_unique.at(cam).at(b));
-
2763 }
-
2764 }else{
-
2765 tau_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = tau_default;
-
2766 }
-
2767
-
2768 }
-
2769
-
2770 cam++;
-
2771 }
-
2772 }
-
2773
-
2774 }
+
2733 tau_unique.emplace(spectrum.first, empty);
+
2734 if (Ncameras > 0) {
+
2735 tau_cam_unique.emplace(spectrum.first, empty_cam);
+
2736 }
+
2737
+
2738 for( uint b=0; b<Nbands; b++ ) {
+
2739 std::string band = labels.at(b);
+
2740
+
2741 for (uint s = 0; s < Nsources; s++) {
+
2742
+
2743 //integrate
+
2744 if( radiation_bands.at(band).wavebandBounds.x!=0 && radiation_bands.at(band).wavebandBounds.y!=0 && !spectrum.second.empty()) {
+
2745 if (!radiation_sources.at(s).source_spectrum.empty()) {
+
2746 tau_unique.at(spectrum.first).at(b).at(s) = integrateSpectrum(s, spectrum.second, radiation_bands.at(band).wavebandBounds.x, radiation_bands.at(band).wavebandBounds.y);
+
2747 } else{
+
2748 tau_unique.at(spectrum.first).at(b).at(s) = integrateSpectrum(spectrum.second, radiation_bands.at(band).wavebandBounds.x, radiation_bands.at(band).wavebandBounds.y)/(radiation_bands.at(band).wavebandBounds.y-radiation_bands.at(band).wavebandBounds.x);
+
2749 }
+
2750 }else{
+
2751 tau_unique.at(spectrum.first).at(b).at(s) = tau_default;
+
2752 }
+
2753
+
2754 //cameras
+
2755 if (Ncameras > 0) {
+
2756 uint cam=0;
+
2757 for (const auto &camera: cameras) {
+
2758
+
2759 if( camera_response_unique.at(cam).at(b).empty() ){
+
2760
+
2761 tau_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = tau_unique.at(spectrum.first).at(b).at(s);
+
2762
+
2763 }else {
+
2764
+
2765 //integrate
+
2766 if( !spectrum.second.empty() ) {
+
2767 if (!radiation_sources.at(s).source_spectrum.empty()) {
+
2768 tau_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = integrateSpectrum(s, spectrum.second, camera_response_unique.at(cam).at(b));
+
2769 } else{
+
2770 tau_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = integrateSpectrum(spectrum.second, camera_response_unique.at(cam).at(b));
+
2771 }
+
2772 }else{
+
2773 tau_cam_unique.at(spectrum.first).at(b).at(s).at(cam) = tau_default;
+
2774 }
2775
-
2776 }
+
2776 }
2777
-
2778 }
-
2779
-
2780 for (size_t u = 0; u < Nprimitives; u++) {
+
2778 cam++;
+
2779 }
+
2780 }
2781
-
2782 uint UUID = context_UUIDs.at(u);
+
2782 }
2783
-
2784 helios::PrimitiveType type = context->getPrimitiveType(UUID);
+
2784 }
2785
-
2786 if (type == helios::PRIMITIVE_TYPE_VOXEL) {
+
2786 }
2787
-
2788// // NOTE: This is a little confusing - for volumes of participating media, we're going to use the "rho" variable to store the absorption coefficient and use the "tau" variable to store the scattering coefficient. This is to save on memory so we don't have to define separate arrays.
-
2789//
-
2790// // Absorption coefficient
-
2791//
-
2792// prop = "attenuation_coefficient_" + band;
-
2793//
-
2794// if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
-
2795// context->getPrimitiveData(UUID, prop.c_str(), rho.at(u).at(b));
-
2796// } else {
-
2797// rho.at(u).at(b) = kappa_default;
-
2798// context->setPrimitiveData(UUID, prop.c_str(), helios::HELIOS_TYPE_FLOAT, 1, &kappa_default);
-
2799// }
-
2800//
-
2801// if (rho.at(u).at(b) < 0) {
-
2802// rho.at(u).at(b) = 0.f;
-
2803// if (message_flag) {
-
2804// std::cout
-
2805// << "WARNING (RadiationModel): absorption coefficient cannot be less than 0. Clamping to 0 for band "
-
2806// << band << "." << std::endl;
-
2807// }
-
2808// } else if (rho.at(u).at(b) > 1.f) {
-
2809// rho.at(u).at(b) = 1.f;
-
2810// if (message_flag) {
-
2811// std::cout
-
2812// << "WARNING (RadiationModel): absorption coefficient cannot be greater than 1. Clamping to 1 for band "
-
2813// << band << "." << std::endl;
-
2814// }
-
2815// }
-
2816//
-
2817// // Scattering coefficient
-
2818//
-
2819// prop = "scattering_coefficient_" + band;
-
2820//
-
2821// if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
-
2822// context->getPrimitiveData(UUID, prop.c_str(), tau[u]);
-
2823// } else {
-
2824// tau.at(u).at(b) = sigmas_default;
-
2825// context->setPrimitiveData(UUID, prop.c_str(), helios::HELIOS_TYPE_FLOAT, 1, &sigmas_default);
-
2826// }
-
2827//
-
2828// if (tau.at(u).at(b) < 0) {
-
2829// tau.at(u).at(b) = 0.f;
-
2830// if (message_flag) {
-
2831// std::cout
-
2832// << "WARNING (RadiationModel): scattering coefficient cannot be less than 0. Clamping to 0 for band "
-
2833// << band << "." << std::endl;
-
2834// }
-
2835// } else if (tau.at(u).at(b) > 1.f) {
-
2836// tau.at(u).at(b) = 1.f;
-
2837// if (message_flag) {
-
2838// std::cout
-
2839// << "WARNING (RadiationModel): scattering coefficient cannot be greater than 1. Clamping to 1 for band "
-
2840// << band << "." << std::endl;
-
2841// }
-
2842// }
-
2843
-
2844 } else { //other than voxels
-
2845
-
2846 // Reflectivity
-
2847
-
2848 //check for primitive data of form "reflectivity_spectrum" that can be used to calculate reflectivity
-
2849 std::string spectrum_label;
-
2850 if (context->doesPrimitiveDataExist(UUID, "reflectivity_spectrum")) {
-
2851 if (context->getPrimitiveDataType(UUID, "reflectivity_spectrum") == HELIOS_TYPE_STRING) {
-
2852 context->getPrimitiveData(UUID, "reflectivity_spectrum", spectrum_label);
-
2853 }
-
2854 }
+
2788 for (size_t u = 0; u < Nprimitives; u++) {
+
2789
+
2790 uint UUID = context_UUIDs.at(u);
+
2791
+
2792 helios::PrimitiveType type = context->getPrimitiveType(UUID);
+
2793
+
2794 if (type == helios::PRIMITIVE_TYPE_VOXEL) {
+
2795
+
2796// // NOTE: This is a little confusing - for volumes of participating media, we're going to use the "rho" variable to store the absorption coefficient and use the "tau" variable to store the scattering coefficient. This is to save on memory so we don't have to define separate arrays.
+
2797//
+
2798// // Absorption coefficient
+
2799//
+
2800// prop = "attenuation_coefficient_" + band;
+
2801//
+
2802// if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
+
2803// context->getPrimitiveData(UUID, prop.c_str(), rho.at(u).at(b));
+
2804// } else {
+
2805// rho.at(u).at(b) = kappa_default;
+
2806// context->setPrimitiveData(UUID, prop.c_str(), helios::HELIOS_TYPE_FLOAT, 1, &kappa_default);
+
2807// }
+
2808//
+
2809// if (rho.at(u).at(b) < 0) {
+
2810// rho.at(u).at(b) = 0.f;
+
2811// if (message_flag) {
+
2812// std::cout
+
2813// << "WARNING (RadiationModel): absorption coefficient cannot be less than 0. Clamping to 0 for band "
+
2814// << band << "." << std::endl;
+
2815// }
+
2816// } else if (rho.at(u).at(b) > 1.f) {
+
2817// rho.at(u).at(b) = 1.f;
+
2818// if (message_flag) {
+
2819// std::cout
+
2820// << "WARNING (RadiationModel): absorption coefficient cannot be greater than 1. Clamping to 1 for band "
+
2821// << band << "." << std::endl;
+
2822// }
+
2823// }
+
2824//
+
2825// // Scattering coefficient
+
2826//
+
2827// prop = "scattering_coefficient_" + band;
+
2828//
+
2829// if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
+
2830// context->getPrimitiveData(UUID, prop.c_str(), tau[u]);
+
2831// } else {
+
2832// tau.at(u).at(b) = sigmas_default;
+
2833// context->setPrimitiveData(UUID, prop.c_str(), helios::HELIOS_TYPE_FLOAT, 1, &sigmas_default);
+
2834// }
+
2835//
+
2836// if (tau.at(u).at(b) < 0) {
+
2837// tau.at(u).at(b) = 0.f;
+
2838// if (message_flag) {
+
2839// std::cout
+
2840// << "WARNING (RadiationModel): scattering coefficient cannot be less than 0. Clamping to 0 for band "
+
2841// << band << "." << std::endl;
+
2842// }
+
2843// } else if (tau.at(u).at(b) > 1.f) {
+
2844// tau.at(u).at(b) = 1.f;
+
2845// if (message_flag) {
+
2846// std::cout
+
2847// << "WARNING (RadiationModel): scattering coefficient cannot be greater than 1. Clamping to 1 for band "
+
2848// << band << "." << std::endl;
+
2849// }
+
2850// }
+
2851
+
2852 } else { //other than voxels
+
2853
+
2854 // Reflectivity
2855
-
2856 uint b = 0;
-
2857 for (const auto &band: labels) {
-
2858
-
2859 //check for primitive data of form "reflectivity_bandname"
-
2860 prop = "reflectivity_" + band;
-
2861
-
2862 float rho_s = rho_default;
-
2863 if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
-
2864 context->getPrimitiveData(UUID, prop.c_str(), rho_s);
-
2865 }
+
2856 //check for primitive data of form "reflectivity_spectrum" that can be used to calculate reflectivity
+
2857 std::string spectrum_label;
+
2858 if (context->doesPrimitiveDataExist(UUID, "reflectivity_spectrum")) {
+
2859 if (context->getPrimitiveDataType(UUID, "reflectivity_spectrum") == HELIOS_TYPE_STRING) {
+
2860 context->getPrimitiveData(UUID, "reflectivity_spectrum", spectrum_label);
+
2861 }
+
2862 }
+
2863
+
2864 uint b = 0;
+
2865 for (const auto &band: labels) {
2866
-
2867 for (uint s = 0; s < Nsources; s++) {
-
2868 if (!spectrum_label.empty() && context->doesGlobalDataExist(spectrum_label.c_str())) {
+
2867 //check for primitive data of form "reflectivity_bandname"
+
2868 prop = "reflectivity_" + band;
2869
-
2870 rho.at(s).at(u).at(b) = rho_unique.at(spectrum_label).at(b).at(s);
-
2871
-
2872 //cameras
-
2873 for( uint cam=0; cam<Ncameras; cam++ ){
-
2874 rho_cam.at(s).at(u).at(b).at(cam) = rho_cam_unique.at(spectrum_label).at(b).at(s).at(cam);
-
2875 }
-
2876
-
2877 //assign default value if there is no primitive data or spectral data
-
2878 } else {
-
2879 rho.at(s).at(u).at(b) = rho_s;
-
2880
-
2881 //cameras
-
2882 for( uint cam=0; cam<Ncameras; cam++ ){
-
2883 rho_cam.at(s).at(u).at(b).at(cam) = rho_s;
-
2884 }
-
2885 }
-
2886
-
2887 //error checking
-
2888 if (rho.at(s).at(u).at(b) < 0) {
-
2889 rho.at(s).at(u).at(b) = 0.f;
-
2890 if (message_flag) {
-
2891 std::cout << "WARNING (RadiationModel): reflectivity cannot be less than 0. Clamping to 0 for band " << band << "." << std::flush;
+
2870 float rho_s = rho_default;
+
2871 if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
+
2872 context->getPrimitiveData(UUID, prop.c_str(), rho_s);
+
2873 }
+
2874
+
2875 for (uint s = 0; s < Nsources; s++) {
+
2876 if (!spectrum_label.empty() && context->doesGlobalDataExist(spectrum_label.c_str())) {
+
2877
+
2878 rho.at(s).at(u).at(b) = rho_unique.at(spectrum_label).at(b).at(s);
+
2879
+
2880 //cameras
+
2881 for( uint cam=0; cam<Ncameras; cam++ ){
+
2882 rho_cam.at(s).at(u).at(b).at(cam) = rho_cam_unique.at(spectrum_label).at(b).at(s).at(cam);
+
2883 }
+
2884
+
2885 //assign default value if there is no primitive data or spectral data
+
2886 } else {
+
2887 rho.at(s).at(u).at(b) = rho_s;
+
2888
+
2889 //cameras
+
2890 for( uint cam=0; cam<Ncameras; cam++ ){
+
2891 rho_cam.at(s).at(u).at(b).at(cam) = rho_s;
2892 }
-
2893 } else if (rho.at(s).at(u).at(b) > 1.f) {
-
2894 rho.at(s).at(u).at(b) = 1.f;
-
2895 if (message_flag) {
-
2896 std::cout << "WARNING (RadiationModel): reflectivity cannot be greater than 1. Clamping to 1 for band " << band << "." << std::flush;
-
2897 }
-
2898 }
-
2899 if( rho.at(s).at(u).at(b)!=0 ){
-
2900 scattering_iterations_needed.at(b) = true;
-
2901 }
-
2902 for( auto &odata : output_prim_data ) {
-
2903 if ( odata == "reflectivity" ){
-
2904 context->setPrimitiveData( UUID, ("reflectivity_" + std::to_string(s) + "_" + band).c_str(), rho.at(s).at(u).at(b) );
+
2893 }
+
2894
+
2895 //error checking
+
2896 if (rho.at(s).at(u).at(b) < 0) {
+
2897 rho.at(s).at(u).at(b) = 0.f;
+
2898 if (message_flag) {
+
2899 std::cout << "WARNING (RadiationModel): reflectivity cannot be less than 0. Clamping to 0 for band " << band << "." << std::flush;
+
2900 }
+
2901 } else if (rho.at(s).at(u).at(b) > 1.f) {
+
2902 rho.at(s).at(u).at(b) = 1.f;
+
2903 if (message_flag) {
+
2904 std::cout << "WARNING (RadiationModel): reflectivity cannot be greater than 1. Clamping to 1 for band " << band << "." << std::flush;
2905 }
2906 }
-
2907
-
2908 }
-
2909 b++;
-
2910 }
-
2911
-
2912 // Transmissivity
-
2913
-
2914 //check for primitive data of form "transmissivity_spectrum" that can be used to calculate transmissivity
-
2915 spectrum_label.resize(0);
-
2916 if (context->doesPrimitiveDataExist(UUID, "transmissivity_spectrum")) {
-
2917 if (context->getPrimitiveDataType(UUID, "transmissivity_spectrum") == HELIOS_TYPE_STRING) {
-
2918 context->getPrimitiveData(UUID, "transmissivity_spectrum", spectrum_label);
-
2919 }
-
2920 }
+
2907 if( rho.at(s).at(u).at(b)!=0 ){
+
2908 scattering_iterations_needed.at(b) = true;
+
2909 }
+
2910 for( auto &odata : output_prim_data ) {
+
2911 if ( odata == "reflectivity" ){
+
2912 context->setPrimitiveData( UUID, ("reflectivity_" + std::to_string(s) + "_" + band).c_str(), rho.at(s).at(u).at(b) );
+
2913 }
+
2914 }
+
2915
+
2916 }
+
2917 b++;
+
2918 }
+
2919
+
2920 // Transmissivity
2921
-
2922 b = 0;
-
2923 for ( const auto &band: labels ) {
-
2924
-
2925 //check for primitive data of form "transmissivity_bandname"
-
2926 prop = "transmissivity_" + band;
-
2927
-
2928 float tau_s = tau_default;
-
2929 if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
-
2930 context->getPrimitiveData(UUID, prop.c_str(), tau_s);
-
2931 }
+
2922 //check for primitive data of form "transmissivity_spectrum" that can be used to calculate transmissivity
+
2923 spectrum_label.resize(0);
+
2924 if (context->doesPrimitiveDataExist(UUID, "transmissivity_spectrum")) {
+
2925 if (context->getPrimitiveDataType(UUID, "transmissivity_spectrum") == HELIOS_TYPE_STRING) {
+
2926 context->getPrimitiveData(UUID, "transmissivity_spectrum", spectrum_label);
+
2927 }
+
2928 }
+
2929
+
2930 b = 0;
+
2931 for ( const auto &band: labels ) {
2932
-
2933 for (uint s = 0; s < Nsources; s++) {
-
2934 if (!spectrum_label.empty() && context->doesGlobalDataExist(spectrum_label.c_str())) {
-
2935 tau.at(s).at(u).at(b) = tau_unique.at(spectrum_label).at(b).at(s);
-
2936
-
2937 //cameras
-
2938 for( uint cam=0; cam<Ncameras; cam++ ){
-
2939 tau_cam.at(s).at(u).at(b).at(cam) = tau_cam_unique.at(spectrum_label).at(b).at(s).at(cam);
-
2940 }
-
2941
-
2942 //assign default value if there is no primitive data or spectral data
-
2943 } else {
-
2944 tau.at(s).at(u).at(b) = tau_s;
-
2945
-
2946 //cameras
-
2947 for( uint cam=0; cam<Ncameras; cam++ ){
-
2948 tau_cam.at(s).at(u).at(b).at(cam) = tau_s;
-
2949 }
-
2950 }
-
2951
-
2952 //error checking
-
2953 if (tau.at(s).at(u).at(b) < 0) {
-
2954 tau.at(s).at(u).at(b) = 0.f;
-
2955 if (message_flag) {
-
2956 std::cout << "WARNING (RadiationModel): transmissivity cannot be less than 0. Clamping to 0 for band " << band << "." << std::endl;
+
2933 //check for primitive data of form "transmissivity_bandname"
+
2934 prop = "transmissivity_" + band;
+
2935
+
2936 float tau_s = tau_default;
+
2937 if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
+
2938 context->getPrimitiveData(UUID, prop.c_str(), tau_s);
+
2939 }
+
2940
+
2941 for (uint s = 0; s < Nsources; s++) {
+
2942 if (!spectrum_label.empty() && context->doesGlobalDataExist(spectrum_label.c_str())) {
+
2943 tau.at(s).at(u).at(b) = tau_unique.at(spectrum_label).at(b).at(s);
+
2944
+
2945 //cameras
+
2946 for( uint cam=0; cam<Ncameras; cam++ ){
+
2947 tau_cam.at(s).at(u).at(b).at(cam) = tau_cam_unique.at(spectrum_label).at(b).at(s).at(cam);
+
2948 }
+
2949
+
2950 //assign default value if there is no primitive data or spectral data
+
2951 } else {
+
2952 tau.at(s).at(u).at(b) = tau_s;
+
2953
+
2954 //cameras
+
2955 for( uint cam=0; cam<Ncameras; cam++ ){
+
2956 tau_cam.at(s).at(u).at(b).at(cam) = tau_s;
2957 }
-
2958 } else if (tau.at(s).at(u).at(b) > 1.f) {
-
2959 tau.at(s).at(u).at(b) = 1.f;
-
2960 if (message_flag) {
-
2961 std::cout << "WARNING (RadiationModel): transmissivity cannot be greater than 1. Clamping to 1 for band " << band << "." << std::endl;
-
2962 }
-
2963 }
-
2964 if( tau.at(s).at(u).at(b)!=0 ){
-
2965 scattering_iterations_needed.at(b) = true;
-
2966 }
-
2967 for( auto &odata : output_prim_data ) {
-
2968 if (odata == "transmissivity" ){
-
2969 context->setPrimitiveData( UUID, ("transmissivity_" + std::to_string(s) + "_" + band).c_str(), tau.at(s).at(u).at(b) );
+
2958 }
+
2959
+
2960 //error checking
+
2961 if (tau.at(s).at(u).at(b) < 0) {
+
2962 tau.at(s).at(u).at(b) = 0.f;
+
2963 if (message_flag) {
+
2964 std::cout << "WARNING (RadiationModel): transmissivity cannot be less than 0. Clamping to 0 for band " << band << "." << std::endl;
+
2965 }
+
2966 } else if (tau.at(s).at(u).at(b) > 1.f) {
+
2967 tau.at(s).at(u).at(b) = 1.f;
+
2968 if (message_flag) {
+
2969 std::cout << "WARNING (RadiationModel): transmissivity cannot be greater than 1. Clamping to 1 for band " << band << "." << std::endl;
2970 }
2971 }
-
2972 }
-
2973 b++;
-
2974 }
-
2975
-
2976 // Emissivity (only for error checking)
-
2977
-
2978 b = 0;
-
2979 for (const auto &band: labels) {
-
2980
-
2981 prop = "emissivity_" + band;
-
2982
-
2983 if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
-
2984 context->getPrimitiveData(UUID, prop.c_str(), eps);
-
2985 } else {
-
2986 eps = eps_default;
-
2987 }
+
2972 if( tau.at(s).at(u).at(b)!=0 ){
+
2973 scattering_iterations_needed.at(b) = true;
+
2974 }
+
2975 for( auto &odata : output_prim_data ) {
+
2976 if (odata == "transmissivity" ){
+
2977 context->setPrimitiveData( UUID, ("transmissivity_" + std::to_string(s) + "_" + band).c_str(), tau.at(s).at(u).at(b) );
+
2978 }
+
2979 }
+
2980 }
+
2981 b++;
+
2982 }
+
2983
+
2984 // Emissivity (only for error checking)
+
2985
+
2986 b = 0;
+
2987 for (const auto &band: labels) {
2988
-
2989 if (eps < 0) {
-
2990 eps = 0.f;
-
2991 if (message_flag) {
-
2992 std::cout << "WARNING (RadiationModel): emissivity cannot be less than 0. Clamping to 0 for band " << band << "." << std::endl;
-
2993 }
-
2994 } else if (eps > 1.f) {
-
2995 eps = 1.f;
-
2996 if (message_flag) {
-
2997 std::cout << "WARNING (RadiationModel): emissivity cannot be greater than 1. Clamping to 1 for band " << band << "." << std::endl;
-
2998 }
-
2999 }
-
3000 if( eps!=1 ){
-
3001 scattering_iterations_needed.at(b) = true;
-
3002 }
-
3003
-
3004 assert(doesBandExist(band));
-
3005
-
3006 for (uint s = 0; s < Nsources; s++) {
-
3007 if (radiation_bands.at(band).emissionFlag) { //emission enabled
-
3008 if (eps != 1.f && rho.at(s).at(u).at(b) == 0 && tau.at(s).at(u).at(b) == 0) {
-
3009 rho.at(s).at(u).at(b) = 1.f - eps;
-
3010 } else if (eps + tau.at(s).at(u).at(b) + rho.at(s).at(u).at(b) != 1.f && eps > 0.f) {
- -
3012 "ERROR (RadiationModel): emissivity, transmissivity, and reflectivity must sum to 1 to ensure energy conservation. Band " +
-
3013 band + ", Primitive #" + std::to_string(UUID) + ": eps=" +
-
3014 std::to_string(eps) + ", tau=" + std::to_string(tau.at(s).at(u).at(b)) +
-
3015 ", rho=" + std::to_string(rho.at(s).at(u).at(b)) +
-
3016 ". It is also possible that you forgot to disable emission for this band.");
-
3017 } else if (radiation_bands.at(band).scatteringDepth == 0 && eps != 1.f) {
-
3018 eps = 1.f;
-
3019 rho.at(s).at(u).at(b) = 0.f;
-
3020 tau.at(s).at(u).at(b) = 0.f;
-
3021 }
-
3022 } else if (tau.at(s).at(u).at(b) + rho.at(s).at(u).at(b) > 1.f) {
- -
3024 "ERROR (RadiationModel): transmissivity and reflectivity cannot sum to greater than 1 ensure energy conservation. Band " +
-
3025 band + ", Primitive #" + std::to_string(UUID) + ": eps=" +
-
3026 std::to_string(eps) + ", tau=" + std::to_string(tau.at(s).at(u).at(b)) +
-
3027 ", rho=" + std::to_string(rho.at(s).at(u).at(b)) +
-
3028 ". It is also possible that you forgot to disable emission for this band.");
-
3029 }
-
3030 }
-
3031 b++;
-
3032 }
-
3033 }
-
3034 }
-
3035
-
3036 initializeBuffer1Df(rho_RTbuffer, flatten(rho));
-
3037 initializeBuffer1Df(tau_RTbuffer, flatten(tau));
-
3038
-
3039 initializeBuffer1Df(rho_cam_RTbuffer, flatten(rho_cam));
-
3040 initializeBuffer1Df(tau_cam_RTbuffer, flatten(tau_cam));
-
3041
-
3042 if( message_flag ) {
-
3043 std::cout << "done\n";
-
3044 }
-
3045
-
3046}
-
3047
-
3048std::vector<helios::vec2> RadiationModel::loadSpectralData( const std::string &global_data_label ) const{
+
2989 prop = "emissivity_" + band;
+
2990
+
2991 if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
+
2992 context->getPrimitiveData(UUID, prop.c_str(), eps);
+
2993 } else {
+
2994 eps = eps_default;
+
2995 }
+
2996
+
2997 if (eps < 0) {
+
2998 eps = 0.f;
+
2999 if (message_flag) {
+
3000 std::cout << "WARNING (RadiationModel): emissivity cannot be less than 0. Clamping to 0 for band " << band << "." << std::endl;
+
3001 }
+
3002 } else if (eps > 1.f) {
+
3003 eps = 1.f;
+
3004 if (message_flag) {
+
3005 std::cout << "WARNING (RadiationModel): emissivity cannot be greater than 1. Clamping to 1 for band " << band << "." << std::endl;
+
3006 }
+
3007 }
+
3008 if( eps!=1 ){
+
3009 scattering_iterations_needed.at(b) = true;
+
3010 }
+
3011
+
3012 assert(doesBandExist(band));
+
3013
+
3014 for (uint s = 0; s < Nsources; s++) {
+
3015 if (radiation_bands.at(band).emissionFlag) { //emission enabled
+
3016 if (eps != 1.f && rho.at(s).at(u).at(b) == 0 && tau.at(s).at(u).at(b) == 0) {
+
3017 rho.at(s).at(u).at(b) = 1.f - eps;
+
3018 } else if (eps + tau.at(s).at(u).at(b) + rho.at(s).at(u).at(b) != 1.f && eps > 0.f) {
+ +
3020 "ERROR (RadiationModel): emissivity, transmissivity, and reflectivity must sum to 1 to ensure energy conservation. Band " +
+
3021 band + ", Primitive #" + std::to_string(UUID) + ": eps=" +
+
3022 std::to_string(eps) + ", tau=" + std::to_string(tau.at(s).at(u).at(b)) +
+
3023 ", rho=" + std::to_string(rho.at(s).at(u).at(b)) +
+
3024 ". It is also possible that you forgot to disable emission for this band.");
+
3025 } else if (radiation_bands.at(band).scatteringDepth == 0 && eps != 1.f) {
+
3026 eps = 1.f;
+
3027 rho.at(s).at(u).at(b) = 0.f;
+
3028 tau.at(s).at(u).at(b) = 0.f;
+
3029 }
+
3030 } else if (tau.at(s).at(u).at(b) + rho.at(s).at(u).at(b) > 1.f) {
+ +
3032 "ERROR (RadiationModel): transmissivity and reflectivity cannot sum to greater than 1 ensure energy conservation. Band " +
+
3033 band + ", Primitive #" + std::to_string(UUID) + ": eps=" +
+
3034 std::to_string(eps) + ", tau=" + std::to_string(tau.at(s).at(u).at(b)) +
+
3035 ", rho=" + std::to_string(rho.at(s).at(u).at(b)) +
+
3036 ". It is also possible that you forgot to disable emission for this band.");
+
3037 }
+
3038 }
+
3039 b++;
+
3040 }
+
3041 }
+
3042 }
+
3043
+
3044 initializeBuffer1Df(rho_RTbuffer, flatten(rho));
+
3045 initializeBuffer1Df(tau_RTbuffer, flatten(tau));
+
3046
+
3047 initializeBuffer1Df(rho_cam_RTbuffer, flatten(rho_cam));
+
3048 initializeBuffer1Df(tau_cam_RTbuffer, flatten(tau_cam));
3049
-
3050 std::vector<helios::vec2> spectrum;
-
3051
-
3052 if( !context->doesGlobalDataExist(global_data_label.c_str()) ){
+
3050 if( message_flag ) {
+
3051 std::cout << "done\n";
+
3052 }
3053
-
3054 //check if spectral data exists in any of the library files
-
3055 bool data_found = false;
-
3056 for( const auto &file : spectral_library_files ){
-
3057 if( Context::scanXMLForTag( file, "globaldata_vec2", global_data_label ) ){
-
3058 context->loadXML( file.c_str(), true );
-
3059 data_found = true;
-
3060 break;
-
3061 }
-
3062 }
-
3063
-
3064 if( !data_found ) {
-
3065 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Global data for spectrum '" + global_data_label + "' could not be found.");
-
3066 }
-
3067 }
-
3068
-
3069 if( context->getGlobalDataType(global_data_label.c_str()) != HELIOS_TYPE_VEC2 ){
-
3070 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Global data for spectrum '" + global_data_label + "' is not of type HELIOS_TYPE_VEC2.");
-
3071 }
-
3072
-
3073 context->getGlobalData(global_data_label.c_str(), spectrum);
-
3074
-
3075 //validate spectrum
-
3076 if( spectrum.empty() ){
-
3077 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Global data for spectrum '" + global_data_label + "' is empty.");
-
3078 }
-
3079 for( auto s=0; s<spectrum.size(); s++ ) {
-
3080 //check that wavelengths are monotonic
-
3081 if( s>0 && spectrum.at(s).x<=spectrum.at(s-1).x ) {
-
3082 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Source spectral data validation failed. Wavelengths must increase monotonically.");
-
3083 }
-
3084 //check that wavelength is within a reasonable range
-
3085 if( spectrum.at(s).x<0 || spectrum.at(s).x>100000 ) {
-
3086 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Source spectral data validation failed. Wavelength value of " + std::to_string(spectrum.at(s).x) + " appears to be erroneous.");
-
3087 }
-
3088 //check that flux is non-negative
-
3089 if( spectrum.at(s).y<0 ) {
-
3090 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Source spectral data validation failed. Flux value at wavelength of " + std::to_string(spectrum.at(s).x) + " appears is negative.");
+
3054}
+
3055
+
3056std::vector<helios::vec2> RadiationModel::loadSpectralData( const std::string &global_data_label ) const{
+
3057
+
3058 std::vector<helios::vec2> spectrum;
+
3059
+
3060 if( !context->doesGlobalDataExist(global_data_label.c_str()) ){
+
3061
+
3062 //check if spectral data exists in any of the library files
+
3063 bool data_found = false;
+
3064 for( const auto &file : spectral_library_files ){
+
3065 if( Context::scanXMLForTag( file, "globaldata_vec2", global_data_label ) ){
+
3066 context->loadXML( file.c_str(), true );
+
3067 data_found = true;
+
3068 break;
+
3069 }
+
3070 }
+
3071
+
3072 if( !data_found ) {
+
3073 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Global data for spectrum '" + global_data_label + "' could not be found.");
+
3074 }
+
3075 }
+
3076
+
3077 if( context->getGlobalDataType(global_data_label.c_str()) != HELIOS_TYPE_VEC2 ){
+
3078 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Global data for spectrum '" + global_data_label + "' is not of type HELIOS_TYPE_VEC2.");
+
3079 }
+
3080
+
3081 context->getGlobalData(global_data_label.c_str(), spectrum);
+
3082
+
3083 //validate spectrum
+
3084 if( spectrum.empty() ){
+
3085 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Global data for spectrum '" + global_data_label + "' is empty.");
+
3086 }
+
3087 for( auto s=0; s<spectrum.size(); s++ ) {
+
3088 //check that wavelengths are monotonic
+
3089 if( s>0 && spectrum.at(s).x<=spectrum.at(s-1).x ) {
+
3090 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Source spectral data validation failed. Wavelengths must increase monotonically.");
3091 }
-
3092 }
-
3093
-
3094 return spectrum;
-
3095
-
3096}
-
3097
-
-
3098void RadiationModel::runBand( const std::string &label ) {
-
3099 std::vector<std::string> labels{label};
-
3100 runBand(labels);
-
3101}
+
3092 //check that wavelength is within a reasonable range
+
3093 if( spectrum.at(s).x<0 || spectrum.at(s).x>100000 ) {
+
3094 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Source spectral data validation failed. Wavelength value of " + std::to_string(spectrum.at(s).x) + " appears to be erroneous.");
+
3095 }
+
3096 //check that flux is non-negative
+
3097 if( spectrum.at(s).y<0 ) {
+
3098 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Source spectral data validation failed. Flux value at wavelength of " + std::to_string(spectrum.at(s).x) + " appears is negative.");
+
3099 }
+
3100 }
+
3101
+
3102 return spectrum;
+
3103
+
3104}
+
3105
+
+
3106void RadiationModel::runBand( const std::string &label ) {
+
3107 std::vector<std::string> labels{label};
+
3108 runBand(labels);
+
3109}
-
3102
-
-
3103void RadiationModel::runBand( const std::vector<std::string> &label ) {
-
3104
-
3105 //----- VERIFICATIONS -----//
-
3106
-
3107 //Check to make sure some geometry was added to the context
-
3108 if( context->getPrimitiveCount()==0 ){
-
3109 std::cerr << "WARNING (RadiationModel::runBand): No geometry was added to the context. There is nothing to simulate...exiting." << std::endl;
-
3110 return;
-
3111 }
+
3110
+
+
3111void RadiationModel::runBand( const std::vector<std::string> &label ) {
3112
-
3113 //Check to make sure geometry was built in OptiX
-
3114 if( !isgeometryinitialized ){
- -
3116 }
-
3117
-
3118 for( const std::string &band : label ){
-
3119 if( !doesBandExist(band) ){
-
3120 helios_runtime_error("ERROR (RadiationModel::runBand): Cannot run band " + band + " because it is not a valid band. Use addRadiationBand() function to add the band.");
-
3121 }
-
3122 }
-
3123
-
3124 //if there are no radiation sources in the simulation, add at least one but with zero fluxes
-
3125 if( radiation_sources.empty() ){
- -
3127 }
-
3128
-
3129 for( const auto &band : label ) {
-
3130 if (!radiation_bands.at(band).radiativepropertiesinitialized) {
-
3131 updateRadiativeProperties(label);
-
3132 break;
-
3133 }
-
3134 }
-
3135
-
3136 //Set the number of radiative bands
-
3137 size_t Nbands = label.size();
-
3138
-
3139 RT_CHECK_ERROR( rtVariableSet1ui( Nbands_RTvariable, Nbands ) );
-
3140
-
3141 //Run all bands by default
-
3142 std::vector<char> band_launch_flag(Nbands);
-
3143 for( uint b=0; b<Nbands; b++ ){
-
3144 band_launch_flag.at(b) = 1;
-
3145 }
-
3146 initializeBuffer1Dchar( band_launch_flag_RTbuffer, band_launch_flag );
-
3147
-
3148 //Set the number of Context primitives
-
3149 size_t Nobjects = primitiveID.size();
-
3150 size_t Nprimitives = context_UUIDs.size();
-
3151 RT_CHECK_ERROR( rtVariableSet1ui( Nprimitives_RTvariable, Nprimitives ) );
-
3152
-
3153 //Set the random number seed
-
3154 RT_CHECK_ERROR( rtVariableSet1ui( random_seed_RTvariable, std::chrono::system_clock::now().time_since_epoch().count() ) );
+
3113 //----- VERIFICATIONS -----//
+
3114
+
3115 //Check to make sure some geometry was added to the context
+
3116 if( context->getPrimitiveCount()==0 ){
+
3117 std::cerr << "WARNING (RadiationModel::runBand): No geometry was added to the context. There is nothing to simulate...exiting." << std::endl;
+
3118 return;
+
3119 }
+
3120
+
3121 //Check to make sure geometry was built in OptiX
+
3122 if( !isgeometryinitialized ){
+ +
3124 }
+
3125
+
3126 for( const std::string &band : label ){
+
3127 if( !doesBandExist(band) ){
+
3128 helios_runtime_error("ERROR (RadiationModel::runBand): Cannot run band " + band + " because it is not a valid band. Use addRadiationBand() function to add the band.");
+
3129 }
+
3130 }
+
3131
+
3132 //if there are no radiation sources in the simulation, add at least one but with zero fluxes
+
3133 if( radiation_sources.empty() ){
+ +
3135 }
+
3136
+
3137 for( const auto &band : label ) {
+
3138 if (!radiation_bands.at(band).radiativepropertiesinitialized) {
+
3139 updateRadiativeProperties(label);
+
3140 break;
+
3141 }
+
3142 }
+
3143
+
3144 //Set the number of radiative bands
+
3145 size_t Nbands = label.size();
+
3146
+
3147 RT_CHECK_ERROR( rtVariableSet1ui( Nbands_RTvariable, Nbands ) );
+
3148
+
3149 //Run all bands by default
+
3150 std::vector<char> band_launch_flag(Nbands);
+
3151 for( uint b=0; b<Nbands; b++ ){
+
3152 band_launch_flag.at(b) = 1;
+
3153 }
+
3154 initializeBuffer1Dchar( band_launch_flag_RTbuffer, band_launch_flag );
3155
-
3156 //Number of external radiation sources
-
3157 uint Nsources = radiation_sources.size();
-
3158 RT_CHECK_ERROR( rtVariableSet1ui( Nsources_RTvariable, Nsources ) );
-
3159
-
3160 //Set periodic boundary condition (if applicable)
-
3161 RT_CHECK_ERROR( rtVariableSet2f( periodic_flag_RTvariable, periodic_flag.x, periodic_flag.y ));
-
3162
-
3163 //Number of radiation cameras
-
3164 uint Ncameras = cameras.size();
-
3165 RT_CHECK_ERROR( rtVariableSet1ui( Ncameras_RTvariable, Ncameras ) );
-
3166
-
3167 //Set scattering depth for each band
-
3168 std::vector<uint> scattering_depth(Nbands);
-
3169 bool scatteringenabled = false;
-
3170 for( auto b=0; b<Nbands; b++ ){
-
3171 scattering_depth.at(b) = radiation_bands.at(label.at(b)).scatteringDepth;
-
3172 if( scattering_depth.at(b)>0 ){
-
3173 scatteringenabled=true;
-
3174 }
-
3175 }
-
3176 initializeBuffer1Dui( max_scatters_RTbuffer, scattering_depth );
-
3177
-
3178 //Issue warning if rho>0, tau>0, or eps<1
-
3179 for( int b=0; b<Nbands; b++ ){
-
3180 if( scattering_depth.at(b)==0 && scattering_iterations_needed.at(b) ){
-
3181 std::cout << "WARNING (RadiationModel::runBand): Surface radiative properties for band " << label.at(b) << " are set to non-default values, but scattering iterations are disabled. Surface radiative properties will be ignored unless scattering depth is non-zero." << std::endl;
+
3156 //Set the number of Context primitives
+
3157 size_t Nobjects = primitiveID.size();
+
3158 size_t Nprimitives = context_UUIDs.size();
+
3159 RT_CHECK_ERROR( rtVariableSet1ui( Nprimitives_RTvariable, Nprimitives ) );
+
3160
+
3161 //Set the random number seed
+
3162 RT_CHECK_ERROR( rtVariableSet1ui( random_seed_RTvariable, std::chrono::system_clock::now().time_since_epoch().count() ) );
+
3163
+
3164 //Number of external radiation sources
+
3165 uint Nsources = radiation_sources.size();
+
3166 RT_CHECK_ERROR( rtVariableSet1ui( Nsources_RTvariable, Nsources ) );
+
3167
+
3168 //Set periodic boundary condition (if applicable)
+
3169 RT_CHECK_ERROR( rtVariableSet2f( periodic_flag_RTvariable, periodic_flag.x, periodic_flag.y ));
+
3170
+
3171 //Number of radiation cameras
+
3172 uint Ncameras = cameras.size();
+
3173 RT_CHECK_ERROR( rtVariableSet1ui( Ncameras_RTvariable, Ncameras ) );
+
3174
+
3175 //Set scattering depth for each band
+
3176 std::vector<uint> scattering_depth(Nbands);
+
3177 bool scatteringenabled = false;
+
3178 for( auto b=0; b<Nbands; b++ ){
+
3179 scattering_depth.at(b) = radiation_bands.at(label.at(b)).scatteringDepth;
+
3180 if( scattering_depth.at(b)>0 ){
+
3181 scatteringenabled=true;
3182 }
3183 }
-
3184
-
3185 //Set diffuse flux for each band
-
3186 std::vector<float> diffuse_flux(Nbands);
-
3187 bool diffuseenabled = false;
-
3188 for( auto b=0; b<Nbands; b++ ){
-
3189 diffuse_flux.at(b) = getDiffuseFlux( label.at(b) );
-
3190 if( diffuse_flux.at(b)>0.f ){
-
3191 diffuseenabled=true;
-
3192 }
-
3193 }
-
3194 initializeBuffer1Df( diffuse_flux_RTbuffer, diffuse_flux );
-
3195
-
3196 //Set diffuse extinction coefficient for each band
-
3197 std::vector<float> diffuse_extinction(Nbands,0);
-
3198 if( diffuseenabled ) {
-
3199 for (auto b = 0; b < Nbands; b++) {
-
3200 diffuse_extinction.at(b) = radiation_bands.at(label.at(b)).diffuseExtinction;
-
3201 }
-
3202 }
-
3203 initializeBuffer1Df(diffuse_extinction_RTbuffer, diffuse_extinction);
-
3204
-
3205 //Set diffuse distribution normalization factor for each band
-
3206 std::vector<float> diffuse_dist_norm(Nbands,0);
-
3207 if( diffuseenabled ) {
-
3208 for (auto b = 0; b < Nbands; b++) {
-
3209 diffuse_dist_norm.at(b) = radiation_bands.at(label.at(b)).diffuseDistNorm;
-
3210 }
-
3211 initializeBuffer1Df(diffuse_dist_norm_RTbuffer, diffuse_dist_norm);
-
3212 }
-
3213
-
3214 //Set diffuse distribution peak direction for each band
-
3215 std::vector<optix::float3> diffuse_peak_dir(Nbands);
-
3216 if( diffuseenabled ) {
-
3217 for (auto b = 0; b < Nbands; b++) {
-
3218 helios::vec3 peak_dir = radiation_bands.at(label.at(b)).diffusePeakDir;
-
3219 diffuse_peak_dir.at(b) = optix::make_float3(peak_dir.x,peak_dir.y,peak_dir.z);
-
3220 }
-
3221 initializeBuffer1Dfloat3(diffuse_peak_dir_RTbuffer, diffuse_peak_dir);
-
3222 }
-
3223
-
3224 //Determine whether emission is enabled for any band
-
3225 bool emissionenabled = false;
-
3226 for( auto b=0; b<Nbands; b++ ){
-
3227 if( radiation_bands.at(label.at(b)).emissionFlag ){
-
3228 emissionenabled=true;
-
3229 }
+
3184 initializeBuffer1Dui( max_scatters_RTbuffer, scattering_depth );
+
3185
+
3186 //Issue warning if rho>0, tau>0, or eps<1
+
3187 for( int b=0; b<Nbands; b++ ){
+
3188 if( scattering_depth.at(b)==0 && scattering_iterations_needed.at(b) ){
+
3189 std::cout << "WARNING (RadiationModel::runBand): Surface radiative properties for band " << label.at(b) << " are set to non-default values, but scattering iterations are disabled. Surface radiative properties will be ignored unless scattering depth is non-zero." << std::endl;
+
3190 }
+
3191 }
+
3192
+
3193 //Set diffuse flux for each band
+
3194 std::vector<float> diffuse_flux(Nbands);
+
3195 bool diffuseenabled = false;
+
3196 for( auto b=0; b<Nbands; b++ ){
+
3197 diffuse_flux.at(b) = getDiffuseFlux( label.at(b) );
+
3198 if( diffuse_flux.at(b)>0.f ){
+
3199 diffuseenabled=true;
+
3200 }
+
3201 }
+
3202 initializeBuffer1Df( diffuse_flux_RTbuffer, diffuse_flux );
+
3203
+
3204 //Set diffuse extinction coefficient for each band
+
3205 std::vector<float> diffuse_extinction(Nbands,0);
+
3206 if( diffuseenabled ) {
+
3207 for (auto b = 0; b < Nbands; b++) {
+
3208 diffuse_extinction.at(b) = radiation_bands.at(label.at(b)).diffuseExtinction;
+
3209 }
+
3210 }
+
3211 initializeBuffer1Df(diffuse_extinction_RTbuffer, diffuse_extinction);
+
3212
+
3213 //Set diffuse distribution normalization factor for each band
+
3214 std::vector<float> diffuse_dist_norm(Nbands,0);
+
3215 if( diffuseenabled ) {
+
3216 for (auto b = 0; b < Nbands; b++) {
+
3217 diffuse_dist_norm.at(b) = radiation_bands.at(label.at(b)).diffuseDistNorm;
+
3218 }
+
3219 initializeBuffer1Df(diffuse_dist_norm_RTbuffer, diffuse_dist_norm);
+
3220 }
+
3221
+
3222 //Set diffuse distribution peak direction for each band
+
3223 std::vector<optix::float3> diffuse_peak_dir(Nbands);
+
3224 if( diffuseenabled ) {
+
3225 for (auto b = 0; b < Nbands; b++) {
+
3226 helios::vec3 peak_dir = radiation_bands.at(label.at(b)).diffusePeakDir;
+
3227 diffuse_peak_dir.at(b) = optix::make_float3(peak_dir.x,peak_dir.y,peak_dir.z);
+
3228 }
+
3229 initializeBuffer1Dfloat3(diffuse_peak_dir_RTbuffer, diffuse_peak_dir);
3230 }
3231
-
3232 //Figure out the maximum direct ray count for all bands in this run and use this as the launch size
-
3233 size_t directRayCount = 0;
-
3234 for( const auto &band : label ) {
-
3235 if( radiation_bands.at(band).directRayCount>directRayCount ) {
-
3236 directRayCount = radiation_bands.at(band).directRayCount;
+
3232 //Determine whether emission is enabled for any band
+
3233 bool emissionenabled = false;
+
3234 for( auto b=0; b<Nbands; b++ ){
+
3235 if( radiation_bands.at(label.at(b)).emissionFlag ){
+
3236 emissionenabled=true;
3237 }
3238 }
3239
-
3240 //Figure out the maximum diffuse ray count for all bands in this run and use this as the launch size
-
3241 size_t diffuseRayCount = 0;
+
3240 //Figure out the maximum direct ray count for all bands in this run and use this as the launch size
+
3241 size_t directRayCount = 0;
3242 for( const auto &band : label ) {
-
3243 if( radiation_bands.at(band).diffuseRayCount>diffuseRayCount ) {
-
3244 diffuseRayCount = radiation_bands.at(band).diffuseRayCount;
+
3243 if( radiation_bands.at(band).directRayCount>directRayCount ) {
+
3244 directRayCount = radiation_bands.at(band).directRayCount;
3245 }
3246 }
3247
3248 //Figure out the maximum diffuse ray count for all bands in this run and use this as the launch size
-
3249 size_t scatteringDepth = 0;
+
3249 size_t diffuseRayCount = 0;
3250 for( const auto &band : label ) {
-
3251 if( radiation_bands.at(band).scatteringDepth>scatteringDepth ) {
-
3252 scatteringDepth = radiation_bands.at(band).scatteringDepth;
+
3251 if( radiation_bands.at(band).diffuseRayCount>diffuseRayCount ) {
+
3252 diffuseRayCount = radiation_bands.at(band).diffuseRayCount;
3253 }
3254 }
3255
-
3256 // Zero buffers
-
3257 zeroBuffer1D( radiation_in_RTbuffer, Nbands*Nprimitives );
-
3258 zeroBuffer1D( scatter_buff_top_RTbuffer, Nbands*Nprimitives );
-
3259 zeroBuffer1D( scatter_buff_bottom_RTbuffer, Nbands*Nprimitives );
-
3260 zeroBuffer1D( Rsky_RTbuffer, Nbands*Nprimitives );
-
3261
-
3262 if( Ncameras>0 ){
-
3263 zeroBuffer1D( scatter_buff_top_cam_RTbuffer, Nbands*Nprimitives );
-
3264 zeroBuffer1D( scatter_buff_bottom_cam_RTbuffer, Nbands*Nprimitives );
-
3265 }
-
3266
-
3267 std::vector<float> TBS_top, TBS_bottom;
-
3268 TBS_top.resize(Nbands*Nprimitives, 0);
-
3269 TBS_bottom = TBS_top;
-
3270
-
3271 std::map<std::string,std::vector<std::vector<float> > > radiation_in_camera;
-
3272
-
3273 size_t maxRays = 1024*1024*1024; //maximum number of total rays in a launch
+
3256 //Figure out the maximum diffuse ray count for all bands in this run and use this as the launch size
+
3257 size_t scatteringDepth = 0;
+
3258 for( const auto &band : label ) {
+
3259 if( radiation_bands.at(band).scatteringDepth>scatteringDepth ) {
+
3260 scatteringDepth = radiation_bands.at(band).scatteringDepth;
+
3261 }
+
3262 }
+
3263
+
3264 // Zero buffers
+
3265 zeroBuffer1D( radiation_in_RTbuffer, Nbands*Nprimitives );
+
3266 zeroBuffer1D( scatter_buff_top_RTbuffer, Nbands*Nprimitives );
+
3267 zeroBuffer1D( scatter_buff_bottom_RTbuffer, Nbands*Nprimitives );
+
3268 zeroBuffer1D( Rsky_RTbuffer, Nbands*Nprimitives );
+
3269
+
3270 if( Ncameras>0 ){
+
3271 zeroBuffer1D( scatter_buff_top_cam_RTbuffer, Nbands*Nprimitives );
+
3272 zeroBuffer1D( scatter_buff_bottom_cam_RTbuffer, Nbands*Nprimitives );
+
3273 }
3274
-
3275 // ***** DIRECT LAUNCH FROM ALL RADIATION SOURCES ***** //
-
3276
-
3277 optix::int3 launch_dim_dir;
+
3275 std::vector<float> TBS_top, TBS_bottom;
+
3276 TBS_top.resize(Nbands*Nprimitives, 0);
+
3277 TBS_bottom = TBS_top;
3278
-
3279 bool rundirect = false;
-
3280 for( uint s=0; s<Nsources; s++ ){
-
3281 for( uint b=0; b<Nbands; b++ ){
-
3282 if( getSourceFlux( s, label.at(b))>0.f){
-
3283 rundirect = true;
-
3284 break;
-
3285 }
-
3286 }
-
3287 }
-
3288
-
3289 if( Nsources>0 && rundirect ){
-
3290
-
3291 //update radiation source buffers
-
3292
-
3293 std::vector<std::vector<float> > fluxes; //first index is the source, second index is the band (only those passed to runBand() function)
-
3294 fluxes.resize(Nsources);
-
3295 std::vector<optix::float3> positions(Nsources);
-
3296 std::vector<optix::float2> widths(Nsources);
-
3297 std::vector<optix::float3> rotations(Nsources);
-
3298 std::vector<uint> types(Nsources);
-
3299
-
3300 size_t s=0;
-
3301 for( const auto &source : radiation_sources ) {
-
3302
-
3303 fluxes.at(s).resize(Nbands);
-
3304
-
3305 for( auto b=0; b<label.size(); b++ ) {
-
3306 fluxes.at(s).at(b) = getSourceFlux( s, label.at(b));
-
3307 }
-
3308
-
3309 positions.at(s) = optix::make_float3( source.source_position.x, source.source_position.y, source.source_position.z );
-
3310 widths.at(s) = optix::make_float2(source.source_width.x, source.source_width.y);
-
3311 rotations.at(s) = optix::make_float3( source.source_rotation.x,source.source_rotation.y,source.source_rotation.z );
-
3312 types.at(s) = source.source_type;
-
3313
-
3314 s++;
-
3315 }
+
3279 std::map<std::string,std::vector<std::vector<float> > > radiation_in_camera;
+
3280
+
3281 size_t maxRays = 1024*1024*1024; //maximum number of total rays in a launch
+
3282
+
3283 // ***** DIRECT LAUNCH FROM ALL RADIATION SOURCES ***** //
+
3284
+
3285 optix::int3 launch_dim_dir;
+
3286
+
3287 bool rundirect = false;
+
3288 for( uint s=0; s<Nsources; s++ ){
+
3289 for( uint b=0; b<Nbands; b++ ){
+
3290 if( getSourceFlux( s, label.at(b))>0.f){
+
3291 rundirect = true;
+
3292 break;
+
3293 }
+
3294 }
+
3295 }
+
3296
+
3297 if( Nsources>0 && rundirect ){
+
3298
+
3299 //update radiation source buffers
+
3300
+
3301 std::vector<std::vector<float> > fluxes; //first index is the source, second index is the band (only those passed to runBand() function)
+
3302 fluxes.resize(Nsources);
+
3303 std::vector<optix::float3> positions(Nsources);
+
3304 std::vector<optix::float2> widths(Nsources);
+
3305 std::vector<optix::float3> rotations(Nsources);
+
3306 std::vector<uint> types(Nsources);
+
3307
+
3308 size_t s=0;
+
3309 for( const auto &source : radiation_sources ) {
+
3310
+
3311 fluxes.at(s).resize(Nbands);
+
3312
+
3313 for( auto b=0; b<label.size(); b++ ) {
+
3314 fluxes.at(s).at(b) = getSourceFlux( s, label.at(b));
+
3315 }
3316
-
3317 initializeBuffer1Df( source_fluxes_RTbuffer, flatten(fluxes) );
-
3318 initializeBuffer1Dfloat3( source_positions_RTbuffer, positions );
-
3319 initializeBuffer1Dfloat2( source_widths_RTbuffer, widths );
-
3320 initializeBuffer1Dfloat3( source_rotations_RTbuffer, rotations );
-
3321 initializeBuffer1Dui( source_types_RTbuffer, types );
-
3322
-
3323 // -- Ray Trace -- //
+
3317 positions.at(s) = optix::make_float3( source.source_position.x, source.source_position.y, source.source_position.z );
+
3318 widths.at(s) = optix::make_float2(source.source_width.x, source.source_width.y);
+
3319 rotations.at(s) = optix::make_float3( source.source_rotation.x,source.source_rotation.y,source.source_rotation.z );
+
3320 types.at(s) = source.source_type;
+
3321
+
3322 s++;
+
3323 }
3324
-
3325 // Compute direct launch dimension
-
3326 size_t n = ceil(sqrt(double(directRayCount)));
-
3327
-
3328 size_t maxPrims = floor( float(maxRays)/float(n*n) );
-
3329
-
3330 int Nlaunches = ceil( n*n*Nobjects/float(maxRays) );
-
3331
-
3332 size_t prims_per_launch = fmin( Nobjects, maxPrims );
-
3333
-
3334 for( uint launch=0; launch<Nlaunches; launch++ ){
+
3325 initializeBuffer1Df( source_fluxes_RTbuffer, flatten(fluxes) );
+
3326 initializeBuffer1Dfloat3( source_positions_RTbuffer, positions );
+
3327 initializeBuffer1Dfloat2( source_widths_RTbuffer, widths );
+
3328 initializeBuffer1Dfloat3( source_rotations_RTbuffer, rotations );
+
3329 initializeBuffer1Dui( source_types_RTbuffer, types );
+
3330
+
3331 // -- Ray Trace -- //
+
3332
+
3333 // Compute direct launch dimension
+
3334 size_t n = ceil(sqrt(double(directRayCount)));
3335
-
3336 size_t prims_this_launch;
-
3337 if( (launch+1)*prims_per_launch > Nobjects ){
-
3338 prims_this_launch = Nobjects-launch*prims_per_launch;
-
3339 }else{
-
3340 prims_this_launch = prims_per_launch;
-
3341 }
-
3342
-
3343 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, launch*prims_per_launch ) );
-
3344
-
3345 launch_dim_dir = optix::make_int3( round(n), round(n), prims_this_launch );
-
3346
-
3347 if( message_flag ){
-
3348 std::cout << "Performing primary direct radiation ray trace for bands ";
-
3349 for( const auto &band : label ) {
-
3350 std::cout << band << ", ";
-
3351 }
-
3352 std::cout << " (batch " << launch+1 << " of " << Nlaunches << ")..." << std::flush;
-
3353 }
-
3354 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIRECT , launch_dim_dir.x, launch_dim_dir.y, launch_dim_dir.z ) );
-
3355
-
3356 if( message_flag ){
-
3357 std::cout << "\r \r" << std::flush;
-
3358 }
-
3359
-
3360 }
-
3361
-
3362 if( message_flag ){
-
3363 std::cout << "Performing primary direct radiation ray trace for bands ";
-
3364 for( const auto &band : label ) {
-
3365 std::cout << band << ", ";
+
3336 size_t maxPrims = floor( float(maxRays)/float(n*n) );
+
3337
+
3338 int Nlaunches = ceil( n*n*Nobjects/float(maxRays) );
+
3339
+
3340 size_t prims_per_launch = fmin( Nobjects, maxPrims );
+
3341
+
3342 for( uint launch=0; launch<Nlaunches; launch++ ){
+
3343
+
3344 size_t prims_this_launch;
+
3345 if( (launch+1)*prims_per_launch > Nobjects ){
+
3346 prims_this_launch = Nobjects-launch*prims_per_launch;
+
3347 }else{
+
3348 prims_this_launch = prims_per_launch;
+
3349 }
+
3350
+
3351 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, launch*prims_per_launch ) );
+
3352
+
3353 launch_dim_dir = optix::make_int3( round(n), round(n), prims_this_launch );
+
3354
+
3355 if( message_flag ){
+
3356 std::cout << "Performing primary direct radiation ray trace for bands ";
+
3357 for( const auto &band : label ) {
+
3358 std::cout << band << ", ";
+
3359 }
+
3360 std::cout << " (batch " << launch+1 << " of " << Nlaunches << ")..." << std::flush;
+
3361 }
+
3362 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIRECT , launch_dim_dir.x, launch_dim_dir.y, launch_dim_dir.z ) );
+
3363
+
3364 if( message_flag ){
+
3365 std::cout << "\r \r" << std::flush;
3366 }
-
3367 std::cout << "...done." << std::endl;
+
3367
3368 }
3369
-
3370 }//end direct source launch
-
3371
-
3372 // --- Diffuse/Emission launch ---- //
-
3373
-
3374 if( emissionenabled || diffuseenabled ){
-
3375
-
3376 std::vector<float> flux_top, flux_bottom;
-
3377 flux_top.resize(Nbands*Nprimitives,0);
-
3378 flux_bottom = flux_top;
+
3370 if( message_flag ){
+
3371 std::cout << "Performing primary direct radiation ray trace for bands ";
+
3372 for( const auto &band : label ) {
+
3373 std::cout << band << ", ";
+
3374 }
+
3375 std::cout << "...done." << std::endl;
+
3376 }
+
3377
+
3378 }//end direct source launch
3379
-
3380 //If we are doing a diffuse/emission ray trace anyway and we have direct scattered energy, we get a "free" scattering trace here
-
3381 if( scatteringenabled && rundirect ){
-
3382 flux_top=getOptiXbufferData( scatter_buff_top_RTbuffer );
-
3383 flux_bottom=getOptiXbufferData( scatter_buff_bottom_RTbuffer );
-
3384 zeroBuffer1D( scatter_buff_top_RTbuffer, Nbands*Nprimitives );
-
3385 zeroBuffer1D( scatter_buff_bottom_RTbuffer, Nbands*Nprimitives );
-
3386 }
+
3380 // --- Diffuse/Emission launch ---- //
+
3381
+
3382 if( emissionenabled || diffuseenabled ){
+
3383
+
3384 std::vector<float> flux_top, flux_bottom;
+
3385 flux_top.resize(Nbands*Nprimitives,0);
+
3386 flux_bottom = flux_top;
3387
-
3388 //add any emitted energy to the outgoing energy buffer
-
3389 if( emissionenabled ) {
-
3390 // Update primitive outgoing emission
-
3391 float eps, temperature;
-
3392
-
3393 void *ptr;
-
3394 float *scatter_buff_top_cam_data, *scatter_buff_bottom_cam_data;
-
3395 if( Ncameras>0 ){
-
3396 //add emitted flux to camera scattered energy buffer
-
3397 RT_CHECK_ERROR( rtBufferMap( scatter_buff_top_cam_RTbuffer, &ptr ) );
-
3398 scatter_buff_top_cam_data = (float*)ptr;
-
3399 RT_CHECK_ERROR( rtBufferMap( scatter_buff_bottom_cam_RTbuffer, &ptr ) );
-
3400 scatter_buff_bottom_cam_data = (float*)ptr;
-
3401 }
-
3402
-
3403 for (auto b = 0; b < Nbands; b++) {
-
3404 if (radiation_bands.at(label.at(b)).emissionFlag) {
-
3405 std::string prop = "emissivity_" + label.at(b);
-
3406 for (size_t u = 0; u < Nprimitives; u++) {
-
3407 size_t ind = u * Nbands + b;
-
3408 uint p = context_UUIDs.at(u);
-
3409 if (context->doesPrimitiveDataExist(p, prop.c_str())) {
-
3410 context->getPrimitiveData(p, prop.c_str(), eps);
-
3411 } else {
-
3412 eps = eps_default;
-
3413 }
-
3414 if (scattering_depth.at(b) == 0 && eps != 1.f) {
-
3415 eps = 1.f;
-
3416 }
-
3417 if (context->doesPrimitiveDataExist(p, "temperature")) {
-
3418 context->getPrimitiveData(p, "temperature", temperature);
-
3419 if (temperature < 0) {
-
3420 temperature = temperature_default;
-
3421 }
-
3422 } else {
-
3423 temperature = temperature_default;
+
3388 //If we are doing a diffuse/emission ray trace anyway and we have direct scattered energy, we get a "free" scattering trace here
+
3389 if( scatteringenabled && rundirect ){
+
3390 flux_top=getOptiXbufferData( scatter_buff_top_RTbuffer );
+
3391 flux_bottom=getOptiXbufferData( scatter_buff_bottom_RTbuffer );
+
3392 zeroBuffer1D( scatter_buff_top_RTbuffer, Nbands*Nprimitives );
+
3393 zeroBuffer1D( scatter_buff_bottom_RTbuffer, Nbands*Nprimitives );
+
3394 }
+
3395
+
3396 //add any emitted energy to the outgoing energy buffer
+
3397 if( emissionenabled ) {
+
3398 // Update primitive outgoing emission
+
3399 float eps, temperature;
+
3400
+
3401 void *ptr;
+
3402 float *scatter_buff_top_cam_data, *scatter_buff_bottom_cam_data;
+
3403 if( Ncameras>0 ){
+
3404 //add emitted flux to camera scattered energy buffer
+
3405 RT_CHECK_ERROR( rtBufferMap( scatter_buff_top_cam_RTbuffer, &ptr ) );
+
3406 scatter_buff_top_cam_data = (float*)ptr;
+
3407 RT_CHECK_ERROR( rtBufferMap( scatter_buff_bottom_cam_RTbuffer, &ptr ) );
+
3408 scatter_buff_bottom_cam_data = (float*)ptr;
+
3409 }
+
3410
+
3411 for (auto b = 0; b < Nbands; b++) {
+
3412 if (radiation_bands.at(label.at(b)).emissionFlag) {
+
3413 std::string prop = "emissivity_" + label.at(b);
+
3414 for (size_t u = 0; u < Nprimitives; u++) {
+
3415 size_t ind = u * Nbands + b;
+
3416 uint p = context_UUIDs.at(u);
+
3417 if (context->doesPrimitiveDataExist(p, prop.c_str())) {
+
3418 context->getPrimitiveData(p, prop.c_str(), eps);
+
3419 } else {
+
3420 eps = eps_default;
+
3421 }
+
3422 if (scattering_depth.at(b) == 0 && eps != 1.f) {
+
3423 eps = 1.f;
3424 }
-
3425 float out_top = sigma * eps * pow(temperature, 4);
-
3426 flux_top.at(ind) += out_top;
-
3427 if( Ncameras>0 ) {
-
3428 scatter_buff_top_cam_data[ind] += out_top;
-
3429 }
-
3430 if (!context->doesPrimitiveDataExist(p, "twosided_flag")) { //if does not exist, assume two-sided
-
3431 flux_bottom.at(ind) += flux_top.at(ind);
-
3432 if( Ncameras>0 ) {
-
3433 scatter_buff_bottom_cam_data[ind] += out_top;
-
3434 }
-
3435 } else {
-
3436 uint flag;
-
3437 context->getPrimitiveData(p, "twosided_flag", flag);
-
3438 if (flag) {
-
3439 flux_bottom.at(ind) += flux_top.at(ind);
-
3440 if( Ncameras>0 ) {
-
3441 scatter_buff_bottom_cam_data[ind] += out_top;
-
3442 }
-
3443 }
-
3444 }
-
3445 }
-
3446 }
-
3447 }
-
3448 if( Ncameras>0 ){
-
3449 RT_CHECK_ERROR( rtBufferUnmap( scatter_buff_top_cam_RTbuffer ) );
-
3450 RT_CHECK_ERROR( rtBufferUnmap( scatter_buff_bottom_cam_RTbuffer ) );
-
3451 }
-
3452 }
-
3453
-
3454 initializeBuffer1Df( radiation_out_top_RTbuffer, flux_top );
-
3455 initializeBuffer1Df( radiation_out_bottom_RTbuffer, flux_bottom );
-
3456
-
3457 // Compute diffuse launch dimension
-
3458 size_t n = ceil(sqrt(double(diffuseRayCount)));
-
3459
-
3460 size_t maxPrims = floor( float(maxRays)/float(n*n) );
+
3425 if (context->doesPrimitiveDataExist(p, "temperature")) {
+
3426 context->getPrimitiveData(p, "temperature", temperature);
+
3427 if (temperature < 0) {
+
3428 temperature = temperature_default;
+
3429 }
+
3430 } else {
+
3431 temperature = temperature_default;
+
3432 }
+
3433 float out_top = sigma * eps * pow(temperature, 4);
+
3434 flux_top.at(ind) += out_top;
+
3435 if( Ncameras>0 ) {
+
3436 scatter_buff_top_cam_data[ind] += out_top;
+
3437 }
+
3438 if (!context->doesPrimitiveDataExist(p, "twosided_flag")) { //if does not exist, assume two-sided
+
3439 flux_bottom.at(ind) += flux_top.at(ind);
+
3440 if( Ncameras>0 ) {
+
3441 scatter_buff_bottom_cam_data[ind] += out_top;
+
3442 }
+
3443 } else {
+
3444 uint flag;
+
3445 context->getPrimitiveData(p, "twosided_flag", flag);
+
3446 if (flag) {
+
3447 flux_bottom.at(ind) += flux_top.at(ind);
+
3448 if( Ncameras>0 ) {
+
3449 scatter_buff_bottom_cam_data[ind] += out_top;
+
3450 }
+
3451 }
+
3452 }
+
3453 }
+
3454 }
+
3455 }
+
3456 if( Ncameras>0 ){
+
3457 RT_CHECK_ERROR( rtBufferUnmap( scatter_buff_top_cam_RTbuffer ) );
+
3458 RT_CHECK_ERROR( rtBufferUnmap( scatter_buff_bottom_cam_RTbuffer ) );
+
3459 }
+
3460 }
3461
-
3462 int Nlaunches = ceil( n*n*Nobjects/float(maxRays) );
-
3463
-
3464 size_t prims_per_launch = fmin( Nobjects, maxPrims );
-
3465
-
3466 for( uint launch=0; launch<Nlaunches; launch++ ){
+
3462 initializeBuffer1Df( radiation_out_top_RTbuffer, flux_top );
+
3463 initializeBuffer1Df( radiation_out_bottom_RTbuffer, flux_bottom );
+
3464
+
3465 // Compute diffuse launch dimension
+
3466 size_t n = ceil(sqrt(double(diffuseRayCount)));
3467
-
3468 size_t prims_this_launch;
-
3469 if( (launch+1)*prims_per_launch > Nobjects ){
-
3470 prims_this_launch = Nobjects-launch*prims_per_launch;
-
3471 }else{
-
3472 prims_this_launch = prims_per_launch;
-
3473 }
-
3474
-
3475 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, launch*prims_per_launch ) );
-
3476
-
3477 optix::int3 launch_dim_diff = optix::make_int3( round(n), round(n), prims_this_launch );
-
3478 assert( launch_dim_diff.x>0 && launch_dim_diff.y>0 );
-
3479
-
3480 if( message_flag ){
-
3481 std::cout << "Performing primary diffuse radiation ray trace for bands ";
-
3482 for( const auto &band : label ) {
-
3483 std::cout << band << " ";
-
3484 }
-
3485 std::cout << " (batch " << launch+1 << " of " << Nlaunches << ")..." << std::flush;
-
3486 }
-
3487 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIFFUSE , launch_dim_diff.x, launch_dim_diff.y, launch_dim_diff.z ) );
+
3468 size_t maxPrims = floor( float(maxRays)/float(n*n) );
+
3469
+
3470 int Nlaunches = ceil( n*n*Nobjects/float(maxRays) );
+
3471
+
3472 size_t prims_per_launch = fmin( Nobjects, maxPrims );
+
3473
+
3474 for( uint launch=0; launch<Nlaunches; launch++ ){
+
3475
+
3476 size_t prims_this_launch;
+
3477 if( (launch+1)*prims_per_launch > Nobjects ){
+
3478 prims_this_launch = Nobjects-launch*prims_per_launch;
+
3479 }else{
+
3480 prims_this_launch = prims_per_launch;
+
3481 }
+
3482
+
3483 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, launch*prims_per_launch ) );
+
3484
+
3485 optix::int3 launch_dim_diff = optix::make_int3( round(n), round(n), prims_this_launch );
+
3486 assert( launch_dim_diff.x>0 && launch_dim_diff.y>0 );
+
3487
3488 if( message_flag ){
-
3489 std::cout << "\r \r" << std::flush;
-
3490 }
-
3491 }
-
3492
-
3493 if( message_flag ){
-
3494 std::cout << "Performing primary diffuse radiation ray trace for bands ";
-
3495 for( const auto &band : label ) {
-
3496 std::cout << band << ", ";
-
3497 }
-
3498 std::cout << "...done." << std::endl;
+
3489 std::cout << "Performing primary diffuse radiation ray trace for bands ";
+
3490 for( const auto &band : label ) {
+
3491 std::cout << band << " ";
+
3492 }
+
3493 std::cout << " (batch " << launch+1 << " of " << Nlaunches << ")..." << std::flush;
+
3494 }
+
3495 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIFFUSE , launch_dim_diff.x, launch_dim_diff.y, launch_dim_diff.z ) );
+
3496 if( message_flag ){
+
3497 std::cout << "\r \r" << std::flush;
+
3498 }
3499 }
3500
-
3501 }
-
3502
-
3503 if( scatteringenabled ){
-
3504
-
3505 for( auto b=0; b<Nbands; b++ ) {
-
3506 diffuse_flux.at(b) = 0.f;
+
3501 if( message_flag ){
+
3502 std::cout << "Performing primary diffuse radiation ray trace for bands ";
+
3503 for( const auto &band : label ) {
+
3504 std::cout << band << ", ";
+
3505 }
+
3506 std::cout << "...done." << std::endl;
3507 }
-
3508 initializeBuffer1Df( diffuse_flux_RTbuffer, diffuse_flux );
-
3509
-
3510 size_t n = ceil(sqrt(double(diffuseRayCount)));
-
3511
-
3512 size_t maxPrims = floor( float(maxRays)/float(n*n) );
-
3513
-
3514 int Nlaunches = ceil( n*n*Nobjects/float(maxRays) );
-
3515
-
3516 size_t prims_per_launch = fmin( Nobjects, maxPrims );
+
3508
+
3509 }
+
3510
+
3511 if( scatteringenabled ){
+
3512
+
3513 for( auto b=0; b<Nbands; b++ ) {
+
3514 diffuse_flux.at(b) = 0.f;
+
3515 }
+
3516 initializeBuffer1Df( diffuse_flux_RTbuffer, diffuse_flux );
3517
-
3518 uint s;
-
3519 for( s=0; s<scatteringDepth; s++ ){
-
3520 if( message_flag ){
-
3521 std::cout << "Performing scattering ray trace (iteration " << s+1 << " of " << scatteringDepth << ")..." << std::flush;
-
3522 }
+
3518 size_t n = ceil(sqrt(double(diffuseRayCount)));
+
3519
+
3520 size_t maxPrims = floor( float(maxRays)/float(n*n) );
+
3521
+
3522 int Nlaunches = ceil( n*n*Nobjects/float(maxRays) );
3523
-
3524 for( uint b=0; b<Nbands; b++ ){
-
3525 uint depth = radiation_bands.at(label.at(b)).scatteringDepth;
-
3526 if( s+1>depth ) {
-
3527 if( message_flag ) {
-
3528 std::cout << "Skipping band " << label.at(b) << " for scattering launch " << s + 1 << std::flush;
-
3529 }
-
3530 band_launch_flag.at(b) = 0;
-
3531 }else{
-
3532 band_launch_flag.at(b) = 1;
-
3533 }
-
3534 }
-
3535 initializeBuffer1Dchar( band_launch_flag_RTbuffer, band_launch_flag );
-
3536
-
3537// TBS_top=getOptiXbufferData( scatter_buff_top_RTbuffer );
-
3538// TBS_bottom=getOptiXbufferData( scatter_buff_bottom_RTbuffer );
-
3539// float TBS_max = 0;
-
3540// for( size_t u=0; u<Nprimitives*Nbands; u++ ){
-
3541// if( TBS_top.at(u)+TBS_bottom.at(u)>TBS_max ){
-
3542// TBS_max = TBS_top.at(u)+TBS_bottom.at(u);
-
3543// }
-
3544// }
-
3545
-
3546 copyBuffer1D( scatter_buff_top_RTbuffer, radiation_out_top_RTbuffer );
-
3547 zeroBuffer1D( scatter_buff_top_RTbuffer, Nbands*Nprimitives );
-
3548 copyBuffer1D( scatter_buff_bottom_RTbuffer, radiation_out_bottom_RTbuffer );
-
3549 zeroBuffer1D( scatter_buff_bottom_RTbuffer, Nbands*Nprimitives );
-
3550
-
3551 for( uint launch=0; launch<Nlaunches; launch++ ){
-
3552
-
3553 size_t prims_this_launch;
-
3554 if( (launch+1)*prims_per_launch > Nobjects ){
-
3555 prims_this_launch = Nobjects-launch*prims_per_launch;
-
3556 }else{
-
3557 prims_this_launch = prims_per_launch;
-
3558 }
-
3559 optix::int3 launch_dim_diff = optix::make_int3( round(n), round(n), prims_this_launch );
+
3524 size_t prims_per_launch = fmin( Nobjects, maxPrims );
+
3525
+
3526 uint s;
+
3527 for( s=0; s<scatteringDepth; s++ ){
+
3528 if( message_flag ){
+
3529 std::cout << "Performing scattering ray trace (iteration " << s+1 << " of " << scatteringDepth << ")..." << std::flush;
+
3530 }
+
3531
+
3532 for( uint b=0; b<Nbands; b++ ){
+
3533 uint depth = radiation_bands.at(label.at(b)).scatteringDepth;
+
3534 if( s+1>depth ) {
+
3535 if( message_flag ) {
+
3536 std::cout << "Skipping band " << label.at(b) << " for scattering launch " << s + 1 << std::flush;
+
3537 }
+
3538 band_launch_flag.at(b) = 0;
+
3539 }else{
+
3540 band_launch_flag.at(b) = 1;
+
3541 }
+
3542 }
+
3543 initializeBuffer1Dchar( band_launch_flag_RTbuffer, band_launch_flag );
+
3544
+
3545// TBS_top=getOptiXbufferData( scatter_buff_top_RTbuffer );
+
3546// TBS_bottom=getOptiXbufferData( scatter_buff_bottom_RTbuffer );
+
3547// float TBS_max = 0;
+
3548// for( size_t u=0; u<Nprimitives*Nbands; u++ ){
+
3549// if( TBS_top.at(u)+TBS_bottom.at(u)>TBS_max ){
+
3550// TBS_max = TBS_top.at(u)+TBS_bottom.at(u);
+
3551// }
+
3552// }
+
3553
+
3554 copyBuffer1D( scatter_buff_top_RTbuffer, radiation_out_top_RTbuffer );
+
3555 zeroBuffer1D( scatter_buff_top_RTbuffer, Nbands*Nprimitives );
+
3556 copyBuffer1D( scatter_buff_bottom_RTbuffer, radiation_out_bottom_RTbuffer );
+
3557 zeroBuffer1D( scatter_buff_bottom_RTbuffer, Nbands*Nprimitives );
+
3558
+
3559 for( uint launch=0; launch<Nlaunches; launch++ ){
3560
-
3561 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, launch*prims_per_launch ) );
-
3562
-
3563 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIFFUSE , launch_dim_diff.x, launch_dim_diff.y, launch_dim_diff.z ) );
-
3564
-
3565 }
-
3566 if( message_flag ){
-
3567 std::cout << "\r \r" << std::flush;
-
3568 }
-
3569
-
3570 }
-
3571
-
3572 if( message_flag ){
-
3573 std::cout << "Performing scattering ray trace...done." << std::endl;
-
3574 }
-
3575
-
3576 }
+
3561 size_t prims_this_launch;
+
3562 if( (launch+1)*prims_per_launch > Nobjects ){
+
3563 prims_this_launch = Nobjects-launch*prims_per_launch;
+
3564 }else{
+
3565 prims_this_launch = prims_per_launch;
+
3566 }
+
3567 optix::int3 launch_dim_diff = optix::make_int3( round(n), round(n), prims_this_launch );
+
3568
+
3569 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, launch*prims_per_launch ) );
+
3570
+
3571 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIFFUSE , launch_dim_diff.x, launch_dim_diff.y, launch_dim_diff.z ) );
+
3572
+
3573 }
+
3574 if( message_flag ){
+
3575 std::cout << "\r \r" << std::flush;
+
3576 }
3577
-
3578 // **** CAMERA RAY TRACE **** //
-
3579 if( Ncameras>0 ){
-
3580
-
3581 //re-set outgoing radiation buffers
-
3582 copyBuffer1D( scatter_buff_top_cam_RTbuffer, radiation_out_top_RTbuffer );
-
3583 copyBuffer1D( scatter_buff_bottom_cam_RTbuffer, radiation_out_bottom_RTbuffer );
-
3584
-
3585 //re-set diffuse radiation fluxes
-
3586 if( diffuseenabled ){
-
3587 for( auto b=0; b<Nbands; b++ ){
-
3588 diffuse_flux.at(b) = getDiffuseFlux(label.at(b));
-
3589 }
-
3590 initializeBuffer1Df( diffuse_flux_RTbuffer, diffuse_flux );
-
3591 }
+
3578 }
+
3579
+
3580 if( message_flag ){
+
3581 std::cout << "Performing scattering ray trace...done." << std::endl;
+
3582 }
+
3583
+
3584 }
+
3585
+
3586 // **** CAMERA RAY TRACE **** //
+
3587 if( Ncameras>0 ){
+
3588
+
3589 //re-set outgoing radiation buffers
+
3590 copyBuffer1D( scatter_buff_top_cam_RTbuffer, radiation_out_top_RTbuffer );
+
3591 copyBuffer1D( scatter_buff_bottom_cam_RTbuffer, radiation_out_bottom_RTbuffer );
3592
-
3593
-
3594 size_t n = ceil(sqrt(double(diffuseRayCount)));
-
3595
-
3596 uint cam=0;
-
3597 for( auto & camera : cameras ){
-
3598
-
3599 //set variable values
-
3600 RT_CHECK_ERROR( rtVariableSet3f( camera_position_RTvariable, camera.second.position.x, camera.second.position.y, camera.second.position.z ) );
-
3601 helios::SphericalCoord dir = cart2sphere( camera.second.lookat - camera.second.position );
-
3602 RT_CHECK_ERROR( rtVariableSet2f( camera_direction_RTvariable, dir.zenith, dir.azimuth ) );
-
3603 RT_CHECK_ERROR( rtVariableSet1f( camera_lens_diameter_RTvariable, camera.second.lens_diameter ) );
-
3604 RT_CHECK_ERROR( rtVariableSet1f( FOV_aspect_RTvariable, camera.second.FOV_aspect_ratio ) );
-
3605 RT_CHECK_ERROR( rtVariableSet1f( camera_focal_length_RTvariable, camera.second.focal_length ) );
-
3606 RT_CHECK_ERROR( rtVariableSet1f( camera_viewplane_length_RTvariable, 1.f/tanf(camera.second.HFOV_degrees*M_PI/180.f) ) );
-
3607 RT_CHECK_ERROR( rtVariableSet1ui( camera_ID_RTvariable, cam ));
-
3608
-
3609 zeroBuffer1D( radiation_in_camera_RTbuffer, camera.second.resolution.x*camera.second.resolution.y*Nbands );
-
3610
-
3611 optix::int3 launch_dim_camera = optix::make_int3( camera.second.antialiasing_samples, camera.second.resolution.x, camera.second.resolution.y );
-
3612
-
3613 if( message_flag ){
-
3614 std::cout << "Performing scattering radiation camera ray trace for camera " << camera.second.label << "..." << std::flush;
-
3615 }
-
3616 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_CAMERA , launch_dim_camera.x, launch_dim_camera.y, launch_dim_camera.z ) );
-
3617 if( message_flag ){
-
3618 std::cout << "done." << std::endl;
-
3619 }
+
3593 //re-set diffuse radiation fluxes
+
3594 if( diffuseenabled ){
+
3595 for( auto b=0; b<Nbands; b++ ){
+
3596 diffuse_flux.at(b) = getDiffuseFlux(label.at(b));
+
3597 }
+
3598 initializeBuffer1Df( diffuse_flux_RTbuffer, diffuse_flux );
+
3599 }
+
3600
+
3601
+
3602 size_t n = ceil(sqrt(double(diffuseRayCount)));
+
3603
+
3604 uint cam=0;
+
3605 for( auto & camera : cameras ){
+
3606
+
3607 //set variable values
+
3608 RT_CHECK_ERROR( rtVariableSet3f( camera_position_RTvariable, camera.second.position.x, camera.second.position.y, camera.second.position.z ) );
+
3609 helios::SphericalCoord dir = cart2sphere( camera.second.lookat - camera.second.position );
+
3610 RT_CHECK_ERROR( rtVariableSet2f( camera_direction_RTvariable, dir.zenith, dir.azimuth ) );
+
3611 RT_CHECK_ERROR( rtVariableSet1f( camera_lens_diameter_RTvariable, camera.second.lens_diameter ) );
+
3612 RT_CHECK_ERROR( rtVariableSet1f( FOV_aspect_RTvariable, camera.second.FOV_aspect_ratio ) );
+
3613 RT_CHECK_ERROR( rtVariableSet1f( camera_focal_length_RTvariable, camera.second.focal_length ) );
+
3614 RT_CHECK_ERROR( rtVariableSet1f( camera_viewplane_length_RTvariable, 1.f/tanf(camera.second.HFOV_degrees*M_PI/180.f) ) );
+
3615 RT_CHECK_ERROR( rtVariableSet1ui( camera_ID_RTvariable, cam ));
+
3616
+
3617 zeroBuffer1D( radiation_in_camera_RTbuffer, camera.second.resolution.x*camera.second.resolution.y*Nbands );
+
3618
+
3619 optix::int3 launch_dim_camera = optix::make_int3( camera.second.antialiasing_samples, camera.second.resolution.x, camera.second.resolution.y );
3620
-
3621 std::vector<float> radiation_camera = getOptiXbufferData(radiation_in_camera_RTbuffer);
-
3622
-
3623 std::string camera_label = camera.second.label;
-
3624
-
3625 for( auto b=0; b<Nbands; b++ ) {
-
3626
-
3627 camera.second.pixel_data[label.at(b)].resize(camera.second.resolution.x*camera.second.resolution.y);
+
3621 if( message_flag ){
+
3622 std::cout << "Performing scattering radiation camera ray trace for camera " << camera.second.label << "..." << std::flush;
+
3623 }
+
3624 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_CAMERA , launch_dim_camera.x, launch_dim_camera.y, launch_dim_camera.z ) );
+
3625 if( message_flag ){
+
3626 std::cout << "done." << std::endl;
+
3627 }
3628
-
3629 std::string data_label = "camera_" + camera_label + "_" + label.at(b);
+
3629 std::vector<float> radiation_camera = getOptiXbufferData(radiation_in_camera_RTbuffer);
3630
-
3631 for( auto p=0; p<camera.second.resolution.x*camera.second.resolution.y; p++ ){
-
3632 camera.second.pixel_data.at(label.at(b)).at(p) = radiation_camera.at(p*Nbands+b);
-
3633 }
+
3631 std::string camera_label = camera.second.label;
+
3632
+
3633 for( auto b=0; b<Nbands; b++ ) {
3634
-
3635 context->setGlobalData(data_label.c_str(), HELIOS_TYPE_FLOAT,camera.second.resolution.x*camera.second.resolution.y,&camera.second.pixel_data.at(label.at(b))[0]);
+
3635 camera.second.pixel_data[label.at(b)].resize(camera.second.resolution.x*camera.second.resolution.y);
3636
-
3637 }
+
3637 std::string data_label = "camera_" + camera_label + "_" + label.at(b);
3638
-
3639 //--- Pixel Labeling Trace ---//
-
3640
-
3641 zeroBuffer1D(camera_pixel_label_RTbuffer,camera.second.resolution.x*camera.second.resolution.y);
-
3642 zeroBuffer1D(camera_pixel_depth_RTbuffer,camera.second.resolution.x*camera.second.resolution.y);
-
3643
-
3644 if( message_flag ){
-
3645 std::cout << "Performing camera pixel labeling ray trace for camera " << camera.second.label << "..." << std::flush;
-
3646 }
-
3647 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_PIXEL_LABEL , 1, launch_dim_camera.y, launch_dim_camera.z ) );
-
3648 if( message_flag ){
-
3649 std::cout << "done." << std::endl;
-
3650 }
+
3639 for( auto p=0; p<camera.second.resolution.x*camera.second.resolution.y; p++ ){
+
3640 camera.second.pixel_data.at(label.at(b)).at(p) = radiation_camera.at(p*Nbands+b);
+
3641 }
+
3642
+
3643 context->setGlobalData(data_label.c_str(), HELIOS_TYPE_FLOAT,camera.second.resolution.x*camera.second.resolution.y,&camera.second.pixel_data.at(label.at(b))[0]);
+
3644
+
3645 }
+
3646
+
3647 //--- Pixel Labeling Trace ---//
+
3648
+
3649 zeroBuffer1D(camera_pixel_label_RTbuffer,camera.second.resolution.x*camera.second.resolution.y);
+
3650 zeroBuffer1D(camera_pixel_depth_RTbuffer,camera.second.resolution.x*camera.second.resolution.y);
3651
-
3652 camera.second.pixel_label_UUID = getOptiXbufferData_ui(camera_pixel_label_RTbuffer);
-
3653 camera.second.pixel_depth = getOptiXbufferData(camera_pixel_depth_RTbuffer);
-
3654
-
3655 //the IDs from the ray trace do not necessarily correspond to the actual primitive UUIDs, so look them up.
-
3656 for( uint ID=0; ID<camera.second.pixel_label_UUID.size(); ID++ ){
-
3657 if( camera.second.pixel_label_UUID.at(ID)>0 ){
-
3658 camera.second.pixel_label_UUID.at(ID) = context_UUIDs.at(camera.second.pixel_label_UUID.at(ID) - 1) + 1;
-
3659 }
-
3660 }
-
3661
-
3662 std::string data_label = "camera_" + camera_label + "_pixel_UUID";
-
3663
-
3664 context->setGlobalData(data_label.c_str(), HELIOS_TYPE_UINT,camera.second.resolution.x*camera.second.resolution.y,&camera.second.pixel_label_UUID[0]);
-
3665
-
3666 data_label = "camera_" + camera_label + "_pixel_depth";
-
3667
-
3668 context->setGlobalData(data_label.c_str(), HELIOS_TYPE_FLOAT,camera.second.resolution.x*camera.second.resolution.y,&camera.second.pixel_depth[0]);
+
3652 if( message_flag ){
+
3653 std::cout << "Performing camera pixel labeling ray trace for camera " << camera.second.label << "..." << std::flush;
+
3654 }
+
3655 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_PIXEL_LABEL , 1, launch_dim_camera.y, launch_dim_camera.z ) );
+
3656 if( message_flag ){
+
3657 std::cout << "done." << std::endl;
+
3658 }
+
3659
+
3660 camera.second.pixel_label_UUID = getOptiXbufferData_ui(camera_pixel_label_RTbuffer);
+
3661 camera.second.pixel_depth = getOptiXbufferData(camera_pixel_depth_RTbuffer);
+
3662
+
3663 //the IDs from the ray trace do not necessarily correspond to the actual primitive UUIDs, so look them up.
+
3664 for( uint ID=0; ID<camera.second.pixel_label_UUID.size(); ID++ ){
+
3665 if( camera.second.pixel_label_UUID.at(ID)>0 ){
+
3666 camera.second.pixel_label_UUID.at(ID) = context_UUIDs.at(camera.second.pixel_label_UUID.at(ID) - 1) + 1;
+
3667 }
+
3668 }
3669
-
3670 cam++;
-
3671 }
-
3672 }
+
3670 std::string data_label = "camera_" + camera_label + "_pixel_UUID";
+
3671
+
3672 context->setGlobalData(data_label.c_str(), HELIOS_TYPE_UINT,camera.second.resolution.x*camera.second.resolution.y,&camera.second.pixel_label_UUID[0]);
3673
-
3674 //deposit any energy that is left to make sure we satisfy conservation of energy
-
3675 TBS_top=getOptiXbufferData( scatter_buff_top_RTbuffer );
-
3676 TBS_bottom=getOptiXbufferData( scatter_buff_bottom_RTbuffer );
+
3674 data_label = "camera_" + camera_label + "_pixel_depth";
+
3675
+
3676 context->setGlobalData(data_label.c_str(), HELIOS_TYPE_FLOAT,camera.second.resolution.x*camera.second.resolution.y,&camera.second.pixel_depth[0]);
3677
-
3678 // Set variables in geometric objects
-
3679
-
3680 std::vector<float> radiation_flux_data;
-
3681 radiation_flux_data=getOptiXbufferData( radiation_in_RTbuffer );
-
3682
-
3683 std::vector<uint> UUIDs_context_all = context->getAllUUIDs();
-
3684
-
3685 for( auto b=0; b<Nbands; b++ ) {
-
3686
-
3687 std::string prop = "radiation_flux_" + label.at(b);
-
3688 for (size_t u = 0; u < Nprimitives; u++) {
-
3689 size_t ind = u * Nbands + b;
-
3690 float R = radiation_flux_data.at(ind) + TBS_top.at(ind) + TBS_bottom.at(ind);
-
3691 context->setPrimitiveData(context_UUIDs.at(u), prop.c_str(), R);
-
3692 if (radiation_flux_data.at(ind) != radiation_flux_data.at(ind)) {
-
3693 std::cout << "NaN here " << ind << std::endl;
-
3694 }
-
3695 }
-
3696
-
3697 if( UUIDs_context_all.size()!=Nprimitives ){
-
3698 for( uint UUID : UUIDs_context_all ){
-
3699 if( context->doesPrimitiveExist(UUID) && !context->doesPrimitiveDataExist(UUID,prop.c_str()) ){
-
3700 context->setPrimitiveData(UUID,prop.c_str(),0.f);
-
3701 }
+
3678 cam++;
+
3679 }
+
3680 }
+
3681
+
3682 //deposit any energy that is left to make sure we satisfy conservation of energy
+
3683 TBS_top=getOptiXbufferData( scatter_buff_top_RTbuffer );
+
3684 TBS_bottom=getOptiXbufferData( scatter_buff_bottom_RTbuffer );
+
3685
+
3686 // Set variables in geometric objects
+
3687
+
3688 std::vector<float> radiation_flux_data;
+
3689 radiation_flux_data=getOptiXbufferData( radiation_in_RTbuffer );
+
3690
+
3691 std::vector<uint> UUIDs_context_all = context->getAllUUIDs();
+
3692
+
3693 for( auto b=0; b<Nbands; b++ ) {
+
3694
+
3695 std::string prop = "radiation_flux_" + label.at(b);
+
3696 for (size_t u = 0; u < Nprimitives; u++) {
+
3697 size_t ind = u * Nbands + b;
+
3698 float R = radiation_flux_data.at(ind) + TBS_top.at(ind) + TBS_bottom.at(ind);
+
3699 context->setPrimitiveData(context_UUIDs.at(u), prop.c_str(), R);
+
3700 if (radiation_flux_data.at(ind) != radiation_flux_data.at(ind)) {
+
3701 std::cout << "NaN here " << ind << std::endl;
3702 }
3703 }
3704
-
3705 }
-
3706
-
3707}
+
3705 if( UUIDs_context_all.size()!=Nprimitives ){
+
3706 for( uint UUID : UUIDs_context_all ){
+
3707 if( context->doesPrimitiveExist(UUID) && !context->doesPrimitiveDataExist(UUID,prop.c_str()) ){
+
3708 context->setPrimitiveData(UUID,prop.c_str(),0.f);
+
3709 }
+
3710 }
+
3711 }
+
3712
+
3713 }
+
3714
+
3715}
-
3708
-
- -
3710
-
3711 std::vector<float> Rsky_SW;
-
3712 Rsky_SW=getOptiXbufferData( Rsky_RTbuffer );
-
3713 float Rsky=0.f;
-
3714 for( size_t i=0; i<Rsky_SW.size(); i++ ){
-
3715 Rsky += Rsky_SW.at(i);
-
3716 }
-
3717 return Rsky;
+
3716
+
+
3718
-
3719}
+
3719 std::vector<float> Rsky_SW;
+
3720 Rsky_SW=getOptiXbufferData( Rsky_RTbuffer );
+
3721 float Rsky=0.f;
+
3722 for( size_t i=0; i<Rsky_SW.size(); i++ ){
+
3723 Rsky += Rsky_SW.at(i);
+
3724 }
+
3725 return Rsky;
+
3726
+
3727}
-
3720
-
- -
3722
-
3723 std::vector<float> total_flux;
-
3724 total_flux.resize(context->getPrimitiveCount(),0.f);
-
3725
-
3726 for( const auto &band : radiation_bands ){
-
3727
-
3728 std::string label = band.first;
-
3729
-
3730 for( size_t u=0; u<context_UUIDs.size(); u++ ){
-
3731
-
3732 uint p = context_UUIDs.at(u);
+
3728
+
+ +
3730
+
3731 std::vector<float> total_flux;
+
3732 total_flux.resize(context->getPrimitiveCount(),0.f);
3733
-
3734 std::string str = "radiation_flux_" + label;
+
3734 for( const auto &band : radiation_bands ){
3735
-
3736 float R;
-
3737 context->getPrimitiveData( p, str.c_str(), R );
-
3738 total_flux.at(u) += R;
+
3736 std::string label = band.first;
+
3737
+
3738 for( size_t u=0; u<context_UUIDs.size(); u++ ){
3739
-
3740 }
+
3740 uint p = context_UUIDs.at(u);
3741
-
3742 }
+
3742 std::string str = "radiation_flux_" + label;
3743
-
3744 return total_flux;
-
3745
-
3746}
-
+
3744 float R;
+
3745 context->getPrimitiveData( p, str.c_str(), R );
+
3746 total_flux.at(u) += R;
3747
-
3748std::vector<float> RadiationModel::getOptiXbufferData( RTbuffer buffer ){
+
3748 }
3749
-
3750 void* _data_;
-
3751 RT_CHECK_ERROR( rtBufferMap( buffer, &_data_ ) );
-
3752 float* data_ptr = (float*)_data_;
+
3750 }
+
3751
+
3752 return total_flux;
3753
-
3754 RTsize size;
-
3755 RT_CHECK_ERROR( rtBufferGetSize1D( buffer, &size ) );
-
3756
-
3757 std::vector<float> data_vec;
-
3758 data_vec.resize(size);
-
3759 for( int i=0; i<size; i++ ){
-
3760 data_vec.at(i)=data_ptr[i];
-
3761 }
-
3762
-
3763 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
3754}
+
+
3755
+
3756std::vector<float> RadiationModel::getOptiXbufferData( RTbuffer buffer ){
+
3757
+
3758 void* _data_;
+
3759 RT_CHECK_ERROR( rtBufferMap( buffer, &_data_ ) );
+
3760 float* data_ptr = (float*)_data_;
+
3761
+
3762 RTsize size;
+
3763 RT_CHECK_ERROR( rtBufferGetSize1D( buffer, &size ) );
3764
-
3765 return data_vec;
-
3766
-
3767}
-
3768
-
3769std::vector<double> RadiationModel::getOptiXbufferData_d( RTbuffer buffer ){
+
3765 std::vector<float> data_vec;
+
3766 data_vec.resize(size);
+
3767 for( int i=0; i<size; i++ ){
+
3768 data_vec.at(i)=data_ptr[i];
+
3769 }
3770
-
3771 void* _data_;
-
3772 RT_CHECK_ERROR( rtBufferMap( buffer, &_data_ ) );
-
3773 double* data_ptr = (double*)_data_;
+
3771 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
3772
+
3773 return data_vec;
3774
-
3775 RTsize size;
-
3776 RT_CHECK_ERROR( rtBufferGetSize1D( buffer, &size ) );
-
3777
-
3778 std::vector<double> data_vec;
-
3779 data_vec.resize(size);
-
3780 for( int i=0; i<size; i++ ){
-
3781 data_vec.at(i)=data_ptr[i];
-
3782 }
-
3783
-
3784 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
3775}
+
3776
+
3777std::vector<double> RadiationModel::getOptiXbufferData_d( RTbuffer buffer ){
+
3778
+
3779 void* _data_;
+
3780 RT_CHECK_ERROR( rtBufferMap( buffer, &_data_ ) );
+
3781 double* data_ptr = (double*)_data_;
+
3782
+
3783 RTsize size;
+
3784 RT_CHECK_ERROR( rtBufferGetSize1D( buffer, &size ) );
3785
-
3786 return data_vec;
-
3787
-
3788}
-
3789
-
3790std::vector<uint> RadiationModel::getOptiXbufferData_ui( RTbuffer buffer ){
+
3786 std::vector<double> data_vec;
+
3787 data_vec.resize(size);
+
3788 for( int i=0; i<size; i++ ){
+
3789 data_vec.at(i)=data_ptr[i];
+
3790 }
3791
-
3792 void* _data_;
-
3793 RT_CHECK_ERROR( rtBufferMap( buffer, &_data_ ) );
-
3794 uint* data_ptr = (uint*)_data_;
+
3792 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
3793
+
3794 return data_vec;
3795
-
3796 RTsize size;
-
3797 RT_CHECK_ERROR( rtBufferGetSize1D( buffer, &size ) );
-
3798
-
3799 std::vector<uint> data_vec;
-
3800 data_vec.resize(size);
-
3801 for( int i=0; i<size; i++ ){
-
3802 data_vec.at(i)=data_ptr[i];
-
3803 }
-
3804
-
3805 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
3796}
+
3797
+
3798std::vector<uint> RadiationModel::getOptiXbufferData_ui( RTbuffer buffer ){
+
3799
+
3800 void* _data_;
+
3801 RT_CHECK_ERROR( rtBufferMap( buffer, &_data_ ) );
+
3802 uint* data_ptr = (uint*)_data_;
+
3803
+
3804 RTsize size;
+
3805 RT_CHECK_ERROR( rtBufferGetSize1D( buffer, &size ) );
3806
-
3807 return data_vec;
-
3808
-
3809}
-
3810
-
3811void RadiationModel::addBuffer( const char* name, RTbuffer& buffer, RTvariable& variable, RTbuffertype type, RTformat format, size_t dimension ){
+
3807 std::vector<uint> data_vec;
+
3808 data_vec.resize(size);
+
3809 for( int i=0; i<size; i++ ){
+
3810 data_vec.at(i)=data_ptr[i];
+
3811 }
3812
-
3813 RT_CHECK_ERROR( rtBufferCreate( OptiX_Context, type, &buffer ) );
-
3814 RT_CHECK_ERROR( rtBufferSetFormat( buffer, format ) );
-
3815 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, name, &variable ) );
-
3816 RT_CHECK_ERROR( rtVariableSetObject( variable, buffer ) );
-
3817 if( dimension==1 ){
-
3818 zeroBuffer1D( buffer, 1 );
-
3819 }else if( dimension==2 ){
-
3820 zeroBuffer2D( buffer, optix::make_int2(1,1) );
-
3821 }else{
-
3822 helios_runtime_error("ERROR (RadiationModel::addBuffer): invalid buffer dimension of " + std::to_string(dimension) + ", must be 1 or 2.");
-
3823 }
-
3824
-
3825}
-
3826
-
3827void RadiationModel::zeroBuffer1D(RTbuffer &buffer, size_t bsize ){
-
3828
-
3829 //get buffer format
-
3830 RTformat format;
-
3831 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
3813 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
3814
+
3815 return data_vec;
+
3816
+
3817}
+
3818
+
3819void RadiationModel::addBuffer( const char* name, RTbuffer& buffer, RTvariable& variable, RTbuffertype type, RTformat format, size_t dimension ){
+
3820
+
3821 RT_CHECK_ERROR( rtBufferCreate( OptiX_Context, type, &buffer ) );
+
3822 RT_CHECK_ERROR( rtBufferSetFormat( buffer, format ) );
+
3823 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, name, &variable ) );
+
3824 RT_CHECK_ERROR( rtVariableSetObject( variable, buffer ) );
+
3825 if( dimension==1 ){
+
3826 zeroBuffer1D( buffer, 1 );
+
3827 }else if( dimension==2 ){
+
3828 zeroBuffer2D( buffer, optix::make_int2(1,1) );
+
3829 }else{
+
3830 helios_runtime_error("ERROR (RadiationModel::addBuffer): invalid buffer dimension of " + std::to_string(dimension) + ", must be 1 or 2.");
+
3831 }
3832
-
3833 if( format==RT_FORMAT_USER ){//Note: for now, assume user format means it's a double
+
3833}
3834
-
3835 std::vector<double> array;
-
3836 array.resize(bsize);
-
3837 for( int i=0; i<bsize; i++ ){
-
3838 array.at(i)=0.f;
-
3839 }
+
3835void RadiationModel::zeroBuffer1D(RTbuffer &buffer, size_t bsize ){
+
3836
+
3837 //get buffer format
+
3838 RTformat format;
+
3839 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
3840
-
3841 initializeBuffer1Dd( buffer, array );
+
3841 if( format==RT_FORMAT_USER ){//Note: for now, assume user format means it's a double
3842
-
3843 }else if( format==RT_FORMAT_FLOAT ){
-
3844
-
3845 std::vector<float> array;
-
3846 array.resize(bsize);
-
3847 for( int i=0; i<bsize; i++ ){
-
3848 array.at(i)=0.f;
-
3849 }
+
3843 std::vector<double> array;
+
3844 array.resize(bsize);
+
3845 for( int i=0; i<bsize; i++ ){
+
3846 array.at(i)=0.f;
+
3847 }
+
3848
+
3849 initializeBuffer1Dd( buffer, array );
3850
-
3851 initializeBuffer1Df( buffer, array );
+
3851 }else if( format==RT_FORMAT_FLOAT ){
3852
-
3853 }else if( format==RT_FORMAT_FLOAT2 ){
-
3854
-
3855 std::vector<optix::float2> array;
-
3856 array.resize(bsize);
-
3857 for( int i=0; i<bsize; i++ ){
-
3858 array.at(i)=optix::make_float2(0,0);
-
3859 }
+
3853 std::vector<float> array;
+
3854 array.resize(bsize);
+
3855 for( int i=0; i<bsize; i++ ){
+
3856 array.at(i)=0.f;
+
3857 }
+
3858
+
3859 initializeBuffer1Df( buffer, array );
3860
-
3861 initializeBuffer1Dfloat2( buffer, array );
+
3861 }else if( format==RT_FORMAT_FLOAT2 ){
3862
-
3863 }else if( format==RT_FORMAT_FLOAT3 ){
-
3864
-
3865 std::vector<optix::float3> array;
-
3866 array.resize(bsize);
-
3867 for( int i=0; i<bsize; i++ ){
-
3868 array.at(i)=optix::make_float3(0,0,0);
-
3869 }
+
3863 std::vector<optix::float2> array;
+
3864 array.resize(bsize);
+
3865 for( int i=0; i<bsize; i++ ){
+
3866 array.at(i)=optix::make_float2(0,0);
+
3867 }
+
3868
+
3869 initializeBuffer1Dfloat2( buffer, array );
3870
-
3871 initializeBuffer1Dfloat3( buffer, array );
+
3871 }else if( format==RT_FORMAT_FLOAT3 ){
3872
-
3873 }else if( format==RT_FORMAT_INT ){
-
3874
-
3875 std::vector<int> array;
-
3876 array.resize(bsize);
-
3877 for( int i=0; i<bsize; i++ ){
-
3878 array.at(i)=0;
-
3879 }
+
3873 std::vector<optix::float3> array;
+
3874 array.resize(bsize);
+
3875 for( int i=0; i<bsize; i++ ){
+
3876 array.at(i)=optix::make_float3(0,0,0);
+
3877 }
+
3878
+
3879 initializeBuffer1Dfloat3( buffer, array );
3880
-
3881 initializeBuffer1Di( buffer, array );
+
3881 }else if( format==RT_FORMAT_INT ){
3882
-
3883 }else if( format==RT_FORMAT_INT2 ){
-
3884
-
3885 std::vector<optix::int2> array;
-
3886 array.resize(bsize);
-
3887 for( int i=0; i<bsize; i++ ){
-
3888 array.at(i)=optix::make_int2(0,0);
-
3889 }
+
3883 std::vector<int> array;
+
3884 array.resize(bsize);
+
3885 for( int i=0; i<bsize; i++ ){
+
3886 array.at(i)=0;
+
3887 }
+
3888
+
3889 initializeBuffer1Di( buffer, array );
3890
-
3891 initializeBuffer1Dint2( buffer, array );
+
3891 }else if( format==RT_FORMAT_INT2 ){
3892
-
3893 }else if( format==RT_FORMAT_INT3 ){
-
3894
-
3895 std::vector<optix::int3> array;
-
3896 array.resize(bsize);
-
3897 for( int i=0; i<bsize; i++ ){
-
3898 array.at(i)=optix::make_int3(0,0,0);
-
3899 }
+
3893 std::vector<optix::int2> array;
+
3894 array.resize(bsize);
+
3895 for( int i=0; i<bsize; i++ ){
+
3896 array.at(i)=optix::make_int2(0,0);
+
3897 }
+
3898
+
3899 initializeBuffer1Dint2( buffer, array );
3900
-
3901 initializeBuffer1Dint3( buffer, array );
+
3901 }else if( format==RT_FORMAT_INT3 ){
3902
-
3903 }else if( format==RT_FORMAT_UNSIGNED_INT ){
-
3904
-
3905 std::vector<uint> array;
-
3906 array.resize(bsize);
-
3907 for( int i=0; i<bsize; i++ ){
-
3908 array.at(i)=0;
-
3909 }
+
3903 std::vector<optix::int3> array;
+
3904 array.resize(bsize);
+
3905 for( int i=0; i<bsize; i++ ){
+
3906 array.at(i)=optix::make_int3(0,0,0);
+
3907 }
+
3908
+
3909 initializeBuffer1Dint3( buffer, array );
3910
-
3911 initializeBuffer1Dui( buffer, array );
+
3911 }else if( format==RT_FORMAT_UNSIGNED_INT ){
3912
-
3913 }else if( format==RT_FORMAT_BYTE ){
-
3914
-
3915 std::vector<char> array;
-
3916 array.resize(bsize);
-
3917 for( int i=0; i<bsize; i++ ){
-
3918 array.at(i)=0;
-
3919 }
+
3913 std::vector<uint> array;
+
3914 array.resize(bsize);
+
3915 for( int i=0; i<bsize; i++ ){
+
3916 array.at(i)=0;
+
3917 }
+
3918
+
3919 initializeBuffer1Dui( buffer, array );
3920
-
3921 initializeBuffer1Dchar( buffer, array );
-
3922 }else{
-
3923 helios_runtime_error("ERROR (RadiationModel::zeroBuffer1D): Buffer type not supported.");
-
3924 }
-
3925
-
3926}
-
3927
-
3928void RadiationModel::copyBuffer1D( RTbuffer &buffer, RTbuffer &buffer_copy ){
-
3929
-
3930 /* \todo Add support for all data types (currently only works for float and float3)*/
-
3931
-
3932 //get buffer format
-
3933 RTformat format;
-
3934 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
3921 }else if( format==RT_FORMAT_BYTE ){
+
3922
+
3923 std::vector<char> array;
+
3924 array.resize(bsize);
+
3925 for( int i=0; i<bsize; i++ ){
+
3926 array.at(i)=0;
+
3927 }
+
3928
+
3929 initializeBuffer1Dchar( buffer, array );
+
3930 }else{
+
3931 helios_runtime_error("ERROR (RadiationModel::zeroBuffer1D): Buffer type not supported.");
+
3932 }
+
3933
+
3934}
3935
-
3936 //get buffer size
-
3937 RTsize bsize;
-
3938 rtBufferGetSize1D( buffer, &bsize );
+
3936void RadiationModel::copyBuffer1D( RTbuffer &buffer, RTbuffer &buffer_copy ){
+
3937
+
3938 /* \todo Add support for all data types (currently only works for float and float3)*/
3939
-
3940 rtBufferSetSize1D( buffer_copy, bsize );
-
3941
-
3942 if( format==RT_FORMAT_FLOAT ){
+
3940 //get buffer format
+
3941 RTformat format;
+
3942 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
3943
-
3944 void* ptr;
-
3945 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
3946 float* data = (float*)ptr;
+
3944 //get buffer size
+
3945 RTsize bsize;
+
3946 rtBufferGetSize1D( buffer, &bsize );
3947
-
3948 void* ptr_copy;
-
3949 RT_CHECK_ERROR( rtBufferMap( buffer_copy, &ptr_copy ) );
-
3950 float* data_copy = (float*)ptr_copy;
+
3948 rtBufferSetSize1D( buffer_copy, bsize );
+
3949
+
3950 if( format==RT_FORMAT_FLOAT ){
3951
-
3952 for( size_t i = 0; i <bsize; i++ ) {
-
3953 data_copy[i] = data[i];
-
3954 }
+
3952 void* ptr;
+
3953 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
3954 float* data = (float*)ptr;
3955
-
3956 }else if( format==RT_FORMAT_FLOAT3 ){
-
3957
-
3958 void* ptr;
-
3959 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
3960 optix::float3* data = (optix::float3*)ptr;
-
3961
-
3962 void* ptr_copy;
-
3963 RT_CHECK_ERROR( rtBufferMap( buffer_copy, &ptr_copy ) );
-
3964 optix::float3* data_copy = (optix::float3*)ptr_copy;
+
3956 void* ptr_copy;
+
3957 RT_CHECK_ERROR( rtBufferMap( buffer_copy, &ptr_copy ) );
+
3958 float* data_copy = (float*)ptr_copy;
+
3959
+
3960 for( size_t i = 0; i <bsize; i++ ) {
+
3961 data_copy[i] = data[i];
+
3962 }
+
3963
+
3964 }else if( format==RT_FORMAT_FLOAT3 ){
3965
-
3966 for( size_t i = 0; i <bsize; i++ ) {
-
3967 data_copy[i] = data[i];
-
3968 }
+
3966 void* ptr;
+
3967 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
3968 optix::float3* data = (optix::float3*)ptr;
3969
-
3970 }
-
3971
-
3972 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
3973 RT_CHECK_ERROR( rtBufferUnmap( buffer_copy ) );
-
3974
-
3975}
-
3976
-
3977void RadiationModel::initializeBuffer1Dd(RTbuffer &buffer, const std::vector<double> &array ){
-
3978
-
3979 size_t bsize = array.size();
-
3980
-
3981 //set buffer size
-
3982 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
3983
-
3984 //get buffer format
-
3985 RTformat format;
-
3986 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
3987
-
3988 if( format!=RT_FORMAT_USER ){
-
3989 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dd): Buffer must have type double.");
-
3990 }
+
3970 void* ptr_copy;
+
3971 RT_CHECK_ERROR( rtBufferMap( buffer_copy, &ptr_copy ) );
+
3972 optix::float3* data_copy = (optix::float3*)ptr_copy;
+
3973
+
3974 for( size_t i = 0; i <bsize; i++ ) {
+
3975 data_copy[i] = data[i];
+
3976 }
+
3977
+
3978 }
+
3979
+
3980 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
3981 RT_CHECK_ERROR( rtBufferUnmap( buffer_copy ) );
+
3982
+
3983}
+
3984
+
3985void RadiationModel::initializeBuffer1Dd(RTbuffer &buffer, const std::vector<double> &array ){
+
3986
+
3987 size_t bsize = array.size();
+
3988
+
3989 //set buffer size
+
3990 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
3991
-
3992 void* ptr;
-
3993 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
3994
-
3995 double* data = (double*)ptr;
-
3996
-
3997 for( size_t i = 0; i <bsize; i++ ) {
-
3998 data[i] = array[i];
-
3999 }
-
4000
-
4001 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
3992 //get buffer format
+
3993 RTformat format;
+
3994 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
3995
+
3996 if( format!=RT_FORMAT_USER ){
+
3997 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dd): Buffer must have type double.");
+
3998 }
+
3999
+
4000 void* ptr;
+
4001 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4002
-
4003}
+
4003 double* data = (double*)ptr;
4004
-
4005void RadiationModel::initializeBuffer1Df(RTbuffer &buffer, const std::vector<float> &array ){
-
4006
-
4007 size_t bsize = array.size();
+
4005 for( size_t i = 0; i <bsize; i++ ) {
+
4006 data[i] = array[i];
+
4007 }
4008
-
4009 //set buffer size
-
4010 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4011
-
4012 //get buffer format
-
4013 RTformat format;
-
4014 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4015
-
4016 if( format!=RT_FORMAT_FLOAT ){
-
4017 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Df): Buffer must have type float.");
-
4018 }
+
4009 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4010
+
4011}
+
4012
+
4013void RadiationModel::initializeBuffer1Df(RTbuffer &buffer, const std::vector<float> &array ){
+
4014
+
4015 size_t bsize = array.size();
+
4016
+
4017 //set buffer size
+
4018 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4019
-
4020 void* ptr;
-
4021 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4022
-
4023 float* data = (float*)ptr;
-
4024
-
4025 for( size_t i = 0; i <bsize; i++ ) {
-
4026 data[i] = array[i];
-
4027 }
-
4028
-
4029 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4020 //get buffer format
+
4021 RTformat format;
+
4022 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4023
+
4024 if( format!=RT_FORMAT_FLOAT ){
+
4025 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Df): Buffer must have type float.");
+
4026 }
+
4027
+
4028 void* ptr;
+
4029 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4030
-
4031}
+
4031 float* data = (float*)ptr;
4032
-
4033void RadiationModel::initializeBuffer1Dfloat2(RTbuffer &buffer, const std::vector<optix::float2> &array ){
-
4034
-
4035 size_t bsize = array.size();
+
4033 for( size_t i = 0; i <bsize; i++ ) {
+
4034 data[i] = array[i];
+
4035 }
4036
-
4037 //set buffer size
-
4038 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4039
-
4040 //get buffer format
-
4041 RTformat format;
-
4042 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4043
-
4044 if( format!=RT_FORMAT_FLOAT2 ){
-
4045 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dfloat2): Buffer must have type float2.");
-
4046 }
+
4037 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4038
+
4039}
+
4040
+
4041void RadiationModel::initializeBuffer1Dfloat2(RTbuffer &buffer, const std::vector<optix::float2> &array ){
+
4042
+
4043 size_t bsize = array.size();
+
4044
+
4045 //set buffer size
+
4046 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4047
-
4048 void* ptr;
-
4049 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4050
-
4051 optix::float2* data = (optix::float2*)ptr;
-
4052
-
4053 for( size_t i = 0; i <bsize; i++ ) {
-
4054 data[i].x = array[i].x;
-
4055 data[i].y = array[i].y;
-
4056 }
-
4057
-
4058 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4059
-
4060}
-
4061
-
4062void RadiationModel::initializeBuffer1Dfloat3(RTbuffer &buffer, const std::vector<optix::float3> &array ){
-
4063
-
4064 size_t bsize = array.size();
+
4048 //get buffer format
+
4049 RTformat format;
+
4050 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4051
+
4052 if( format!=RT_FORMAT_FLOAT2 ){
+
4053 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dfloat2): Buffer must have type float2.");
+
4054 }
+
4055
+
4056 void* ptr;
+
4057 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4058
+
4059 optix::float2* data = (optix::float2*)ptr;
+
4060
+
4061 for( size_t i = 0; i <bsize; i++ ) {
+
4062 data[i].x = array[i].x;
+
4063 data[i].y = array[i].y;
+
4064 }
4065
-
4066 //set buffer size
-
4067 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4068
-
4069 //get buffer format
-
4070 RTformat format;
-
4071 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4072
-
4073 if( format!=RT_FORMAT_FLOAT3 ){
-
4074 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dfloat3): Buffer must have type float3.");
-
4075 }
+
4066 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4067
+
4068}
+
4069
+
4070void RadiationModel::initializeBuffer1Dfloat3(RTbuffer &buffer, const std::vector<optix::float3> &array ){
+
4071
+
4072 size_t bsize = array.size();
+
4073
+
4074 //set buffer size
+
4075 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4076
-
4077 void* ptr;
-
4078 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4079
-
4080 optix::float3* data = (optix::float3*)ptr;
-
4081
-
4082 for( size_t i = 0; i <bsize; i++ ) {
-
4083 data[i].x = array[i].x;
-
4084 data[i].y = array[i].y;
-
4085 data[i].z = array[i].z;
-
4086 }
+
4077 //get buffer format
+
4078 RTformat format;
+
4079 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4080
+
4081 if( format!=RT_FORMAT_FLOAT3 ){
+
4082 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dfloat3): Buffer must have type float3.");
+
4083 }
+
4084
+
4085 void* ptr;
+
4086 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4087
-
4088 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4088 optix::float3* data = (optix::float3*)ptr;
4089
-
4090}
-
4091
-
4092void RadiationModel::initializeBuffer1Dfloat4(RTbuffer &buffer, const std::vector<optix::float4> &array ){
-
4093
-
4094 size_t bsize = array.size();
+
4090 for( size_t i = 0; i <bsize; i++ ) {
+
4091 data[i].x = array[i].x;
+
4092 data[i].y = array[i].y;
+
4093 data[i].z = array[i].z;
+
4094 }
4095
-
4096 //set buffer size
-
4097 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4098
-
4099 //get buffer format
-
4100 RTformat format;
-
4101 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4102
-
4103 if( format!=RT_FORMAT_FLOAT4 ){
-
4104 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dfloat4): Buffer must have type float4.");
-
4105 }
+
4096 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4097
+
4098}
+
4099
+
4100void RadiationModel::initializeBuffer1Dfloat4(RTbuffer &buffer, const std::vector<optix::float4> &array ){
+
4101
+
4102 size_t bsize = array.size();
+
4103
+
4104 //set buffer size
+
4105 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4106
-
4107 void* ptr;
-
4108 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4109
-
4110 optix::float4* data = (optix::float4*)ptr;
-
4111
-
4112 for( size_t i = 0; i <bsize; i++ ) {
-
4113 data[i].x = array[i].x;
-
4114 data[i].y = array[i].y;
-
4115 data[i].z = array[i].z;
-
4116 data[i].w = array[i].w;
-
4117 }
-
4118
-
4119 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4120
-
4121}
-
4122
-
4123void RadiationModel::initializeBuffer1Di(RTbuffer &buffer, const std::vector<int> &array ){
-
4124
-
4125 size_t bsize = array.size();
+
4107 //get buffer format
+
4108 RTformat format;
+
4109 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4110
+
4111 if( format!=RT_FORMAT_FLOAT4 ){
+
4112 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dfloat4): Buffer must have type float4.");
+
4113 }
+
4114
+
4115 void* ptr;
+
4116 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4117
+
4118 optix::float4* data = (optix::float4*)ptr;
+
4119
+
4120 for( size_t i = 0; i <bsize; i++ ) {
+
4121 data[i].x = array[i].x;
+
4122 data[i].y = array[i].y;
+
4123 data[i].z = array[i].z;
+
4124 data[i].w = array[i].w;
+
4125 }
4126
-
4127 //set buffer size
-
4128 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4129
-
4130 //get buffer format
-
4131 RTformat format;
-
4132 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4133
-
4134 if( format!=RT_FORMAT_INT ){
-
4135 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Di): Buffer must have type int.");
-
4136 }
+
4127 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4128
+
4129}
+
4130
+
4131void RadiationModel::initializeBuffer1Di(RTbuffer &buffer, const std::vector<int> &array ){
+
4132
+
4133 size_t bsize = array.size();
+
4134
+
4135 //set buffer size
+
4136 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4137
-
4138 void* ptr;
-
4139 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4140
-
4141 int* data = (int*)ptr;
-
4142
-
4143 for( size_t i = 0; i <bsize; i++ ) {
-
4144 data[i] = array[i];
-
4145 }
-
4146
-
4147 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4138 //get buffer format
+
4139 RTformat format;
+
4140 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4141
+
4142 if( format!=RT_FORMAT_INT ){
+
4143 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Di): Buffer must have type int.");
+
4144 }
+
4145
+
4146 void* ptr;
+
4147 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4148
-
4149}
+
4149 int* data = (int*)ptr;
4150
-
4151void RadiationModel::initializeBuffer1Dui(RTbuffer &buffer, const std::vector<uint> &array ){
-
4152
-
4153 size_t bsize = array.size();
+
4151 for( size_t i = 0; i <bsize; i++ ) {
+
4152 data[i] = array[i];
+
4153 }
4154
-
4155 //set buffer size
-
4156 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4157
-
4158 //get buffer format
-
4159 RTformat format;
-
4160 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4161
-
4162 if( format!=RT_FORMAT_UNSIGNED_INT ){
-
4163 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dui): Buffer must have type unsigned int.");
-
4164 }
+
4155 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4156
+
4157}
+
4158
+
4159void RadiationModel::initializeBuffer1Dui(RTbuffer &buffer, const std::vector<uint> &array ){
+
4160
+
4161 size_t bsize = array.size();
+
4162
+
4163 //set buffer size
+
4164 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4165
-
4166 void* ptr;
-
4167 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4168
-
4169 uint* data = (uint*)ptr;
-
4170
-
4171 for( size_t i = 0; i <bsize; i++ ) {
-
4172 data[i] = array[i];
-
4173 }
-
4174
-
4175 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4166 //get buffer format
+
4167 RTformat format;
+
4168 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4169
+
4170 if( format!=RT_FORMAT_UNSIGNED_INT ){
+
4171 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dui): Buffer must have type unsigned int.");
+
4172 }
+
4173
+
4174 void* ptr;
+
4175 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4176
-
4177}
+
4177 uint* data = (uint*)ptr;
4178
-
4179void RadiationModel::initializeBuffer1Dint2(RTbuffer &buffer, const std::vector<optix::int2> &array ){
-
4180
-
4181 size_t bsize = array.size();
+
4179 for( size_t i = 0; i <bsize; i++ ) {
+
4180 data[i] = array[i];
+
4181 }
4182
-
4183 //set buffer size
-
4184 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4185
-
4186 //get buffer format
-
4187 RTformat format;
-
4188 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4189
-
4190 if( format!=RT_FORMAT_INT2 ){
-
4191 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dint2): Buffer must have type int2.");
-
4192 }
+
4183 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4184
+
4185}
+
4186
+
4187void RadiationModel::initializeBuffer1Dint2(RTbuffer &buffer, const std::vector<optix::int2> &array ){
+
4188
+
4189 size_t bsize = array.size();
+
4190
+
4191 //set buffer size
+
4192 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4193
-
4194 void* ptr;
-
4195 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4196
-
4197 optix::int2* data = (optix::int2*)ptr;
-
4198
-
4199 for( size_t i = 0; i <bsize; i++ ) {
-
4200 data[i] = array[i];
-
4201 }
-
4202
-
4203 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4194 //get buffer format
+
4195 RTformat format;
+
4196 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4197
+
4198 if( format!=RT_FORMAT_INT2 ){
+
4199 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dint2): Buffer must have type int2.");
+
4200 }
+
4201
+
4202 void* ptr;
+
4203 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4204
-
4205}
+
4205 optix::int2* data = (optix::int2*)ptr;
4206
-
4207void RadiationModel::initializeBuffer1Dint3(RTbuffer &buffer, const std::vector<optix::int3> &array ){
-
4208
-
4209 size_t bsize = array.size();
+
4207 for( size_t i = 0; i <bsize; i++ ) {
+
4208 data[i] = array[i];
+
4209 }
4210
-
4211 //set buffer size
-
4212 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4213
-
4214 //get buffer format
-
4215 RTformat format;
-
4216 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4217
-
4218 if( format!=RT_FORMAT_INT3 ){
-
4219 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dint3): Buffer must have type int3.");
-
4220 }
+
4211 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4212
+
4213}
+
4214
+
4215void RadiationModel::initializeBuffer1Dint3(RTbuffer &buffer, const std::vector<optix::int3> &array ){
+
4216
+
4217 size_t bsize = array.size();
+
4218
+
4219 //set buffer size
+
4220 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4221
-
4222 void* ptr;
-
4223 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4224
-
4225 optix::int3* data = (optix::int3*)ptr;
-
4226
-
4227 for( size_t i = 0; i <bsize; i++ ) {
-
4228 data[i] = array[i];
-
4229 }
-
4230
-
4231 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4222 //get buffer format
+
4223 RTformat format;
+
4224 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4225
+
4226 if( format!=RT_FORMAT_INT3 ){
+
4227 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dint3): Buffer must have type int3.");
+
4228 }
+
4229
+
4230 void* ptr;
+
4231 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4232
-
4233}
+
4233 optix::int3* data = (optix::int3*)ptr;
4234
-
4235void RadiationModel::initializeBuffer1Dchar(RTbuffer &buffer, const std::vector<char> &array ){
-
4236
-
4237 size_t bsize = array.size();
+
4235 for( size_t i = 0; i <bsize; i++ ) {
+
4236 data[i] = array[i];
+
4237 }
4238
-
4239 //set buffer size
-
4240 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4241
-
4242 //get buffer format
-
4243 RTformat format;
-
4244 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4245
-
4246 if( format!=RT_FORMAT_BYTE ){
-
4247 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dchar): Buffer must have type char.");
-
4248 }
+
4239 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4240
+
4241}
+
4242
+
4243void RadiationModel::initializeBuffer1Dchar(RTbuffer &buffer, const std::vector<char> &array ){
+
4244
+
4245 size_t bsize = array.size();
+
4246
+
4247 //set buffer size
+
4248 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4249
-
4250 void* ptr;
-
4251 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4252
-
4253 char* data = (char*)ptr;
-
4254
-
4255 for( size_t i = 0; i <bsize; i++ ) {
-
4256 data[i] = array[i];
-
4257 }
-
4258
-
4259 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4250 //get buffer format
+
4251 RTformat format;
+
4252 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4253
+
4254 if( format!=RT_FORMAT_BYTE ){
+
4255 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dchar): Buffer must have type char.");
+
4256 }
+
4257
+
4258 void* ptr;
+
4259 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4260
-
4261}
+
4261 char* data = (char*)ptr;
4262
-
4263void RadiationModel::zeroBuffer2D(RTbuffer &buffer, optix::int2 bsize ){
-
4264
-
4265 //set buffer size
-
4266 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4267
-
4268 //get buffer format
-
4269 RTformat format;
-
4270 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4271
-
4272 if( format==RT_FORMAT_USER ){//Note: for now we'll assume this means it's a double
-
4273 std::vector<std::vector<double> > array;
-
4274 array.resize(bsize.y);
-
4275 for( int j=0; j<bsize.y; j++ ){
-
4276 array.at(j).resize(bsize.x);
-
4277 for( int i=0; i<bsize.x; i++ ){
-
4278 array.at(j).at(i)=0.f;
-
4279 }
-
4280 }
-
4281 initializeBuffer2Dd( buffer, array );
-
4282 }else if( format==RT_FORMAT_FLOAT ){
-
4283 std::vector<std::vector<float> > array;
-
4284 array.resize(bsize.y);
-
4285 for( int j=0; j<bsize.y; j++ ){
-
4286 array.at(j).resize(bsize.x);
-
4287 for( int i=0; i<bsize.x; i++ ){
-
4288 array.at(j).at(i)=0.f;
-
4289 }
-
4290 }
-
4291 initializeBuffer2Df( buffer, array );
-
4292 }else if( format==RT_FORMAT_FLOAT2 ){
-
4293 std::vector<std::vector<optix::float2> > array;
-
4294 array.resize(bsize.y);
-
4295 for( int j=0; j<bsize.y; j++ ){
-
4296 array.at(j).resize(bsize.x);
-
4297 for( int i=0; i<bsize.x; i++ ){
-
4298 array.at(j).at(i).x=0.f;
-
4299 array.at(j).at(i).y=0.f;
-
4300 }
-
4301 }
-
4302 initializeBuffer2Dfloat2( buffer, array );
-
4303 }else if( format==RT_FORMAT_FLOAT3 ){
-
4304 std::vector<std::vector<optix::float3> > array;
-
4305 array.resize(bsize.y);
-
4306 for( int j=0; j<bsize.y; j++ ){
-
4307 array.at(j).resize(bsize.x);
-
4308 for( int i=0; i<bsize.x; i++ ){
-
4309 array.at(j).at(i).x=0.f;
-
4310 array.at(j).at(i).y=0.f;
-
4311 array.at(j).at(i).z=0.f;
-
4312 }
-
4313 }
-
4314 initializeBuffer2Dfloat3( buffer, array );
-
4315 }else if( format==RT_FORMAT_FLOAT4 ){
-
4316 std::vector<std::vector<optix::float4> > array;
-
4317 array.resize(bsize.y);
-
4318 for( int j=0; j<bsize.y; j++ ){
-
4319 array.at(j).resize(bsize.x);
-
4320 for( int i=0; i<bsize.x; i++ ){
-
4321 array.at(j).at(i).x=0.f;
-
4322 array.at(j).at(i).y=0.f;
-
4323 array.at(j).at(i).z=0.f;
-
4324 array.at(j).at(i).w=0.f;
-
4325 }
-
4326 }
-
4327 initializeBuffer2Dfloat4( buffer, array );
-
4328 }else if( format==RT_FORMAT_INT ){
-
4329 std::vector<std::vector<int> > array;
-
4330 array.resize(bsize.y);
-
4331 for( int j=0; j<bsize.y; j++ ){
-
4332 array.at(j).resize(bsize.x);
-
4333 for( int i=0; i<bsize.x; i++ ){
-
4334 array.at(j).at(i)=0;
-
4335 }
-
4336 }
-
4337 initializeBuffer2Di( buffer, array );
-
4338 }else if( format==RT_FORMAT_UNSIGNED_INT ){
-
4339 std::vector<std::vector<uint> > array;
-
4340 array.resize(bsize.y);
-
4341 for( int j=0; j<bsize.y; j++ ){
-
4342 array.at(j).resize(bsize.x);
-
4343 for( int i=0; i<bsize.x; i++ ){
-
4344 array.at(j).at(i)=0;
-
4345 }
-
4346 }
-
4347 initializeBuffer2Dui( buffer, array );
-
4348 }else if( format==RT_FORMAT_INT2 ){
-
4349 std::vector<std::vector<optix::int2> > array;
-
4350 array.resize(bsize.y);
-
4351 for( int j=0; j<bsize.y; j++ ){
-
4352 array.at(j).resize(bsize.x);
-
4353 for( int i=0; i<bsize.x; i++ ){
-
4354 array.at(j).at(i).x=0;
-
4355 array.at(j).at(i).y=0;
-
4356 }
-
4357 }
-
4358 initializeBuffer2Dint2( buffer, array );
-
4359 }else if( format==RT_FORMAT_INT3 ){
-
4360 std::vector<std::vector<optix::int3> > array;
-
4361 array.resize(bsize.y);
-
4362 for( int j=0; j<bsize.y; j++ ){
-
4363 array.at(j).resize(bsize.x);
-
4364 for( int i=0; i<bsize.x; i++ ){
-
4365 array.at(j).at(i).x=0;
-
4366 array.at(j).at(i).y=0;
-
4367 array.at(j).at(i).z=0;
-
4368 }
-
4369 }
-
4370 initializeBuffer2Dint3( buffer, array );
-
4371 }else if( format==RT_FORMAT_BYTE ){
-
4372 std::vector<std::vector<bool> > array;
-
4373 array.resize(bsize.y);
-
4374 for( int j=0; j<bsize.y; j++ ){
-
4375 array.at(j).resize(bsize.x);
-
4376 for( int i=0; i<bsize.x; i++ ){
-
4377 array.at(j).at(i)=false;
-
4378 }
-
4379 }
-
4380 initializeBuffer2Dbool( buffer, array );
-
4381 }else{
-
4382 helios_runtime_error("ERROR (RadiationModel::zeroBuffer2D): unknown buffer format.");
-
4383 }
-
4384
-
4385}
-
4386
-
4387void RadiationModel::initializeBuffer2Dd(RTbuffer &buffer, const std::vector<std::vector<double>> &array ){
-
4388
-
4389 optix::int2 bsize;
-
4390 bsize.y = array.size();
-
4391 if( bsize.y==0 ){
-
4392 bsize.x = 0;
-
4393 }else{
-
4394 bsize.x = array.front().size();
-
4395 }
+
4263 for( size_t i = 0; i <bsize; i++ ) {
+
4264 data[i] = array[i];
+
4265 }
+
4266
+
4267 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4268
+
4269}
+
4270
+
4271void RadiationModel::zeroBuffer2D(RTbuffer &buffer, optix::int2 bsize ){
+
4272
+
4273 //set buffer size
+
4274 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4275
+
4276 //get buffer format
+
4277 RTformat format;
+
4278 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4279
+
4280 if( format==RT_FORMAT_USER ){//Note: for now we'll assume this means it's a double
+
4281 std::vector<std::vector<double> > array;
+
4282 array.resize(bsize.y);
+
4283 for( int j=0; j<bsize.y; j++ ){
+
4284 array.at(j).resize(bsize.x);
+
4285 for( int i=0; i<bsize.x; i++ ){
+
4286 array.at(j).at(i)=0.f;
+
4287 }
+
4288 }
+
4289 initializeBuffer2Dd( buffer, array );
+
4290 }else if( format==RT_FORMAT_FLOAT ){
+
4291 std::vector<std::vector<float> > array;
+
4292 array.resize(bsize.y);
+
4293 for( int j=0; j<bsize.y; j++ ){
+
4294 array.at(j).resize(bsize.x);
+
4295 for( int i=0; i<bsize.x; i++ ){
+
4296 array.at(j).at(i)=0.f;
+
4297 }
+
4298 }
+
4299 initializeBuffer2Df( buffer, array );
+
4300 }else if( format==RT_FORMAT_FLOAT2 ){
+
4301 std::vector<std::vector<optix::float2> > array;
+
4302 array.resize(bsize.y);
+
4303 for( int j=0; j<bsize.y; j++ ){
+
4304 array.at(j).resize(bsize.x);
+
4305 for( int i=0; i<bsize.x; i++ ){
+
4306 array.at(j).at(i).x=0.f;
+
4307 array.at(j).at(i).y=0.f;
+
4308 }
+
4309 }
+
4310 initializeBuffer2Dfloat2( buffer, array );
+
4311 }else if( format==RT_FORMAT_FLOAT3 ){
+
4312 std::vector<std::vector<optix::float3> > array;
+
4313 array.resize(bsize.y);
+
4314 for( int j=0; j<bsize.y; j++ ){
+
4315 array.at(j).resize(bsize.x);
+
4316 for( int i=0; i<bsize.x; i++ ){
+
4317 array.at(j).at(i).x=0.f;
+
4318 array.at(j).at(i).y=0.f;
+
4319 array.at(j).at(i).z=0.f;
+
4320 }
+
4321 }
+
4322 initializeBuffer2Dfloat3( buffer, array );
+
4323 }else if( format==RT_FORMAT_FLOAT4 ){
+
4324 std::vector<std::vector<optix::float4> > array;
+
4325 array.resize(bsize.y);
+
4326 for( int j=0; j<bsize.y; j++ ){
+
4327 array.at(j).resize(bsize.x);
+
4328 for( int i=0; i<bsize.x; i++ ){
+
4329 array.at(j).at(i).x=0.f;
+
4330 array.at(j).at(i).y=0.f;
+
4331 array.at(j).at(i).z=0.f;
+
4332 array.at(j).at(i).w=0.f;
+
4333 }
+
4334 }
+
4335 initializeBuffer2Dfloat4( buffer, array );
+
4336 }else if( format==RT_FORMAT_INT ){
+
4337 std::vector<std::vector<int> > array;
+
4338 array.resize(bsize.y);
+
4339 for( int j=0; j<bsize.y; j++ ){
+
4340 array.at(j).resize(bsize.x);
+
4341 for( int i=0; i<bsize.x; i++ ){
+
4342 array.at(j).at(i)=0;
+
4343 }
+
4344 }
+
4345 initializeBuffer2Di( buffer, array );
+
4346 }else if( format==RT_FORMAT_UNSIGNED_INT ){
+
4347 std::vector<std::vector<uint> > array;
+
4348 array.resize(bsize.y);
+
4349 for( int j=0; j<bsize.y; j++ ){
+
4350 array.at(j).resize(bsize.x);
+
4351 for( int i=0; i<bsize.x; i++ ){
+
4352 array.at(j).at(i)=0;
+
4353 }
+
4354 }
+
4355 initializeBuffer2Dui( buffer, array );
+
4356 }else if( format==RT_FORMAT_INT2 ){
+
4357 std::vector<std::vector<optix::int2> > array;
+
4358 array.resize(bsize.y);
+
4359 for( int j=0; j<bsize.y; j++ ){
+
4360 array.at(j).resize(bsize.x);
+
4361 for( int i=0; i<bsize.x; i++ ){
+
4362 array.at(j).at(i).x=0;
+
4363 array.at(j).at(i).y=0;
+
4364 }
+
4365 }
+
4366 initializeBuffer2Dint2( buffer, array );
+
4367 }else if( format==RT_FORMAT_INT3 ){
+
4368 std::vector<std::vector<optix::int3> > array;
+
4369 array.resize(bsize.y);
+
4370 for( int j=0; j<bsize.y; j++ ){
+
4371 array.at(j).resize(bsize.x);
+
4372 for( int i=0; i<bsize.x; i++ ){
+
4373 array.at(j).at(i).x=0;
+
4374 array.at(j).at(i).y=0;
+
4375 array.at(j).at(i).z=0;
+
4376 }
+
4377 }
+
4378 initializeBuffer2Dint3( buffer, array );
+
4379 }else if( format==RT_FORMAT_BYTE ){
+
4380 std::vector<std::vector<bool> > array;
+
4381 array.resize(bsize.y);
+
4382 for( int j=0; j<bsize.y; j++ ){
+
4383 array.at(j).resize(bsize.x);
+
4384 for( int i=0; i<bsize.x; i++ ){
+
4385 array.at(j).at(i)=false;
+
4386 }
+
4387 }
+
4388 initializeBuffer2Dbool( buffer, array );
+
4389 }else{
+
4390 helios_runtime_error("ERROR (RadiationModel::zeroBuffer2D): unknown buffer format.");
+
4391 }
+
4392
+
4393}
+
4394
+
4395void RadiationModel::initializeBuffer2Dd(RTbuffer &buffer, const std::vector<std::vector<double>> &array ){
4396
-
4397 //set buffer size
-
4398 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4399
-
4400 //get buffer formatsyn
-
4401 RTformat format;
-
4402 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4403
-
4404 void* ptr;
-
4405 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4406
-
4407 if( format==RT_FORMAT_USER ){
-
4408 double* data = (double*)ptr;
-
4409 for( size_t j = 0; j<bsize.y; j++ ) {
-
4410 for( size_t i = 0; i<bsize.x; i++ ) {
-
4411 data[i+j*bsize.x] = array[j][i];
-
4412 }
-
4413 }
-
4414 }else{
-
4415 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dd): Buffer does not have format 'RT_FORMAT_USER'.");
-
4416 }
-
4417
-
4418 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4419
-
4420}
-
4421
-
4422void RadiationModel::initializeBuffer2Df(RTbuffer &buffer, const std::vector<std::vector<float>> &array ){
-
4423
-
4424 optix::int2 bsize;
-
4425 bsize.y = array.size();
-
4426 if( bsize.y==0 ){
-
4427 bsize.x = 0;
-
4428 }else{
-
4429 bsize.x = array.front().size();
-
4430 }
+
4397 optix::int2 bsize;
+
4398 bsize.y = array.size();
+
4399 if( bsize.y==0 ){
+
4400 bsize.x = 0;
+
4401 }else{
+
4402 bsize.x = array.front().size();
+
4403 }
+
4404
+
4405 //set buffer size
+
4406 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4407
+
4408 //get buffer formatsyn
+
4409 RTformat format;
+
4410 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4411
+
4412 void* ptr;
+
4413 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4414
+
4415 if( format==RT_FORMAT_USER ){
+
4416 double* data = (double*)ptr;
+
4417 for( size_t j = 0; j<bsize.y; j++ ) {
+
4418 for( size_t i = 0; i<bsize.x; i++ ) {
+
4419 data[i+j*bsize.x] = array[j][i];
+
4420 }
+
4421 }
+
4422 }else{
+
4423 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dd): Buffer does not have format 'RT_FORMAT_USER'.");
+
4424 }
+
4425
+
4426 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4427
+
4428}
+
4429
+
4430void RadiationModel::initializeBuffer2Df(RTbuffer &buffer, const std::vector<std::vector<float>> &array ){
4431
-
4432 //set buffer size
-
4433 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4434
-
4435 //get buffer format
-
4436 RTformat format;
-
4437 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4438
-
4439 void* ptr;
-
4440 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4441
-
4442 if( format==RT_FORMAT_FLOAT ){
-
4443 float* data = (float*)ptr;
-
4444 for( size_t j = 0; j<bsize.y; j++ ) {
-
4445 for( size_t i = 0; i<bsize.x; i++ ) {
-
4446 data[i+j*bsize.x] = array[j][i];
-
4447 }
-
4448 }
-
4449 }else{
-
4450 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Df): Buffer does not have format 'RT_FORMAT_FLOAT'.");
-
4451 }
-
4452
-
4453 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4454
-
4455}
-
4456
-
4457void RadiationModel::initializeBuffer2Dfloat2(RTbuffer &buffer, const std::vector<std::vector<optix::float2>> &array ){
-
4458
-
4459 optix::int2 bsize;
-
4460 bsize.y = array.size();
-
4461 if( bsize.y==0 ){
-
4462 bsize.x = 0;
-
4463 }else{
-
4464 bsize.x = array.front().size();
-
4465 }
+
4432 optix::int2 bsize;
+
4433 bsize.y = array.size();
+
4434 if( bsize.y==0 ){
+
4435 bsize.x = 0;
+
4436 }else{
+
4437 bsize.x = array.front().size();
+
4438 }
+
4439
+
4440 //set buffer size
+
4441 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4442
+
4443 //get buffer format
+
4444 RTformat format;
+
4445 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4446
+
4447 void* ptr;
+
4448 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4449
+
4450 if( format==RT_FORMAT_FLOAT ){
+
4451 float* data = (float*)ptr;
+
4452 for( size_t j = 0; j<bsize.y; j++ ) {
+
4453 for( size_t i = 0; i<bsize.x; i++ ) {
+
4454 data[i+j*bsize.x] = array[j][i];
+
4455 }
+
4456 }
+
4457 }else{
+
4458 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Df): Buffer does not have format 'RT_FORMAT_FLOAT'.");
+
4459 }
+
4460
+
4461 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4462
+
4463}
+
4464
+
4465void RadiationModel::initializeBuffer2Dfloat2(RTbuffer &buffer, const std::vector<std::vector<optix::float2>> &array ){
4466
-
4467 //set buffer size
-
4468 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4469
-
4470 //get buffer format
-
4471 RTformat format;
-
4472 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4473
-
4474 void* ptr;
-
4475 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4476
-
4477 if( format==RT_FORMAT_FLOAT2 ){
-
4478 optix::float2* data = (optix::float2*)ptr;
-
4479 for( size_t j = 0; j<bsize.y; j++ ) {
-
4480 for( size_t i = 0; i<bsize.x; i++ ) {
-
4481 data[i+j*bsize.x].x = array[j][i].x;
-
4482 data[i+j*bsize.x].y = array[j][i].y;
-
4483 }
-
4484 }
-
4485 }else{
-
4486 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dfloat2): Buffer does not have format 'RT_FORMAT_FLOAT2'.");
-
4487 }
-
4488
-
4489 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4490
-
4491}
-
4492
-
4493void RadiationModel::initializeBuffer2Dfloat3(RTbuffer &buffer, const std::vector<std::vector<optix::float3>> &array ){
-
4494
-
4495 optix::int2 bsize;
-
4496 bsize.y = array.size();
-
4497 if( bsize.y==0 ){
-
4498 bsize.x = 0;
-
4499 }else{
-
4500 bsize.x = array.front().size();
-
4501 }
+
4467 optix::int2 bsize;
+
4468 bsize.y = array.size();
+
4469 if( bsize.y==0 ){
+
4470 bsize.x = 0;
+
4471 }else{
+
4472 bsize.x = array.front().size();
+
4473 }
+
4474
+
4475 //set buffer size
+
4476 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4477
+
4478 //get buffer format
+
4479 RTformat format;
+
4480 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4481
+
4482 void* ptr;
+
4483 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4484
+
4485 if( format==RT_FORMAT_FLOAT2 ){
+
4486 optix::float2* data = (optix::float2*)ptr;
+
4487 for( size_t j = 0; j<bsize.y; j++ ) {
+
4488 for( size_t i = 0; i<bsize.x; i++ ) {
+
4489 data[i+j*bsize.x].x = array[j][i].x;
+
4490 data[i+j*bsize.x].y = array[j][i].y;
+
4491 }
+
4492 }
+
4493 }else{
+
4494 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dfloat2): Buffer does not have format 'RT_FORMAT_FLOAT2'.");
+
4495 }
+
4496
+
4497 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4498
+
4499}
+
4500
+
4501void RadiationModel::initializeBuffer2Dfloat3(RTbuffer &buffer, const std::vector<std::vector<optix::float3>> &array ){
4502
-
4503 //set buffer size
-
4504 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4505
-
4506 //get buffer format
-
4507 RTformat format;
-
4508 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4509
-
4510 void* ptr;
-
4511 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4512
-
4513 if( format==RT_FORMAT_FLOAT3 ){
-
4514 optix::float3* data = (optix::float3*)ptr;
-
4515 for( size_t j = 0; j<bsize.y; j++ ) {
-
4516 for( size_t i = 0; i<bsize.x; i++ ) {
-
4517 data[i+j*bsize.x].x = array.at(j).at(i).x;
-
4518 data[i+j*bsize.x].y = array.at(j).at(i).y;
-
4519 data[i+j*bsize.x].z = array.at(j).at(i).z;
-
4520 }
-
4521 }
-
4522 }else{
-
4523 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dfloat3): Buffer does not have format 'RT_FORMAT_FLOAT3'.");
-
4524 }
-
4525
-
4526 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4527
-
4528}
-
4529
-
4530void RadiationModel::initializeBuffer2Dfloat4(RTbuffer &buffer, const std::vector<std::vector<optix::float4>> &array ){
-
4531
-
4532 optix::int2 bsize;
-
4533 bsize.y = array.size();
-
4534 if( bsize.y==0 ){
-
4535 bsize.x = 0;
-
4536 }else{
-
4537 bsize.x = array.front().size();
-
4538 }
+
4503 optix::int2 bsize;
+
4504 bsize.y = array.size();
+
4505 if( bsize.y==0 ){
+
4506 bsize.x = 0;
+
4507 }else{
+
4508 bsize.x = array.front().size();
+
4509 }
+
4510
+
4511 //set buffer size
+
4512 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4513
+
4514 //get buffer format
+
4515 RTformat format;
+
4516 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4517
+
4518 void* ptr;
+
4519 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4520
+
4521 if( format==RT_FORMAT_FLOAT3 ){
+
4522 optix::float3* data = (optix::float3*)ptr;
+
4523 for( size_t j = 0; j<bsize.y; j++ ) {
+
4524 for( size_t i = 0; i<bsize.x; i++ ) {
+
4525 data[i+j*bsize.x].x = array.at(j).at(i).x;
+
4526 data[i+j*bsize.x].y = array.at(j).at(i).y;
+
4527 data[i+j*bsize.x].z = array.at(j).at(i).z;
+
4528 }
+
4529 }
+
4530 }else{
+
4531 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dfloat3): Buffer does not have format 'RT_FORMAT_FLOAT3'.");
+
4532 }
+
4533
+
4534 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4535
+
4536}
+
4537
+
4538void RadiationModel::initializeBuffer2Dfloat4(RTbuffer &buffer, const std::vector<std::vector<optix::float4>> &array ){
4539
-
4540 //set buffer size
-
4541 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4542
-
4543 //get buffer format
-
4544 RTformat format;
-
4545 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4546
-
4547 void* ptr;
-
4548 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4549
-
4550 if( format==RT_FORMAT_FLOAT4 ){
-
4551 optix::float4* data = (optix::float4*)ptr;
-
4552 for( size_t j = 0; j<bsize.y; j++ ) {
-
4553 for( size_t i = 0; i<bsize.x; i++ ) {
-
4554 data[i+j*bsize.x].x = array[j][i].x;
-
4555 data[i+j*bsize.x].y = array[j][i].y;
-
4556 data[i+j*bsize.x].z = array[j][i].z;
-
4557 data[i+j*bsize.x].w = array[j][i].w;
-
4558 }
-
4559 }
-
4560 }else{
-
4561 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dfloat4): Buffer does not have format 'RT_FORMAT_FLOAT4'.");
-
4562 }
-
4563
-
4564 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4565
-
4566}
-
4567
-
4568void RadiationModel::initializeBuffer2Di(RTbuffer &buffer, const std::vector<std::vector<int>> &array ){
-
4569
-
4570 optix::int2 bsize;
-
4571 bsize.y = array.size();
-
4572 if( bsize.y==0 ){
-
4573 bsize.x = 0;
-
4574 }else{
-
4575 bsize.x = array.front().size();
-
4576 }
+
4540 optix::int2 bsize;
+
4541 bsize.y = array.size();
+
4542 if( bsize.y==0 ){
+
4543 bsize.x = 0;
+
4544 }else{
+
4545 bsize.x = array.front().size();
+
4546 }
+
4547
+
4548 //set buffer size
+
4549 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4550
+
4551 //get buffer format
+
4552 RTformat format;
+
4553 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4554
+
4555 void* ptr;
+
4556 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4557
+
4558 if( format==RT_FORMAT_FLOAT4 ){
+
4559 optix::float4* data = (optix::float4*)ptr;
+
4560 for( size_t j = 0; j<bsize.y; j++ ) {
+
4561 for( size_t i = 0; i<bsize.x; i++ ) {
+
4562 data[i+j*bsize.x].x = array[j][i].x;
+
4563 data[i+j*bsize.x].y = array[j][i].y;
+
4564 data[i+j*bsize.x].z = array[j][i].z;
+
4565 data[i+j*bsize.x].w = array[j][i].w;
+
4566 }
+
4567 }
+
4568 }else{
+
4569 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dfloat4): Buffer does not have format 'RT_FORMAT_FLOAT4'.");
+
4570 }
+
4571
+
4572 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4573
+
4574}
+
4575
+
4576void RadiationModel::initializeBuffer2Di(RTbuffer &buffer, const std::vector<std::vector<int>> &array ){
4577
-
4578 //set buffer size
-
4579 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4580
-
4581 //get buffer format
-
4582 RTformat format;
-
4583 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4584
-
4585 void* ptr;
-
4586 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4587
-
4588 if( format==RT_FORMAT_INT ){
-
4589 int* data = (int*)ptr;
-
4590 for( size_t j = 0; j<bsize.y; j++ ) {
-
4591 for( size_t i = 0; i<bsize.x; i++ ) {
-
4592 data[i+j*bsize.x] = array[j][i];
-
4593 }
-
4594 }
-
4595 }else{
-
4596 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Di): Buffer does not have format 'RT_FORMAT_INT'.");
-
4597 }
-
4598
-
4599 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4600
-
4601}
-
4602
-
4603void RadiationModel::initializeBuffer2Dui(RTbuffer &buffer, const std::vector<std::vector<uint>> &array ){
-
4604
-
4605 optix::int2 bsize;
-
4606 bsize.y = array.size();
-
4607 if( bsize.y==0 ){
-
4608 bsize.x = 0;
-
4609 }else{
-
4610 bsize.x = array.front().size();
-
4611 }
+
4578 optix::int2 bsize;
+
4579 bsize.y = array.size();
+
4580 if( bsize.y==0 ){
+
4581 bsize.x = 0;
+
4582 }else{
+
4583 bsize.x = array.front().size();
+
4584 }
+
4585
+
4586 //set buffer size
+
4587 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4588
+
4589 //get buffer format
+
4590 RTformat format;
+
4591 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4592
+
4593 void* ptr;
+
4594 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4595
+
4596 if( format==RT_FORMAT_INT ){
+
4597 int* data = (int*)ptr;
+
4598 for( size_t j = 0; j<bsize.y; j++ ) {
+
4599 for( size_t i = 0; i<bsize.x; i++ ) {
+
4600 data[i+j*bsize.x] = array[j][i];
+
4601 }
+
4602 }
+
4603 }else{
+
4604 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Di): Buffer does not have format 'RT_FORMAT_INT'.");
+
4605 }
+
4606
+
4607 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4608
+
4609}
+
4610
+
4611void RadiationModel::initializeBuffer2Dui(RTbuffer &buffer, const std::vector<std::vector<uint>> &array ){
4612
-
4613 //set buffer size
-
4614 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4615
-
4616 //get buffer format
-
4617 RTformat format;
-
4618 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4619
-
4620 void* ptr;
-
4621 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4622
-
4623 if( format==RT_FORMAT_UNSIGNED_INT ){
-
4624 uint* data = (uint*)ptr;
-
4625 for( size_t j = 0; j<bsize.y; j++ ) {
-
4626 for( size_t i = 0; i<bsize.x; i++ ) {
-
4627 data[i+j*bsize.x] = array[j][i];
-
4628 }
-
4629 }
-
4630 }else{
-
4631 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dui): Buffer does not have format 'RT_FORMAT_UNSIGNED_INT'.");
-
4632 }
-
4633
-
4634 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4635
-
4636}
-
4637
-
4638void RadiationModel::initializeBuffer2Dint2(RTbuffer &buffer, const std::vector<std::vector<optix::int2>> &array ){
-
4639
-
4640 optix::int2 bsize;
-
4641 bsize.y = array.size();
-
4642 if( bsize.y==0 ){
-
4643 bsize.x = 0;
-
4644 }else{
-
4645 bsize.x = array.front().size();
-
4646 }
+
4613 optix::int2 bsize;
+
4614 bsize.y = array.size();
+
4615 if( bsize.y==0 ){
+
4616 bsize.x = 0;
+
4617 }else{
+
4618 bsize.x = array.front().size();
+
4619 }
+
4620
+
4621 //set buffer size
+
4622 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4623
+
4624 //get buffer format
+
4625 RTformat format;
+
4626 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4627
+
4628 void* ptr;
+
4629 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4630
+
4631 if( format==RT_FORMAT_UNSIGNED_INT ){
+
4632 uint* data = (uint*)ptr;
+
4633 for( size_t j = 0; j<bsize.y; j++ ) {
+
4634 for( size_t i = 0; i<bsize.x; i++ ) {
+
4635 data[i+j*bsize.x] = array[j][i];
+
4636 }
+
4637 }
+
4638 }else{
+
4639 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dui): Buffer does not have format 'RT_FORMAT_UNSIGNED_INT'.");
+
4640 }
+
4641
+
4642 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4643
+
4644}
+
4645
+
4646void RadiationModel::initializeBuffer2Dint2(RTbuffer &buffer, const std::vector<std::vector<optix::int2>> &array ){
4647
-
4648 //set buffer size
-
4649 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4650
-
4651 //get buffer format
-
4652 RTformat format;
-
4653 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4654
-
4655 void* ptr;
-
4656 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4657
-
4658 if( format==RT_FORMAT_INT2 ){
-
4659 optix::int2* data = (optix::int2*)ptr;
-
4660 for( size_t j = 0; j<bsize.y; j++ ) {
-
4661 for( size_t i = 0; i<bsize.x; i++ ) {
-
4662 data[i+j*bsize.x].x = array[j][i].x;
-
4663 data[i+j*bsize.x].y = array[j][i].y;
-
4664 }
-
4665 }
-
4666 }else{
-
4667 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dint2): Buffer does not have format 'RT_FORMAT_INT2'.");
-
4668 }
-
4669
-
4670 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4671
-
4672}
-
4673
-
4674void RadiationModel::initializeBuffer2Dint3(RTbuffer &buffer, const std::vector<std::vector<optix::int3>> &array ){
-
4675
-
4676 optix::int2 bsize;
-
4677 bsize.y = array.size();
-
4678 if( bsize.y==0 ){
-
4679 bsize.x = 0;
-
4680 }else{
-
4681 bsize.x = array.front().size();
-
4682 }
+
4648 optix::int2 bsize;
+
4649 bsize.y = array.size();
+
4650 if( bsize.y==0 ){
+
4651 bsize.x = 0;
+
4652 }else{
+
4653 bsize.x = array.front().size();
+
4654 }
+
4655
+
4656 //set buffer size
+
4657 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4658
+
4659 //get buffer format
+
4660 RTformat format;
+
4661 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4662
+
4663 void* ptr;
+
4664 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4665
+
4666 if( format==RT_FORMAT_INT2 ){
+
4667 optix::int2* data = (optix::int2*)ptr;
+
4668 for( size_t j = 0; j<bsize.y; j++ ) {
+
4669 for( size_t i = 0; i<bsize.x; i++ ) {
+
4670 data[i+j*bsize.x].x = array[j][i].x;
+
4671 data[i+j*bsize.x].y = array[j][i].y;
+
4672 }
+
4673 }
+
4674 }else{
+
4675 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dint2): Buffer does not have format 'RT_FORMAT_INT2'.");
+
4676 }
+
4677
+
4678 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4679
+
4680}
+
4681
+
4682void RadiationModel::initializeBuffer2Dint3(RTbuffer &buffer, const std::vector<std::vector<optix::int3>> &array ){
4683
-
4684 //set buffer size
-
4685 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4686
-
4687 //get buffer format
-
4688 RTformat format;
-
4689 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4690
-
4691 void* ptr;
-
4692 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4693
-
4694 if( format==RT_FORMAT_INT3 ){
-
4695 optix::int3* data = (optix::int3*)ptr;
-
4696 for( size_t j = 0; j<bsize.y; j++ ) {
-
4697 for( size_t i = 0; i<bsize.x; i++ ) {
-
4698 data[i+j*bsize.x].x = array[j][i].x;
-
4699 data[i+j*bsize.x].y = array[j][i].y;
-
4700 data[i+j*bsize.x].z = array[j][i].z;
-
4701 }
-
4702 }
-
4703 }else{
-
4704 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dint3): Buffer does not have format 'RT_FORMAT_INT3'.");
-
4705 }
-
4706
-
4707 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4708
-
4709}
-
4710
-
4711void RadiationModel::initializeBuffer2Dbool(RTbuffer &buffer, const std::vector<std::vector<bool>> &array ){
-
4712
-
4713 optix::int2 bsize;
-
4714 bsize.y = array.size();
-
4715 if( bsize.y==0 ){
-
4716 bsize.x = 0;
-
4717 }else{
-
4718 bsize.x = array.front().size();
-
4719 }
+
4684 optix::int2 bsize;
+
4685 bsize.y = array.size();
+
4686 if( bsize.y==0 ){
+
4687 bsize.x = 0;
+
4688 }else{
+
4689 bsize.x = array.front().size();
+
4690 }
+
4691
+
4692 //set buffer size
+
4693 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4694
+
4695 //get buffer format
+
4696 RTformat format;
+
4697 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4698
+
4699 void* ptr;
+
4700 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4701
+
4702 if( format==RT_FORMAT_INT3 ){
+
4703 optix::int3* data = (optix::int3*)ptr;
+
4704 for( size_t j = 0; j<bsize.y; j++ ) {
+
4705 for( size_t i = 0; i<bsize.x; i++ ) {
+
4706 data[i+j*bsize.x].x = array[j][i].x;
+
4707 data[i+j*bsize.x].y = array[j][i].y;
+
4708 data[i+j*bsize.x].z = array[j][i].z;
+
4709 }
+
4710 }
+
4711 }else{
+
4712 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dint3): Buffer does not have format 'RT_FORMAT_INT3'.");
+
4713 }
+
4714
+
4715 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4716
+
4717}
+
4718
+
4719void RadiationModel::initializeBuffer2Dbool(RTbuffer &buffer, const std::vector<std::vector<bool>> &array ){
4720
-
4721 //set buffer size
-
4722 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4723
-
4724 //get buffer format
-
4725 RTformat format;
-
4726 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4727
-
4728 void* ptr;
-
4729 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4730
-
4731 if( format==RT_FORMAT_BYTE ){
-
4732 bool* data = (bool*)ptr;
-
4733 for( size_t j = 0; j<bsize.y; j++ ) {
-
4734 for( size_t i = 0; i<bsize.x; i++ ) {
-
4735 data[i+j*bsize.x] = array[j][i];
-
4736 }
-
4737 }
-
4738 }else{
-
4739 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dbool): Buffer does not have format 'RT_FORMAT_BYTE'.");
-
4740 }
-
4741
-
4742 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4743
-
4744}
-
4745
-
4746template <typename anytype>
-
4747void RadiationModel::initializeBuffer3D(RTbuffer &buffer, const std::vector<std::vector<std::vector<anytype>>> &array ){
-
4748
-
4749 optix::int3 bsize;
-
4750 bsize.z = array.size();
-
4751 if( bsize.z==0 ){
-
4752 bsize.y=0;
-
4753 bsize.x=0;
-
4754 }else{
-
4755 bsize.y=array.front().size();
-
4756 if( bsize.y==0 ){
-
4757 bsize.x=0;
-
4758 }else{
-
4759 bsize.x = array.front().front().size();
-
4760 }
-
4761 }
-
4762
-
4763 //set buffer size
-
4764 RT_CHECK_ERROR( rtBufferSetSize3D( buffer, bsize.x, bsize.y, bsize.z ) );
-
4765
-
4766 //get buffer format
-
4767 RTformat format;
-
4768 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4769
-
4770 //zero out buffer
-
4771 void* ptr;
-
4772 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4721 optix::int2 bsize;
+
4722 bsize.y = array.size();
+
4723 if( bsize.y==0 ){
+
4724 bsize.x = 0;
+
4725 }else{
+
4726 bsize.x = array.front().size();
+
4727 }
+
4728
+
4729 //set buffer size
+
4730 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4731
+
4732 //get buffer format
+
4733 RTformat format;
+
4734 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4735
+
4736 void* ptr;
+
4737 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4738
+
4739 if( format==RT_FORMAT_BYTE ){
+
4740 bool* data = (bool*)ptr;
+
4741 for( size_t j = 0; j<bsize.y; j++ ) {
+
4742 for( size_t i = 0; i<bsize.x; i++ ) {
+
4743 data[i+j*bsize.x] = array[j][i];
+
4744 }
+
4745 }
+
4746 }else{
+
4747 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dbool): Buffer does not have format 'RT_FORMAT_BYTE'.");
+
4748 }
+
4749
+
4750 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4751
+
4752}
+
4753
+
4754template <typename anytype>
+
4755void RadiationModel::initializeBuffer3D(RTbuffer &buffer, const std::vector<std::vector<std::vector<anytype>>> &array ){
+
4756
+
4757 optix::int3 bsize;
+
4758 bsize.z = array.size();
+
4759 if( bsize.z==0 ){
+
4760 bsize.y=0;
+
4761 bsize.x=0;
+
4762 }else{
+
4763 bsize.y=array.front().size();
+
4764 if( bsize.y==0 ){
+
4765 bsize.x=0;
+
4766 }else{
+
4767 bsize.x = array.front().front().size();
+
4768 }
+
4769 }
+
4770
+
4771 //set buffer size
+
4772 RT_CHECK_ERROR( rtBufferSetSize3D( buffer, bsize.x, bsize.y, bsize.z ) );
4773
-
4774 if( format==RT_FORMAT_FLOAT ){
-
4775 float* data = (float*)ptr;
-
4776 for( size_t k = 0; k<bsize.z; k++ ) {
-
4777 for( size_t j = 0; j<bsize.y; j++ ) {
-
4778 for( size_t i = 0; i<bsize.x; i++ ) {
-
4779 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
-
4780 }
-
4781 }
-
4782 }
-
4783 }else if( format==RT_FORMAT_INT ){
-
4784 int* data = (int*)ptr;
-
4785 for( size_t k = 0; k<bsize.z; k++ ) {
-
4786 for( size_t j = 0; j<bsize.y; j++ ) {
-
4787 for( size_t i = 0; i<bsize.x; i++ ) {
-
4788 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
-
4789 }
-
4790 }
-
4791 }
-
4792 }else if( format==RT_FORMAT_UNSIGNED_INT ){
-
4793 uint* data = (uint*)ptr;
-
4794 for( size_t k = 0; k<bsize.z; k++ ) {
-
4795 for( size_t j = 0; j<bsize.y; j++ ) {
-
4796 for( size_t i = 0; i<bsize.x; i++ ) {
-
4797 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
-
4798 }
-
4799 }
-
4800 }
-
4801 }else if( format==RT_FORMAT_BYTE ){
-
4802 bool* data = (bool*)ptr;
-
4803 for( size_t k = 0; k<bsize.z; k++ ) {
-
4804 for( size_t j = 0; j<bsize.y; j++ ) {
-
4805 for( size_t i = 0; i<bsize.x; i++ ) {
-
4806 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
-
4807 }
-
4808 }
-
4809 }
-
4810 }else{
-
4811 std::cerr<< "ERROR (RadiationModel::initializeBuffer3D): unsupported buffer format." << std::endl;
-
4812
-
4813 }
-
4814
-
4815 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4816
-
4817
-
4818}
-
4819
-
- -
4821
-
4822 vec3 dir = view_direction;
-
4823 dir.normalize();
+
4774 //get buffer format
+
4775 RTformat format;
+
4776 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4777
+
4778 //zero out buffer
+
4779 void* ptr;
+
4780 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4781
+
4782 if( format==RT_FORMAT_FLOAT ){
+
4783 float* data = (float*)ptr;
+
4784 for( size_t k = 0; k<bsize.z; k++ ) {
+
4785 for( size_t j = 0; j<bsize.y; j++ ) {
+
4786 for( size_t i = 0; i<bsize.x; i++ ) {
+
4787 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
+
4788 }
+
4789 }
+
4790 }
+
4791 }else if( format==RT_FORMAT_INT ){
+
4792 int* data = (int*)ptr;
+
4793 for( size_t k = 0; k<bsize.z; k++ ) {
+
4794 for( size_t j = 0; j<bsize.y; j++ ) {
+
4795 for( size_t i = 0; i<bsize.x; i++ ) {
+
4796 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
+
4797 }
+
4798 }
+
4799 }
+
4800 }else if( format==RT_FORMAT_UNSIGNED_INT ){
+
4801 uint* data = (uint*)ptr;
+
4802 for( size_t k = 0; k<bsize.z; k++ ) {
+
4803 for( size_t j = 0; j<bsize.y; j++ ) {
+
4804 for( size_t i = 0; i<bsize.x; i++ ) {
+
4805 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
+
4806 }
+
4807 }
+
4808 }
+
4809 }else if( format==RT_FORMAT_BYTE ){
+
4810 bool* data = (bool*)ptr;
+
4811 for( size_t k = 0; k<bsize.z; k++ ) {
+
4812 for( size_t j = 0; j<bsize.y; j++ ) {
+
4813 for( size_t i = 0; i<bsize.x; i++ ) {
+
4814 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
+
4815 }
+
4816 }
+
4817 }
+
4818 }else{
+
4819 std::cerr<< "ERROR (RadiationModel::initializeBuffer3D): unsupported buffer format." << std::endl;
+
4820
+
4821 }
+
4822
+
4823 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
4824
-
4825 float Gtheta = 0;
-
4826 float total_area = 0;
-
4827 for( std::size_t u=0; u<primitiveID.size(); u++ ){
-
4828
-
4829 uint UUID = context_UUIDs.at(primitiveID.at(u));
-
4830
-
4831 vec3 normal = context->getPrimitiveNormal(UUID);
-
4832 float area = context->getPrimitiveArea(UUID);
-
4833
-
4834 Gtheta += fabsf(normal*dir)*area;
-
4835
-
4836 total_area += area;
-
4837
-
4838 }
-
4839
-
4840 return Gtheta/total_area;
+
4825
+
4826}
+
4827
+
+ +
4829
+
4830 vec3 dir = view_direction;
+
4831 dir.normalize();
+
4832
+
4833 float Gtheta = 0;
+
4834 float total_area = 0;
+
4835 for( std::size_t u=0; u<primitiveID.size(); u++ ){
+
4836
+
4837 uint UUID = context_UUIDs.at(primitiveID.at(u));
+
4838
+
4839 vec3 normal = context->getPrimitiveNormal(UUID);
+
4840 float area = context->getPrimitiveArea(UUID);
4841
-
4842}
-
+
4842 Gtheta += fabsf(normal*dir)*area;
4843
-
4844void RadiationModel::setCameraCalibration(CameraCalibration *CameraCalibration){
-
4845 cameracalibration = CameraCalibration;
-
4846 calibration_flag = true;
-
4847}
-
4848
-
-
4849void RadiationModel::updateCameraResponse(const std::string &orginalcameralabel, const std::vector<std::string> &sourcelabels_raw,
-
4850 const std::vector<std::string>& cameraresponselabels, vec2 &wavelengthrange,
-
4851 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark) {
-
4852
-
4853 std::vector<std::string> objectlabels;
-
4854 vec2 wavelengthrange_c = wavelengthrange;
-
4855 cameracalibration->preprocessSpectra(sourcelabels_raw, cameraresponselabels, objectlabels, wavelengthrange_c);
+
4844 total_area += area;
+
4845
+
4846 }
+
4847
+
4848 return Gtheta/total_area;
+
4849
+
4850}
+
+
4851
+
4852void RadiationModel::setCameraCalibration(CameraCalibration *CameraCalibration){
+
4853 cameracalibration = CameraCalibration;
+
4854 calibration_flag = true;
+
4855}
4856
-
4857 RadiationCamera calibratecamera = cameras.at(orginalcameralabel);
-
4858 CameraProperties cameraproperties;
-
4859 cameraproperties.HFOV = calibratecamera.HFOV_degrees;
-
4860 cameraproperties.camera_resolution = calibratecamera.resolution;
-
4861 cameraproperties.focal_plane_distance = calibratecamera.focal_length;
-
4862 cameraproperties.lens_diameter = calibratecamera.lens_diameter;
-
4863 cameraproperties.FOV_aspect_ratio = calibratecamera.FOV_aspect_ratio;
+
+
4857void RadiationModel::updateCameraResponse(const std::string &orginalcameralabel, const std::vector<std::string> &sourcelabels_raw,
+
4858 const std::vector<std::string>& cameraresponselabels, vec2 &wavelengthrange,
+
4859 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark) {
+
4860
+
4861 std::vector<std::string> objectlabels;
+
4862 vec2 wavelengthrange_c = wavelengthrange;
+
4863 cameracalibration->preprocessSpectra(sourcelabels_raw, cameraresponselabels, objectlabels, wavelengthrange_c);
4864
-
4865 std::vector<uint> UUIDs_target = cameracalibration->getColorBoardUUIDs();
-
4866 std::string cameralabel = "calibration";
-
4867 std::map<uint,std::vector<vec2>> simulatedcolorboardspectra;
-
4868 for (uint UUID:UUIDs_target){
-
4869 simulatedcolorboardspectra.emplace(UUID, NULL);
-
4870 }
-
4871
-
4872 for (uint ID = 0; ID<radiation_sources.size();ID++) {
- -
4874 }
-
4875
-
4876 std::vector<float> wavelengths;
-
4877 context->getGlobalData("wavelengths", wavelengths);
-
4878 int numberwavelengths= wavelengths.size();
+
4865 RadiationCamera calibratecamera = cameras.at(orginalcameralabel);
+
4866 CameraProperties cameraproperties;
+
4867 cameraproperties.HFOV = calibratecamera.HFOV_degrees;
+
4868 cameraproperties.camera_resolution = calibratecamera.resolution;
+
4869 cameraproperties.focal_plane_distance = calibratecamera.focal_length;
+
4870 cameraproperties.lens_diameter = calibratecamera.lens_diameter;
+
4871 cameraproperties.FOV_aspect_ratio = calibratecamera.FOV_aspect_ratio;
+
4872
+
4873 std::vector<uint> UUIDs_target = cameracalibration->getColorBoardUUIDs();
+
4874 std::string cameralabel = "calibration";
+
4875 std::map<uint,std::vector<vec2>> simulatedcolorboardspectra;
+
4876 for (uint UUID:UUIDs_target){
+
4877 simulatedcolorboardspectra.emplace(UUID, NULL);
+
4878 }
4879
-
4880 for (int iw=0; iw < numberwavelengths; iw++) {
-
4881 std::string wavelengthlabel = std::to_string(wavelengths.at(iw));
-
4882
-
4883 std::vector<std::string> sourcelabels;
-
4884 for (std::string sourcelabel_raw:sourcelabels_raw){
-
4885 std::vector<vec2> icalsource;
-
4886 icalsource.push_back(cameracalibration->processedspectra.at("source").at(sourcelabel_raw).at(iw));
-
4887 icalsource.push_back(cameracalibration->processedspectra.at("source").at(sourcelabel_raw).at(iw));
-
4888 icalsource.at(1).x+=1;
-
4889 std::string sourcelable = "Cal_source_"+sourcelabel_raw;
-
4890 sourcelabels.push_back(sourcelable);
-
4891 context->setGlobalData(sourcelable.c_str(),HELIOS_TYPE_VEC2,2,&icalsource[0]);
-
4892 }
-
4893
-
4894 std::vector<vec2> icalcamera(2);
-
4895 icalcamera.at(0).y=1;
-
4896 icalcamera.at(1).y=1;
-
4897 icalcamera.at(0).x=wavelengths.at(iw);
-
4898 icalcamera.at(1).x=wavelengths.at(iw)+1;
-
4899 std::string camlable = "Cal_cameraresponse";
-
4900 context->setGlobalData(camlable.c_str(),HELIOS_TYPE_VEC2,2,&icalcamera[0]);
+
4880 for (uint ID = 0; ID<radiation_sources.size();ID++) {
+ +
4882 }
+
4883
+
4884 std::vector<float> wavelengths;
+
4885 context->getGlobalData("wavelengths", wavelengths);
+
4886 int numberwavelengths= wavelengths.size();
+
4887
+
4888 for (int iw=0; iw < numberwavelengths; iw++) {
+
4889 std::string wavelengthlabel = std::to_string(wavelengths.at(iw));
+
4890
+
4891 std::vector<std::string> sourcelabels;
+
4892 for (std::string sourcelabel_raw:sourcelabels_raw){
+
4893 std::vector<vec2> icalsource;
+
4894 icalsource.push_back(cameracalibration->processedspectra.at("source").at(sourcelabel_raw).at(iw));
+
4895 icalsource.push_back(cameracalibration->processedspectra.at("source").at(sourcelabel_raw).at(iw));
+
4896 icalsource.at(1).x+=1;
+
4897 std::string sourcelable = "Cal_source_"+sourcelabel_raw;
+
4898 sourcelabels.push_back(sourcelable);
+
4899 context->setGlobalData(sourcelable.c_str(),HELIOS_TYPE_VEC2,2,&icalsource[0]);
+
4900 }
4901
-
4902 for (auto objectpair : cameracalibration->processedspectra.at("object")){
-
4903 std::vector<vec2> spectrum_obj;
-
4904 spectrum_obj.push_back(objectpair.second.at(iw));
-
4905 spectrum_obj.push_back(objectpair.second.at(iw));
-
4906 spectrum_obj.at(1).x += 1;
-
4907 context->setGlobalData(objectpair.first.c_str(), HELIOS_TYPE_VEC2, 2, &spectrum_obj[0]);
-
4908 }
+
4902 std::vector<vec2> icalcamera(2);
+
4903 icalcamera.at(0).y=1;
+
4904 icalcamera.at(1).y=1;
+
4905 icalcamera.at(0).x=wavelengths.at(iw);
+
4906 icalcamera.at(1).x=wavelengths.at(iw)+1;
+
4907 std::string camlable = "Cal_cameraresponse";
+
4908 context->setGlobalData(camlable.c_str(),HELIOS_TYPE_VEC2,2,&icalcamera[0]);
4909
-
4910 RadiationModel::addRadiationBand(wavelengthlabel, std::stof(wavelengthlabel), std::stof(wavelengthlabel) + 1);
-
4911 RadiationModel::disableEmission(wavelengthlabel);
-
4912
-
4913 uint ID = 0;
-
4914 for (std::string sourcelabel_raw:sourcelabels_raw) {
-
4915 RadiationModel::setSourceSpectrum(ID, sourcelabels.at(ID).c_str());
-
4916 RadiationModel::setSourceFlux(ID, wavelengthlabel, 1);
-
4917 ID ++;
-
4918 }
-
4919 RadiationModel::setScatteringDepth(wavelengthlabel, 1);
-
4920 RadiationModel::setDiffuseRadiationFlux(wavelengthlabel, 0);
-
4921 RadiationModel::setDiffuseRadiationExtinctionCoeff(wavelengthlabel, 0.f, make_vec3(-0.5, 0.5, 1));
-
4922
-
4923 RadiationModel::addRadiationCamera(cameralabel, {wavelengthlabel}, calibratecamera.position, calibratecamera.lookat, cameraproperties, 10);
-
4924 RadiationModel::setCameraSpectralResponse(cameralabel, wavelengthlabel, camlable);
- -
4926 RadiationModel::runBand({wavelengthlabel});
-
4927
-
4928 std::vector<float> camera_data;
-
4929 std::string global_data_label = "camera_" + cameralabel + "_" + wavelengthlabel;
-
4930 context->getGlobalData(global_data_label.c_str(), camera_data);
-
4931
-
4932 std::vector<uint> pixel_labels;
-
4933 std::string global_data_label_UUID = "camera_" + cameralabel + "_pixel_UUID";
-
4934 context->getGlobalData(global_data_label_UUID.c_str(), pixel_labels);
+
4910 for (auto objectpair : cameracalibration->processedspectra.at("object")){
+
4911 std::vector<vec2> spectrum_obj;
+
4912 spectrum_obj.push_back(objectpair.second.at(iw));
+
4913 spectrum_obj.push_back(objectpair.second.at(iw));
+
4914 spectrum_obj.at(1).x += 1;
+
4915 context->setGlobalData(objectpair.first.c_str(), HELIOS_TYPE_VEC2, 2, &spectrum_obj[0]);
+
4916 }
+
4917
+
4918 RadiationModel::addRadiationBand(wavelengthlabel, std::stof(wavelengthlabel), std::stof(wavelengthlabel) + 1);
+
4919 RadiationModel::disableEmission(wavelengthlabel);
+
4920
+
4921 uint ID = 0;
+
4922 for (std::string sourcelabel_raw:sourcelabels_raw) {
+
4923 RadiationModel::setSourceSpectrum(ID, sourcelabels.at(ID).c_str());
+
4924 RadiationModel::setSourceFlux(ID, wavelengthlabel, 1);
+
4925 ID ++;
+
4926 }
+
4927 RadiationModel::setScatteringDepth(wavelengthlabel, 1);
+
4928 RadiationModel::setDiffuseRadiationFlux(wavelengthlabel, 0);
+
4929 RadiationModel::setDiffuseRadiationExtinctionCoeff(wavelengthlabel, 0.f, make_vec3(-0.5, 0.5, 1));
+
4930
+
4931 RadiationModel::addRadiationCamera(cameralabel, {wavelengthlabel}, calibratecamera.position, calibratecamera.lookat, cameraproperties, 10);
+
4932 RadiationModel::setCameraSpectralResponse(cameralabel, wavelengthlabel, camlable);
+ +
4934 RadiationModel::runBand({wavelengthlabel});
4935
-
4936 for (uint j = 0; j < calibratecamera.resolution.y; j++) {
-
4937 for (uint i = 0; i < calibratecamera.resolution.x; i++) {
-
4938 float icdata = camera_data.at(j * calibratecamera.resolution.x + i);
+
4936 std::vector<float> camera_data;
+
4937 std::string global_data_label = "camera_" + cameralabel + "_" + wavelengthlabel;
+
4938 context->getGlobalData(global_data_label.c_str(), camera_data);
4939
-
4940 uint UUID = pixel_labels.at(j * calibratecamera.resolution.x + i)-1;
-
4941 if (find(UUIDs_target.begin(), UUIDs_target.end(), UUID) != UUIDs_target.end()){
-
4942 if ( simulatedcolorboardspectra.at(UUID).empty()){
-
4943 simulatedcolorboardspectra.at(UUID).push_back(make_vec2(wavelengths.at(iw), icdata / float(numberwavelengths)));
-
4944 }
-
4945 else if (simulatedcolorboardspectra.at(UUID).back().x == wavelengths.at(iw)){
-
4946 simulatedcolorboardspectra.at(UUID).back().y += icdata / float(numberwavelengths);
-
4947 }
-
4948 else if(simulatedcolorboardspectra.at(UUID).back().x !=wavelengths.at(iw)){
-
4949 simulatedcolorboardspectra.at(UUID).push_back(make_vec2(wavelengths.at(iw), icdata / float(numberwavelengths)));
-
4950 }
-
4951 }
-
4952 }
-
4953 }
-
4954 }
-
4955 // Update camera response spectra
-
4956 cameracalibration->updateCameraResponseSpectra(cameraresponselabels, calibratedmark ,simulatedcolorboardspectra, truevalues);
-
4957 // Reset color board spectra
-
4958 std::vector<uint> UUIDs_colorbd = cameracalibration->getColorBoardUUIDs();
-
4959 for (uint UUID:UUIDs_colorbd){
-
4960 std::string colorboardspectra;
-
4961 context->getPrimitiveData(UUID, "reflectivity_spectrum", colorboardspectra);
-
4962 context->setPrimitiveData(UUID, "reflectivity_spectrum", colorboardspectra+"_raw");
-
4963 }
-
4964}
-
-
4965
-
-
4966void RadiationModel::runRadiationImaging(const std::string& cameralabel, const std::vector<std::string>& sourcelabels, const std::vector<std::string>& bandlabels,
-
4967 const std::vector<std::string>& cameraresponselabels, helios::vec2 wavelengthrange,
-
4968 float fluxscale, float diffusefactor, uint scatteringdepth){
-
4969
-
4970 float sources_fluxsum = 0;
-
4971 std::vector<float> sources_fluxes;
-
4972 for (uint ID = 0; ID < sourcelabels.size(); ID++){
-
4973 std::vector<vec2> Source_spectrum = loadSpectralData(sourcelabels.at(ID).c_str());
-
4974 sources_fluxes.push_back(RadiationModel::integrateSpectrum(Source_spectrum, wavelengthrange.x, wavelengthrange.y));
-
4975 RadiationModel::setSourceSpectrum(ID, sourcelabels.at(ID).c_str());
-
4976 RadiationModel::setSourceSpectrumIntegral(ID, sources_fluxes.at(ID));
-
4977 sources_fluxsum += sources_fluxes.at(ID);
-
4978 }
-
4979
-
4980 RadiationModel::addRadiationBand(bandlabels.at(0), wavelengthrange.x, wavelengthrange.y);
-
4981 RadiationModel::disableEmission(bandlabels.at(0));
-
4982 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
-
4983 RadiationModel::setSourceFlux(ID, bandlabels.at(0), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
-
4984 }
-
4985 RadiationModel::setScatteringDepth(bandlabels.at(0), scatteringdepth);
-
4986 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(0), diffusefactor * sources_fluxsum );
-
4987 RadiationModel::setDiffuseRadiationExtinctionCoeff(bandlabels.at(0), 1.f, make_vec3(-0.5, 0.5, 1) );
-
4988
-
4989 if (bandlabels.size()>1){
-
4990 for (int iband=1;iband<bandlabels.size();iband++){
-
4991 RadiationModel::copyRadiationBand(bandlabels.at(iband-1), bandlabels.at(iband), wavelengthrange.x, wavelengthrange.y);
-
4992 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
-
4993 RadiationModel::setSourceFlux(ID, bandlabels.at(iband), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
-
4994 }
-
4995 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(iband), diffusefactor * sources_fluxsum );
-
4996 }
-
4997 }
-
4998
-
4999 for (int iband=0;iband<bandlabels.size();iband++){
-
5000 RadiationModel::setCameraSpectralResponse(cameralabel, bandlabels.at(iband), cameraresponselabels.at(iband));
-
5001 }
-
5002
- -
5004 RadiationModel::runBand(bandlabels);
-
5005}
+
4940 std::vector<uint> pixel_labels;
+
4941 std::string global_data_label_UUID = "camera_" + cameralabel + "_pixel_UUID";
+
4942 context->getGlobalData(global_data_label_UUID.c_str(), pixel_labels);
+
4943
+
4944 for (uint j = 0; j < calibratecamera.resolution.y; j++) {
+
4945 for (uint i = 0; i < calibratecamera.resolution.x; i++) {
+
4946 float icdata = camera_data.at(j * calibratecamera.resolution.x + i);
+
4947
+
4948 uint UUID = pixel_labels.at(j * calibratecamera.resolution.x + i)-1;
+
4949 if (find(UUIDs_target.begin(), UUIDs_target.end(), UUID) != UUIDs_target.end()){
+
4950 if ( simulatedcolorboardspectra.at(UUID).empty()){
+
4951 simulatedcolorboardspectra.at(UUID).push_back(make_vec2(wavelengths.at(iw), icdata / float(numberwavelengths)));
+
4952 }
+
4953 else if (simulatedcolorboardspectra.at(UUID).back().x == wavelengths.at(iw)){
+
4954 simulatedcolorboardspectra.at(UUID).back().y += icdata / float(numberwavelengths);
+
4955 }
+
4956 else if(simulatedcolorboardspectra.at(UUID).back().x !=wavelengths.at(iw)){
+
4957 simulatedcolorboardspectra.at(UUID).push_back(make_vec2(wavelengths.at(iw), icdata / float(numberwavelengths)));
+
4958 }
+
4959 }
+
4960 }
+
4961 }
+
4962 }
+
4963 // Update camera response spectra
+
4964 cameracalibration->updateCameraResponseSpectra(cameraresponselabels, calibratedmark ,simulatedcolorboardspectra, truevalues);
+
4965 // Reset color board spectra
+
4966 std::vector<uint> UUIDs_colorbd = cameracalibration->getColorBoardUUIDs();
+
4967 for (uint UUID:UUIDs_colorbd){
+
4968 std::string colorboardspectra;
+
4969 context->getPrimitiveData(UUID, "reflectivity_spectrum", colorboardspectra);
+
4970 context->setPrimitiveData(UUID, "reflectivity_spectrum", colorboardspectra+"_raw");
+
4971 }
+
4972}
+
4973
+
+
4974void RadiationModel::runRadiationImaging(const std::string& cameralabel, const std::vector<std::string>& sourcelabels, const std::vector<std::string>& bandlabels,
+
4975 const std::vector<std::string>& cameraresponselabels, helios::vec2 wavelengthrange,
+
4976 float fluxscale, float diffusefactor, uint scatteringdepth){
+
4977
+
4978 float sources_fluxsum = 0;
+
4979 std::vector<float> sources_fluxes;
+
4980 for (uint ID = 0; ID < sourcelabels.size(); ID++){
+
4981 std::vector<vec2> Source_spectrum = loadSpectralData(sourcelabels.at(ID).c_str());
+
4982 sources_fluxes.push_back(RadiationModel::integrateSpectrum(Source_spectrum, wavelengthrange.x, wavelengthrange.y));
+
4983 RadiationModel::setSourceSpectrum(ID, sourcelabels.at(ID).c_str());
+
4984 RadiationModel::setSourceSpectrumIntegral(ID, sources_fluxes.at(ID));
+
4985 sources_fluxsum += sources_fluxes.at(ID);
+
4986 }
+
4987
+
4988 RadiationModel::addRadiationBand(bandlabels.at(0), wavelengthrange.x, wavelengthrange.y);
+
4989 RadiationModel::disableEmission(bandlabels.at(0));
+
4990 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
+
4991 RadiationModel::setSourceFlux(ID, bandlabels.at(0), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
+
4992 }
+
4993 RadiationModel::setScatteringDepth(bandlabels.at(0), scatteringdepth);
+
4994 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(0), diffusefactor * sources_fluxsum );
+
4995 RadiationModel::setDiffuseRadiationExtinctionCoeff(bandlabels.at(0), 1.f, make_vec3(-0.5, 0.5, 1) );
+
4996
+
4997 if (bandlabels.size()>1){
+
4998 for (int iband=1;iband<bandlabels.size();iband++){
+
4999 RadiationModel::copyRadiationBand(bandlabels.at(iband-1), bandlabels.at(iband), wavelengthrange.x, wavelengthrange.y);
+
5000 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
+
5001 RadiationModel::setSourceFlux(ID, bandlabels.at(iband), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
+
5002 }
+
5003 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(iband), diffusefactor * sources_fluxsum );
+
5004 }
+
5005 }
5006
-
-
5007void RadiationModel::runRadiationImaging(const std::vector<std::string>& cameralabels, const std::vector<std::string>& sourcelabels, const std::vector<std::string>& bandlabels,
-
5008 const std::vector<std::string>& cameraresponselabels, helios::vec2 wavelengthrange,
-
5009 float fluxscale, float diffusefactor, uint scatteringdepth){
+
5007 for (int iband=0;iband<bandlabels.size();iband++){
+
5008 RadiationModel::setCameraSpectralResponse(cameralabel, bandlabels.at(iband), cameraresponselabels.at(iband));
+
5009 }
5010
-
5011 float sources_fluxsum = 0;
-
5012 std::vector<float> sources_fluxes;
-
5013 for (uint ID = 0; ID < sourcelabels.size(); ID++){
-
5014 std::vector<vec2> Source_spectrum = loadSpectralData(sourcelabels.at(ID).c_str());
-
5015 sources_fluxes.push_back(RadiationModel::integrateSpectrum(Source_spectrum, wavelengthrange.x, wavelengthrange.y));
-
5016 RadiationModel::setSourceSpectrum(ID, sourcelabels.at(ID).c_str());
-
5017 RadiationModel::setSourceSpectrumIntegral(ID, sources_fluxes.at(ID));
-
5018 sources_fluxsum += sources_fluxes.at(ID);
-
5019 }
-
5020
-
5021 RadiationModel::addRadiationBand(bandlabels.at(0), wavelengthrange.x, wavelengthrange.y);
-
5022 RadiationModel::disableEmission(bandlabels.at(0));
-
5023 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
-
5024 RadiationModel::setSourceFlux(ID, bandlabels.at(0), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
-
5025 }
-
5026 RadiationModel::setScatteringDepth(bandlabels.at(0), scatteringdepth);
-
5027 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(0), diffusefactor * sources_fluxsum );
-
5028 RadiationModel::setDiffuseRadiationExtinctionCoeff(bandlabels.at(0), 1.f, make_vec3(-0.5, 0.5, 1) );
-
5029
-
5030 if (bandlabels.size()>1){
-
5031 for (int iband=1;iband<bandlabels.size();iband++){
-
5032 RadiationModel::copyRadiationBand(bandlabels.at(iband-1), bandlabels.at(iband), wavelengthrange.x, wavelengthrange.y);
-
5033 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
-
5034 RadiationModel::setSourceFlux(ID, bandlabels.at(iband), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
-
5035 }
-
5036 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(iband), diffusefactor * sources_fluxsum );
-
5037 }
-
5038 }
-
5039
-
5040 for (int ic=0;ic<cameralabels.size();ic++){
-
5041 for (int iband=0;iband<bandlabels.size();iband++){
-
5042 RadiationModel::setCameraSpectralResponse(cameralabels.at(ic), bandlabels.at(iband), cameraresponselabels.at(iband));
-
5043 }
-
5044 }
-
5045
-
5046
- -
5048 RadiationModel::runBand(bandlabels);
-
5049}
+ +
5012 RadiationModel::runBand(bandlabels);
+
5013}
-
5050
-
-
5051float RadiationModel::getCameraResponseScale(const std::string &orginalcameralabel, const std::vector<std::string>& cameraresponselabels,
-
5052 const std::vector<std::string>& bandlabels, const std::vector<std::string> &sourcelabels,
-
5053 vec2 &wavelengthrange, const std::vector<std::vector<float>> &truevalues){
+
5014
+
+
5015void RadiationModel::runRadiationImaging(const std::vector<std::string>& cameralabels, const std::vector<std::string>& sourcelabels, const std::vector<std::string>& bandlabels,
+
5016 const std::vector<std::string>& cameraresponselabels, helios::vec2 wavelengthrange,
+
5017 float fluxscale, float diffusefactor, uint scatteringdepth){
+
5018
+
5019 float sources_fluxsum = 0;
+
5020 std::vector<float> sources_fluxes;
+
5021 for (uint ID = 0; ID < sourcelabels.size(); ID++){
+
5022 std::vector<vec2> Source_spectrum = loadSpectralData(sourcelabels.at(ID).c_str());
+
5023 sources_fluxes.push_back(RadiationModel::integrateSpectrum(Source_spectrum, wavelengthrange.x, wavelengthrange.y));
+
5024 RadiationModel::setSourceSpectrum(ID, sourcelabels.at(ID).c_str());
+
5025 RadiationModel::setSourceSpectrumIntegral(ID, sources_fluxes.at(ID));
+
5026 sources_fluxsum += sources_fluxes.at(ID);
+
5027 }
+
5028
+
5029 RadiationModel::addRadiationBand(bandlabels.at(0), wavelengthrange.x, wavelengthrange.y);
+
5030 RadiationModel::disableEmission(bandlabels.at(0));
+
5031 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
+
5032 RadiationModel::setSourceFlux(ID, bandlabels.at(0), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
+
5033 }
+
5034 RadiationModel::setScatteringDepth(bandlabels.at(0), scatteringdepth);
+
5035 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(0), diffusefactor * sources_fluxsum );
+
5036 RadiationModel::setDiffuseRadiationExtinctionCoeff(bandlabels.at(0), 1.f, make_vec3(-0.5, 0.5, 1) );
+
5037
+
5038 if (bandlabels.size()>1){
+
5039 for (int iband=1;iband<bandlabels.size();iband++){
+
5040 RadiationModel::copyRadiationBand(bandlabels.at(iband-1), bandlabels.at(iband), wavelengthrange.x, wavelengthrange.y);
+
5041 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
+
5042 RadiationModel::setSourceFlux(ID, bandlabels.at(iband), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
+
5043 }
+
5044 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(iband), diffusefactor * sources_fluxsum );
+
5045 }
+
5046 }
+
5047
+
5048 for (int ic=0;ic<cameralabels.size();ic++){
+
5049 for (int iband=0;iband<bandlabels.size();iband++){
+
5050 RadiationModel::setCameraSpectralResponse(cameralabels.at(ic), bandlabels.at(iband), cameraresponselabels.at(iband));
+
5051 }
+
5052 }
+
5053
5054
-
5055
-
5056 RadiationCamera calibratecamera = cameras.at(orginalcameralabel);
-
5057 CameraProperties cameraproperties;
-
5058 cameraproperties.HFOV = calibratecamera.HFOV_degrees;
-
5059 cameraproperties.camera_resolution = calibratecamera.resolution;
-
5060 cameraproperties.focal_plane_distance = calibratecamera.focal_length;
-
5061 cameraproperties.lens_diameter = calibratecamera.lens_diameter;
-
5062 cameraproperties.FOV_aspect_ratio = calibratecamera.FOV_aspect_ratio;
-
5063
-
5064 std::string cameralabel = orginalcameralabel+"Scale";
-
5065 RadiationModel::addRadiationCamera(cameralabel, bandlabels, calibratecamera.position, calibratecamera.lookat, cameraproperties,20);
-
5066 RadiationModel::runRadiationImaging(cameralabel, sourcelabels, bandlabels, cameraresponselabels, wavelengthrange, 1, 0);
-
5067
-
5068 // Get camera spectral response scale based on comparing true values and calibrated image
-
5069 float camerascale = cameracalibration->getCameraResponseScale(cameralabel, cameraproperties.camera_resolution, bandlabels, truevalues);
-
5070 return camerascale;
-
5071}
+ +
5056 RadiationModel::runBand(bandlabels);
+
5057}
-
5072
-
5073
-
-
5074void RadiationModel::writePrimitiveDataLabelMap(const std::string &cameralabel, const std::string &primitive_data_label, const std::string &imagefile_base, const std::string &image_path, int frame, float padvalue){
+
5058
+
+
5059float RadiationModel::getCameraResponseScale(const std::string &orginalcameralabel, const std::vector<std::string>& cameraresponselabels,
+
5060 const std::vector<std::string>& bandlabels, const std::vector<std::string> &sourcelabels,
+
5061 vec2 &wavelengthrange, const std::vector<std::vector<float>> &truevalues){
+
5062
+
5063
+
5064 RadiationCamera calibratecamera = cameras.at(orginalcameralabel);
+
5065 CameraProperties cameraproperties;
+
5066 cameraproperties.HFOV = calibratecamera.HFOV_degrees;
+
5067 cameraproperties.camera_resolution = calibratecamera.resolution;
+
5068 cameraproperties.focal_plane_distance = calibratecamera.focal_length;
+
5069 cameraproperties.lens_diameter = calibratecamera.lens_diameter;
+
5070 cameraproperties.FOV_aspect_ratio = calibratecamera.FOV_aspect_ratio;
+
5071
+
5072 std::string cameralabel = orginalcameralabel+"Scale";
+
5073 RadiationModel::addRadiationCamera(cameralabel, bandlabels, calibratecamera.position, calibratecamera.lookat, cameraproperties,20);
+
5074 RadiationModel::runRadiationImaging(cameralabel, sourcelabels, bandlabels, cameraresponselabels, wavelengthrange, 1, 0);
5075
-
5076 if( cameras.find(cameralabel)==cameras.end() ){
-
5077 helios_runtime_error( "ERROR (RadiationModel::writePrimitiveDataLabelMap): Camera '" + cameralabel + "' does not exist." );
-
5078 }
-
5079
-
5080 //Get image UUID labels
-
5081 std::vector<uint> camera_UUIDs;
-
5082 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
-
5083 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
-
5084 helios_runtime_error( "ERROR (RadiationModel::writePrimitiveDataLabelMap): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
-
5085 }
-
5086 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
-
5087 std::vector<uint> pixel_UUIDs = camera_UUIDs;
-
5088 int2 camera_resolution = cameras.at(cameralabel).resolution;
-
5089
-
5090 std::string frame_str;
-
5091 if( frame>=0 ) {
-
5092 frame_str = std::to_string(frame);
+
5076 // Get camera spectral response scale based on comparing true values and calibrated image
+
5077 float camerascale = cameracalibration->getCameraResponseScale(cameralabel, cameraproperties.camera_resolution, bandlabels, truevalues);
+
5078 return camerascale;
+
5079}
+
+
5080
+
5081
+
+
5082void RadiationModel::writePrimitiveDataLabelMap(const std::string &cameralabel, const std::string &primitive_data_label, const std::string &imagefile_base, const std::string &image_path, int frame, float padvalue){
+
5083
+
5084 if( cameras.find(cameralabel)==cameras.end() ){
+
5085 helios_runtime_error( "ERROR (RadiationModel::writePrimitiveDataLabelMap): Camera '" + cameralabel + "' does not exist." );
+
5086 }
+
5087
+
5088 //Get image UUID labels
+
5089 std::vector<uint> camera_UUIDs;
+
5090 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
+
5091 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
+
5092 helios_runtime_error( "ERROR (RadiationModel::writePrimitiveDataLabelMap): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
5093 }
-
5094
-
5095 std::ostringstream outfile;
-
5096
-
5097 if( !validateOutputPath(outfile) ){
-
5098 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission.");
-
5099 }
-
5100
-
5101 if( frame>=0 ) {
-
5102 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
-
5103 }else{
-
5104 outfile << cameralabel << "_" << imagefile_base << ".txt";
-
5105 }
-
5106
-
5107 //Output label image in ".txt" format
-
5108 std::ofstream pixel_data(outfile.str());
+
5094 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
+
5095 std::vector<uint> pixel_UUIDs = camera_UUIDs;
+
5096 int2 camera_resolution = cameras.at(cameralabel).resolution;
+
5097
+
5098 std::string frame_str;
+
5099 if( frame>=0 ) {
+
5100 frame_str = std::to_string(frame);
+
5101 }
+
5102
+
5103 std::string output_path = image_path;
+
5104 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
5105 helios_runtime_error("ERROR (RadiationModel::writePrimitiveDataLabelMap): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
5106 }else if( !getFileName(output_path).empty() ){
+
5107 helios_runtime_error("ERROR(RadiationModel::writePrimitiveDataLabelMap): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
5108 }
5109
-
5110 if( !pixel_data.is_open() ){
-
5111 helios_runtime_error( "ERROR (RadiationModel::writePrimitiveDataLabelMap): Could not open file '" + outfile.str() + "' for writing." );
-
5112 }
-
5113
-
5114 bool empty_flag = true;
-
5115 for (uint j = 0; j < camera_resolution.y; j++) {
-
5116 for (uint i = 0; i < camera_resolution.x; i++) {
-
5117 uint ii = camera_resolution.x - i -1;
-
5118 uint UUID =pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
-
5119 if (context->doesPrimitiveExist(UUID) && context->doesPrimitiveDataExist(UUID,primitive_data_label.c_str())){
-
5120 HeliosDataType datatype = context->getPrimitiveDataType(UUID,primitive_data_label.c_str());
-
5121 if( datatype == HELIOS_TYPE_FLOAT ){
-
5122 float labeldata;
-
5123 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
-
5124 pixel_data << labeldata << " ";
-
5125 empty_flag = false;
-
5126 }
-
5127 else if (datatype == HELIOS_TYPE_UINT){
-
5128 uint labeldata;
-
5129 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
-
5130 pixel_data << labeldata << " ";
-
5131 empty_flag = false;
-
5132 }
-
5133 else if (datatype == HELIOS_TYPE_INT){
-
5134 int labeldata;
+
5110 std::ostringstream outfile;
+
5111 outfile << output_path;
+
5112
+
5113 if( frame>=0 ) {
+
5114 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
+
5115 }else{
+
5116 outfile << cameralabel << "_" << imagefile_base << ".txt";
+
5117 }
+
5118
+
5119 //Output label image in ".txt" format
+
5120 std::ofstream pixel_data(outfile.str());
+
5121
+
5122 if( !pixel_data.is_open() ){
+
5123 helios_runtime_error( "ERROR (RadiationModel::writePrimitiveDataLabelMap): Could not open file '" + outfile.str() + "' for writing." );
+
5124 }
+
5125
+
5126 bool empty_flag = true;
+
5127 for (uint j = 0; j < camera_resolution.y; j++) {
+
5128 for (uint i = 0; i < camera_resolution.x; i++) {
+
5129 uint ii = camera_resolution.x - i -1;
+
5130 uint UUID =pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
+
5131 if (context->doesPrimitiveExist(UUID) && context->doesPrimitiveDataExist(UUID,primitive_data_label.c_str())){
+
5132 HeliosDataType datatype = context->getPrimitiveDataType(UUID,primitive_data_label.c_str());
+
5133 if( datatype == HELIOS_TYPE_FLOAT ){
+
5134 float labeldata;
5135 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
5136 pixel_data << labeldata << " ";
5137 empty_flag = false;
5138 }
-
5139 else if (datatype == HELIOS_TYPE_DOUBLE){
-
5140 double labeldata;
+
5139 else if (datatype == HELIOS_TYPE_UINT){
+
5140 uint labeldata;
5141 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
5142 pixel_data << labeldata << " ";
5143 empty_flag = false;
-
5144 }else{
-
5145 pixel_data << padvalue << " ";
-
5146 }
-
5147 }else{
-
5148 pixel_data << padvalue << " ";
-
5149 }
-
5150 }
-
5151 pixel_data << "\n";
-
5152 }
-
5153 pixel_data.close();
-
5154
-
5155 if( empty_flag ){
-
5156 std::cerr << "WARNING (RadiationModel::writePrimitiveDataLabelMap): No primitive data of " << primitive_data_label << " found in camera image. Primitive data map contains only padded values." << std::endl;
-
5157 }
-
5158
-
5159}
-
-
5160
-
-
5161void RadiationModel::writeObjectDataLabelMap(const std::string &cameralabel, const std::string &object_data_label, const std::string &imagefile_base, const std::string &image_path, int frame, float padvalue){
-
5162
-
5163 if( cameras.find(cameralabel)==cameras.end() ){
-
5164 helios_runtime_error( "ERROR (RadiationModel::writeObjectDataLabelMap): Camera '" + cameralabel + "' does not exist." );
-
5165 }
+
5144 }
+
5145 else if (datatype == HELIOS_TYPE_INT){
+
5146 int labeldata;
+
5147 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
+
5148 pixel_data << labeldata << " ";
+
5149 empty_flag = false;
+
5150 }
+
5151 else if (datatype == HELIOS_TYPE_DOUBLE){
+
5152 double labeldata;
+
5153 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
+
5154 pixel_data << labeldata << " ";
+
5155 empty_flag = false;
+
5156 }else{
+
5157 pixel_data << padvalue << " ";
+
5158 }
+
5159 }else{
+
5160 pixel_data << padvalue << " ";
+
5161 }
+
5162 }
+
5163 pixel_data << "\n";
+
5164 }
+
5165 pixel_data.close();
5166
-
5167 //Get image UUID labels
-
5168 std::vector<uint> camera_UUIDs;
-
5169 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
-
5170 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
-
5171 helios_runtime_error( "ERROR (RadiationModel::writeObjectDataLabelMap): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
-
5172 }
-
5173 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
-
5174 std::vector<uint> pixel_UUIDs = camera_UUIDs;
-
5175 int2 camera_resolution = cameras.at(cameralabel).resolution;
-
5176
-
5177 std::string frame_str;
-
5178 if( frame>=0 ) {
-
5179 frame_str = std::to_string(frame);
-
5180 }
-
5181
-
5182 std::ostringstream outfile;
-
5183
-
5184 if( !validateOutputPath(outfile) ){
-
5185 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission.");
-
5186 }
-
5187
-
5188 if( frame>=0 ) {
-
5189 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
-
5190 }else{
-
5191 outfile << cameralabel << "_" << imagefile_base << ".txt";
+
5167 if( empty_flag ){
+
5168 std::cerr << "WARNING (RadiationModel::writePrimitiveDataLabelMap): No primitive data of " << primitive_data_label << " found in camera image. Primitive data map contains only padded values." << std::endl;
+
5169 }
+
5170
+
5171}
+
+
5172
+
+
5173void RadiationModel::writeObjectDataLabelMap(const std::string &cameralabel, const std::string &object_data_label, const std::string &imagefile_base, const std::string &image_path, int frame, float padvalue){
+
5174
+
5175 if( cameras.find(cameralabel)==cameras.end() ){
+
5176 helios_runtime_error( "ERROR (RadiationModel::writeObjectDataLabelMap): Camera '" + cameralabel + "' does not exist." );
+
5177 }
+
5178
+
5179 //Get image UUID labels
+
5180 std::vector<uint> camera_UUIDs;
+
5181 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
+
5182 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
+
5183 helios_runtime_error( "ERROR (RadiationModel::writeObjectDataLabelMap): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
+
5184 }
+
5185 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
+
5186 std::vector<uint> pixel_UUIDs = camera_UUIDs;
+
5187 int2 camera_resolution = cameras.at(cameralabel).resolution;
+
5188
+
5189 std::string frame_str;
+
5190 if( frame>=0 ) {
+
5191 frame_str = std::to_string(frame);
5192 }
5193
-
5194 //Output label image in ".txt" format
-
5195 std::ofstream pixel_data(outfile.str());
-
5196
-
5197 if( !pixel_data.is_open() ){
-
5198 helios_runtime_error( "ERROR (RadiationModel::writeObjectDataLabelMap): Could not open file '" + outfile.str() + "' for writing." );
+
5194 std::string output_path = image_path;
+
5195 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
5196 helios_runtime_error("ERROR (RadiationModel::writeObjectDataLabelMap): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
5197 }else if( !getFileName(output_path).empty() ){
+
5198 helios_runtime_error("ERROR(RadiationModel::writeObjectDataLabelMap): Image output directory contains a filename. This argument should be the path to a directory not a file.");
5199 }
5200
-
5201 bool empty_flag = true;
-
5202 for (uint j = 0; j < camera_resolution.y; j++) {
-
5203 for (uint i = 0; i < camera_resolution.x; i++) {
-
5204 uint ii = camera_resolution.x - i -1;
-
5205 uint UUID =pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
-
5206 uint objID = context->getPrimitiveParentObjectID(UUID);
-
5207 if (context->doesObjectExist(objID) && context->doesObjectDataExist(objID,object_data_label.c_str())){
-
5208 HeliosDataType datatype = context->getObjectDataType(objID,object_data_label.c_str());
-
5209 if( datatype == HELIOS_TYPE_FLOAT ){
-
5210 float labeldata;
-
5211 context->getObjectData(UUID,object_data_label.c_str(),labeldata);
-
5212 pixel_data << labeldata << " ";
-
5213 empty_flag = false;
-
5214 }
-
5215 else if (datatype == HELIOS_TYPE_UINT){
-
5216 uint labeldata;
-
5217 context->getObjectData(UUID,object_data_label.c_str(),labeldata);
-
5218 pixel_data << labeldata << " ";
-
5219 empty_flag = false;
-
5220 }
-
5221 else if (datatype == HELIOS_TYPE_INT){
-
5222 int labeldata;
-
5223 context->getObjectData(UUID,object_data_label.c_str(),labeldata);
-
5224 pixel_data << labeldata << " ";
-
5225 empty_flag = false;
-
5226 }
-
5227 else if (datatype == HELIOS_TYPE_DOUBLE){
-
5228 double labeldata;
-
5229 context->getObjectData(UUID,object_data_label.c_str(),labeldata);
-
5230 pixel_data << labeldata << " ";
-
5231 empty_flag = false;
-
5232 }else{
-
5233 pixel_data << padvalue << " ";
-
5234 }
-
5235 }else{
-
5236 pixel_data << padvalue << " ";
-
5237 }
-
5238 }
-
5239 pixel_data << "\n";
-
5240 }
-
5241 pixel_data.close();
-
5242
-
5243 if( empty_flag ){
-
5244 std::cerr << "WARNING (RadiationModel::writeObjectDataLabelMap): No object data of " << object_data_label << " found in camera image. Object data map contains only padded values." << std::endl;
-
5245 }
-
5246
-
5247}
+
5201 std::ostringstream outfile;
+
5202 outfile << output_path;
+
5203
+
5204 if( frame>=0 ) {
+
5205 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
+
5206 }else{
+
5207 outfile << cameralabel << "_" << imagefile_base << ".txt";
+
5208 }
+
5209
+
5210 //Output label image in ".txt" format
+
5211 std::ofstream pixel_data(outfile.str());
+
5212
+
5213 if( !pixel_data.is_open() ){
+
5214 helios_runtime_error( "ERROR (RadiationModel::writeObjectDataLabelMap): Could not open file '" + outfile.str() + "' for writing." );
+
5215 }
+
5216
+
5217 bool empty_flag = true;
+
5218 for (uint j = 0; j < camera_resolution.y; j++) {
+
5219 for (uint i = 0; i < camera_resolution.x; i++) {
+
5220 uint ii = camera_resolution.x - i -1;
+
5221 uint UUID =pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
+
5222 uint objID = context->getPrimitiveParentObjectID(UUID);
+
5223 if (context->doesObjectExist(objID) && context->doesObjectDataExist(objID,object_data_label.c_str())){
+
5224 HeliosDataType datatype = context->getObjectDataType(objID,object_data_label.c_str());
+
5225 if( datatype == HELIOS_TYPE_FLOAT ){
+
5226 float labeldata;
+
5227 context->getObjectData(UUID,object_data_label.c_str(),labeldata);
+
5228 pixel_data << labeldata << " ";
+
5229 empty_flag = false;
+
5230 }
+
5231 else if (datatype == HELIOS_TYPE_UINT){
+
5232 uint labeldata;
+
5233 context->getObjectData(UUID,object_data_label.c_str(),labeldata);
+
5234 pixel_data << labeldata << " ";
+
5235 empty_flag = false;
+
5236 }
+
5237 else if (datatype == HELIOS_TYPE_INT){
+
5238 int labeldata;
+
5239 context->getObjectData(UUID,object_data_label.c_str(),labeldata);
+
5240 pixel_data << labeldata << " ";
+
5241 empty_flag = false;
+
5242 }
+
5243 else if (datatype == HELIOS_TYPE_DOUBLE){
+
5244 double labeldata;
+
5245 context->getObjectData(UUID,object_data_label.c_str(),labeldata);
+
5246 pixel_data << labeldata << " ";
+
5247 empty_flag = false;
+
5248 }else{
+
5249 pixel_data << padvalue << " ";
+
5250 }
+
5251 }else{
+
5252 pixel_data << padvalue << " ";
+
5253 }
+
5254 }
+
5255 pixel_data << "\n";
+
5256 }
+
5257 pixel_data.close();
+
5258
+
5259 if( empty_flag ){
+
5260 std::cerr << "WARNING (RadiationModel::writeObjectDataLabelMap): No object data of " << object_data_label << " found in camera image. Object data map contains only padded values." << std::endl;
+
5261 }
+
5262
+
5263}
-
5248
-
-
5249void RadiationModel::writeDepthImageData(const std::string &cameralabel, const std::string &imagefile_base, const std::string &image_path, int frame) {
-
5250
-
5251 if( cameras.find(cameralabel)==cameras.end() ){
-
5252 helios_runtime_error( "ERROR (RadiationModel::writeDepthImageData): Camera '" + cameralabel + "' does not exist." );
-
5253 }
-
5254
-
5255 std::string global_data_label = "camera_" + cameralabel + "_pixel_depth";
-
5256 if( !context->doesGlobalDataExist(global_data_label.c_str()) ){
-
5257 helios_runtime_error("ERROR (RadiationModel::writeDepthImageData): Depth data for camera '" + cameralabel + "' does not exist. Was the radiation model run for the camera?" );
-
5258 }
-
5259 std::vector<float> camera_depth;
-
5260 context->getGlobalData(global_data_label.c_str(), camera_depth);
-
5261 helios::vec3 camera_position = cameras.at(cameralabel).position;
-
5262 helios::vec3 camera_lookat = cameras.at(cameralabel).lookat;
-
5263
-
5264 int2 camera_resolution = cameras.at(cameralabel).resolution;
-
5265
-
5266 std::string frame_str;
-
5267 if( frame>=0 ) {
-
5268 frame_str = std::to_string(frame);
+
5264
+
+
5265void RadiationModel::writeDepthImageData(const std::string &cameralabel, const std::string &imagefile_base, const std::string &image_path, int frame) {
+
5266
+
5267 if( cameras.find(cameralabel)==cameras.end() ){
+
5268 helios_runtime_error( "ERROR (RadiationModel::writeDepthImageData): Camera '" + cameralabel + "' does not exist." );
5269 }
5270
-
5271 std::ostringstream outfile;
-
5272
-
5273 if( !validateOutputPath(outfile) ){
-
5274 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission.");
-
5275 }
-
5276
-
5277 if( frame>=0 ) {
-
5278 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
-
5279 }else{
-
5280 outfile << cameralabel << "_" << imagefile_base << ".txt";
-
5281 }
-
5282
-
5283 //Output label image in ".txt" format
-
5284 std::ofstream pixel_data(outfile.str());
-
5285
-
5286 if( !pixel_data.is_open() ){
-
5287 helios_runtime_error( "ERROR (RadiationModel::writeDepthImageData): Could not open file '" + outfile.str() + "' for writing." );
-
5288 }
-
5289
-
5290 for ( int j = 0; j<camera_resolution.y; j++ ) {
-
5291 for ( int i = camera_resolution.x-1; i >= 0; i--) {
-
5292 pixel_data << camera_depth.at(j*camera_resolution.x + i) << " ";
-
5293 }
-
5294 pixel_data << "\n";
-
5295 }
+
5271 std::string global_data_label = "camera_" + cameralabel + "_pixel_depth";
+
5272 if( !context->doesGlobalDataExist(global_data_label.c_str()) ){
+
5273 helios_runtime_error("ERROR (RadiationModel::writeDepthImageData): Depth data for camera '" + cameralabel + "' does not exist. Was the radiation model run for the camera?" );
+
5274 }
+
5275 std::vector<float> camera_depth;
+
5276 context->getGlobalData(global_data_label.c_str(), camera_depth);
+
5277 helios::vec3 camera_position = cameras.at(cameralabel).position;
+
5278 helios::vec3 camera_lookat = cameras.at(cameralabel).lookat;
+
5279
+
5280 int2 camera_resolution = cameras.at(cameralabel).resolution;
+
5281
+
5282 std::string frame_str;
+
5283 if( frame>=0 ) {
+
5284 frame_str = std::to_string(frame);
+
5285 }
+
5286
+
5287 std::string output_path = image_path;
+
5288 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
5289 helios_runtime_error("ERROR (RadiationModel::writeDepthImageData): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
5290 }else if( !getFileName(output_path).empty() ){
+
5291 helios_runtime_error("ERROR(RadiationModel::writeDepthImageData): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
5292 }
+
5293
+
5294 std::ostringstream outfile;
+
5295 outfile << output_path;
5296
-
5297 pixel_data.close();
-
5298
-
5299}
-
-
5300
-
-
5301void RadiationModel::writeNormDepthImage(const std::string &cameralabel, const std::string &imagefile_base, float max_depth, const std::string &image_path, int frame){
+
5297 if( frame>=0 ) {
+
5298 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
+
5299 }else{
+
5300 outfile << cameralabel << "_" << imagefile_base << ".txt";
+
5301 }
5302
-
5303 if( cameras.find(cameralabel)==cameras.end() ){
-
5304 helios_runtime_error( "ERROR (RadiationModel::writeNormDepthImage): Camera '" + cameralabel + "' does not exist." );
-
5305 }
-
5306
-
5307 std::string global_data_label = "camera_" + cameralabel + "_pixel_depth";
-
5308 if( !context->doesGlobalDataExist(global_data_label.c_str()) ){
-
5309 helios_runtime_error("ERROR (RadiationModel::writeNormDepthImage): Depth data for camera '" + cameralabel + "' does not exist. Was the radiation model run for the camera?" );
-
5310 }
-
5311 std::vector<float> camera_depth;
-
5312 context->getGlobalData(global_data_label.c_str(), camera_depth);
-
5313 helios::vec3 camera_position = cameras.at(cameralabel).position;
-
5314 helios::vec3 camera_lookat = cameras.at(cameralabel).lookat;
-
5315
-
5316 int2 camera_resolution = cameras.at(cameralabel).resolution;
-
5317
-
5318 std::string frame_str;
-
5319 if( frame>=0 ) {
-
5320 frame_str = std::to_string(frame);
-
5321 }
+
5303 //Output label image in ".txt" format
+
5304 std::ofstream pixel_data(outfile.str());
+
5305
+
5306 if( !pixel_data.is_open() ){
+
5307 helios_runtime_error( "ERROR (RadiationModel::writeDepthImageData): Could not open file '" + outfile.str() + "' for writing." );
+
5308 }
+
5309
+
5310 for ( int j = 0; j<camera_resolution.y; j++ ) {
+
5311 for ( int i = camera_resolution.x-1; i >= 0; i--) {
+
5312 pixel_data << camera_depth.at(j*camera_resolution.x + i) << " ";
+
5313 }
+
5314 pixel_data << "\n";
+
5315 }
+
5316
+
5317 pixel_data.close();
+
5318
+
5319}
+
+
5320
+
+
5321void RadiationModel::writeNormDepthImage(const std::string &cameralabel, const std::string &imagefile_base, float max_depth, const std::string &image_path, int frame){
5322
-
5323 std::ostringstream outfile;
-
5324
-
5325 if( !validateOutputPath(outfile) ){
-
5326 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission.");
-
5327 }
-
5328
-
5329 if( frame>=0 ) {
-
5330 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".jpeg";
-
5331 }else{
-
5332 outfile << cameralabel << "_" << imagefile_base << ".jpeg";
-
5333 }
-
5334
-
5335 float min_depth = 99999;
-
5336 for( int i=0; i<camera_depth.size(); i++ ){
-
5337 if( camera_depth.at(i)<0 || camera_depth.at(i)>max_depth ){
-
5338 camera_depth.at(i) = max_depth;
-
5339 }
-
5340 if( camera_depth.at(i)<min_depth ){
-
5341 min_depth = camera_depth.at(i);
-
5342 }
-
5343 }
-
5344 for( int i=0; i<camera_depth.size(); i++ ){
-
5345 camera_depth.at(i) = 1.f-(camera_depth.at(i)-min_depth)/(max_depth-min_depth);
-
5346 }
-
5347
-
5348 std::vector<RGBcolor> pixel_data(camera_resolution.x*camera_resolution.y);
+
5323 if( cameras.find(cameralabel)==cameras.end() ){
+
5324 helios_runtime_error( "ERROR (RadiationModel::writeNormDepthImage): Camera '" + cameralabel + "' does not exist." );
+
5325 }
+
5326
+
5327 std::string global_data_label = "camera_" + cameralabel + "_pixel_depth";
+
5328 if( !context->doesGlobalDataExist(global_data_label.c_str()) ){
+
5329 helios_runtime_error("ERROR (RadiationModel::writeNormDepthImage): Depth data for camera '" + cameralabel + "' does not exist. Was the radiation model run for the camera?" );
+
5330 }
+
5331 std::vector<float> camera_depth;
+
5332 context->getGlobalData(global_data_label.c_str(), camera_depth);
+
5333 helios::vec3 camera_position = cameras.at(cameralabel).position;
+
5334 helios::vec3 camera_lookat = cameras.at(cameralabel).lookat;
+
5335
+
5336 int2 camera_resolution = cameras.at(cameralabel).resolution;
+
5337
+
5338 std::string frame_str;
+
5339 if( frame>=0 ) {
+
5340 frame_str = std::to_string(frame);
+
5341 }
+
5342
+
5343 std::string output_path = image_path;
+
5344 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
5345 helios_runtime_error("ERROR (RadiationModel::writeNormDepthImage): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
5346 }else if( !getFileName(output_path).empty() ){
+
5347 helios_runtime_error("ERROR(RadiationModel::writeNormDepthImage): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
5348 }
5349
-
5350 RGBcolor pixel_color;
-
5351 for (uint j = 0; j < camera_resolution.y; j++) {
-
5352 for (uint i=0; i < camera_resolution.x; i++) {
-
5353
-
5354 float c = camera_depth.at(j * camera_resolution.x + i);
-
5355 pixel_color = make_RGBcolor(c,c,c);
-
5356
-
5357 uint ii = camera_resolution.x - i -1;
-
5358 uint jj = camera_resolution.y - j - 1;
-
5359 pixel_data.at(jj * camera_resolution.x + ii) = pixel_color;
-
5360 }
-
5361 }
-
5362
-
5363 writeJPEG( outfile.str(), camera_resolution.x, camera_resolution.y, pixel_data );
-
5364
-
5365}
-
-
5366
-
5367
-
-
5368void RadiationModel::writeImageBoundingBoxes(const std::string &cameralabel, const std::string &primitive_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path, bool append_label_file, int frame){
-
5369
-
5370 if( cameras.find(cameralabel)==cameras.end() ){
-
5371 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes): Camera '" + cameralabel + "' does not exist." );
-
5372 }
+
5350 std::ostringstream outfile;
+
5351 outfile << output_path;
+
5352
+
5353 if( frame>=0 ) {
+
5354 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".jpeg";
+
5355 }else{
+
5356 outfile << cameralabel << "_" << imagefile_base << ".jpeg";
+
5357 }
+
5358
+
5359 float min_depth = 99999;
+
5360 for( int i=0; i<camera_depth.size(); i++ ){
+
5361 if( camera_depth.at(i)<0 || camera_depth.at(i)>max_depth ){
+
5362 camera_depth.at(i) = max_depth;
+
5363 }
+
5364 if( camera_depth.at(i)<min_depth ){
+
5365 min_depth = camera_depth.at(i);
+
5366 }
+
5367 }
+
5368 for( int i=0; i<camera_depth.size(); i++ ){
+
5369 camera_depth.at(i) = 1.f-(camera_depth.at(i)-min_depth)/(max_depth-min_depth);
+
5370 }
+
5371
+
5372 std::vector<RGBcolor> pixel_data(camera_resolution.x*camera_resolution.y);
5373
-
5374 //Get image UUID labels
-
5375 std::vector<uint> camera_UUIDs;
-
5376 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
-
5377 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
-
5378 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
-
5379 }
-
5380 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
-
5381 std::vector<uint> pixel_UUIDs = camera_UUIDs;
-
5382 int2 camera_resolution = cameras.at(cameralabel).resolution;
-
5383
-
5384 std::string frame_str;
-
5385 if( frame>=0 ) {
-
5386 frame_str = std::to_string(frame);
-
5387 }
+
5374 RGBcolor pixel_color;
+
5375 for (uint j = 0; j < camera_resolution.y; j++) {
+
5376 for (uint i=0; i < camera_resolution.x; i++) {
+
5377
+
5378 float c = camera_depth.at(j * camera_resolution.x + i);
+
5379 pixel_color = make_RGBcolor(c,c,c);
+
5380
+
5381 uint ii = camera_resolution.x - i -1;
+
5382 uint jj = camera_resolution.y - j - 1;
+
5383 pixel_data.at(jj * camera_resolution.x + ii) = pixel_color;
+
5384 }
+
5385 }
+
5386
+
5387 writeJPEG( outfile.str(), camera_resolution.x, camera_resolution.y, pixel_data );
5388
-
5389 std::ostringstream outfile;
+
5389}
+
5390
-
5391 if( !validateOutputPath(outfile) ){
-
5392 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission.");
-
5393 }
-
5394
-
5395 if( frame>=0 ) {
-
5396 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
-
5397 }else{
-
5398 outfile << cameralabel << "_" << imagefile_base << ".txt";
-
5399 }
-
5400
-
5401 //Output label image in ".txt" format
-
5402 std::ofstream label_file;
-
5403 if( append_label_file ){
-
5404 label_file.open(outfile.str(), std::ios::out | std::ios::app);
-
5405 }else{
-
5406 label_file.open(outfile.str());
-
5407 }
-
5408
-
5409 if( !label_file.is_open() ){
-
5410 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes): Could not open file '" + outfile.str() + "'." );
+
5391
+
+
5392void RadiationModel::writeImageBoundingBoxes(const std::string &cameralabel, const std::string &primitive_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path, bool append_label_file, int frame){
+
5393
+
5394 if( cameras.find(cameralabel)==cameras.end() ){
+
5395 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes): Camera '" + cameralabel + "' does not exist." );
+
5396 }
+
5397
+
5398 //Get image UUID labels
+
5399 std::vector<uint> camera_UUIDs;
+
5400 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
+
5401 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
+
5402 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
+
5403 }
+
5404 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
+
5405 std::vector<uint> pixel_UUIDs = camera_UUIDs;
+
5406 int2 camera_resolution = cameras.at(cameralabel).resolution;
+
5407
+
5408 std::string frame_str;
+
5409 if( frame>=0 ) {
+
5410 frame_str = std::to_string(frame);
5411 }
5412
-
5413 std::map<int, vec4> pdata_bounds;
-
5414
-
5415 for (int j = 0; j < camera_resolution.y; j++) {
-
5416 for (int i = 0; i < camera_resolution.x; i++) {
-
5417 uint ii = camera_resolution.x - i -1;
-
5418 uint UUID =pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
-
5419 if (context->doesPrimitiveExist(UUID) && context->doesPrimitiveDataExist(UUID,primitive_data_label.c_str())){
-
5420
-
5421 uint labeldata;
+
5413 std::string output_path = image_path;
+
5414 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
5415 helios_runtime_error("ERROR (RadiationModel::writeImageBoundingBoxes): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
5416 }else if( !getFileName(output_path).empty() ){
+
5417 helios_runtime_error("ERROR(RadiationModel::writeImageBoundingBoxes): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
5418 }
+
5419
+
5420 std::ostringstream outfile;
+
5421 outfile << output_path;
5422
-
5423 HeliosDataType datatype = context->getPrimitiveDataType(UUID,primitive_data_label.c_str());
-
5424 if (datatype == HELIOS_TYPE_UINT){
-
5425 uint labeldata_ui;
-
5426 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata_ui);
-
5427 labeldata = labeldata_ui;
-
5428 }
-
5429 else if (datatype == HELIOS_TYPE_INT){
-
5430 int labeldata_i;
-
5431 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata_i);
-
5432 labeldata = (uint)labeldata_i;
-
5433 }else{
-
5434 continue;
-
5435 }
+
5423 if( frame>=0 ) {
+
5424 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
+
5425 }else{
+
5426 outfile << cameralabel << "_" << imagefile_base << ".txt";
+
5427 }
+
5428
+
5429 //Output label image in ".txt" format
+
5430 std::ofstream label_file;
+
5431 if( append_label_file ){
+
5432 label_file.open(outfile.str(), std::ios::out | std::ios::app);
+
5433 }else{
+
5434 label_file.open(outfile.str());
+
5435 }
5436
-
5437 if( pdata_bounds.find(labeldata) == pdata_bounds.end() ) {
-
5438 pdata_bounds[labeldata] = make_vec4(1e6, -1, 1e6, -1);
-
5439 }
+
5437 if( !label_file.is_open() ){
+
5438 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes): Could not open file '" + outfile.str() + "'." );
+
5439 }
5440
-
5441 if( i<pdata_bounds[labeldata].x ){
-
5442 pdata_bounds[labeldata].x = i;
-
5443 }
-
5444 if( i>pdata_bounds[labeldata].y ){
-
5445 pdata_bounds[labeldata].y = i;
-
5446 }
-
5447 if( j<pdata_bounds[labeldata].z ){
-
5448 pdata_bounds[labeldata].z = j;
-
5449 }
-
5450 if( j>pdata_bounds[labeldata].w ){
-
5451 pdata_bounds[labeldata].w = j;
-
5452 }
-
5453
-
5454 }
-
5455 }
-
5456 }
-
5457
-
5458 for( auto box : pdata_bounds ){
-
5459 vec4 bbox = box.second;
-
5460 if( bbox.x==bbox.y || bbox.z==bbox.w ){ //filter boxes of zeros size
-
5461 continue;
-
5462 }
-
5463 label_file << object_class_ID << " " << (bbox.x + 0.5 * (bbox.y - bbox.x)) / float(camera_resolution.x) << " "
-
5464 << (bbox.z + 0.5 * (bbox.w - bbox.z)) / float(camera_resolution.y) << " " << std::setprecision(6)
-
5465 << std::fixed << (bbox.y - bbox.x) / float(camera_resolution.x) << " "
-
5466 << (bbox.w - bbox.z) / float(camera_resolution.y) << std::endl;
-
5467 }
+
5441 std::map<int, vec4> pdata_bounds;
+
5442
+
5443 for (int j = 0; j < camera_resolution.y; j++) {
+
5444 for (int i = 0; i < camera_resolution.x; i++) {
+
5445 uint ii = camera_resolution.x - i -1;
+
5446 uint UUID =pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
+
5447 if (context->doesPrimitiveExist(UUID) && context->doesPrimitiveDataExist(UUID,primitive_data_label.c_str())){
+
5448
+
5449 uint labeldata;
+
5450
+
5451 HeliosDataType datatype = context->getPrimitiveDataType(UUID,primitive_data_label.c_str());
+
5452 if (datatype == HELIOS_TYPE_UINT){
+
5453 uint labeldata_ui;
+
5454 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata_ui);
+
5455 labeldata = labeldata_ui;
+
5456 }
+
5457 else if (datatype == HELIOS_TYPE_INT){
+
5458 int labeldata_i;
+
5459 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata_i);
+
5460 labeldata = (uint)labeldata_i;
+
5461 }else{
+
5462 continue;
+
5463 }
+
5464
+
5465 if( pdata_bounds.find(labeldata) == pdata_bounds.end() ) {
+
5466 pdata_bounds[labeldata] = make_vec4(1e6, -1, 1e6, -1);
+
5467 }
5468
-
5469 label_file.close();
-
5470
-
5471}
-
-
5472
-
-
5473void RadiationModel::writeImageBoundingBoxes_ObjectData(const std::string &cameralabel, const std::string &object_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path, bool append_label_file, int frame){
-
5474
-
5475 if( cameras.find(cameralabel)==cameras.end() ){
-
5476 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Camera '" + cameralabel + "' does not exist." );
-
5477 }
-
5478
-
5479 //Get image UUID labels
-
5480 std::vector<uint> camera_UUIDs;
-
5481 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
-
5482 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
-
5483 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
+
5469 if( i<pdata_bounds[labeldata].x ){
+
5470 pdata_bounds[labeldata].x = i;
+
5471 }
+
5472 if( i>pdata_bounds[labeldata].y ){
+
5473 pdata_bounds[labeldata].y = i;
+
5474 }
+
5475 if( j<pdata_bounds[labeldata].z ){
+
5476 pdata_bounds[labeldata].z = j;
+
5477 }
+
5478 if( j>pdata_bounds[labeldata].w ){
+
5479 pdata_bounds[labeldata].w = j;
+
5480 }
+
5481
+
5482 }
+
5483 }
5484 }
-
5485 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
-
5486 std::vector<uint> pixel_UUIDs = camera_UUIDs;
-
5487 int2 camera_resolution = cameras.at(cameralabel).resolution;
-
5488
-
5489 std::string frame_str;
-
5490 if( frame>=0 ) {
-
5491 frame_str = std::to_string(frame);
-
5492 }
-
5493
-
5494 std::ostringstream outfile;
-
5495
-
5496 if( !validateOutputPath(outfile) ){
-
5497 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission.");
-
5498 }
-
5499
-
5500 if( frame>=0 ) {
-
5501 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
-
5502 }else{
-
5503 outfile << cameralabel << "_" << imagefile_base << ".txt";
-
5504 }
-
5505
-
5506 //Output label image in ".txt" format
-
5507 std::ofstream label_file;
-
5508 if( append_label_file ){
-
5509 label_file.open(outfile.str(), std::ios::out | std::ios::app);
-
5510 }else{
-
5511 label_file.open(outfile.str());
+
5485
+
5486 for( auto box : pdata_bounds ){
+
5487 vec4 bbox = box.second;
+
5488 if( bbox.x==bbox.y || bbox.z==bbox.w ){ //filter boxes of zeros size
+
5489 continue;
+
5490 }
+
5491 label_file << object_class_ID << " " << (bbox.x + 0.5 * (bbox.y - bbox.x)) / float(camera_resolution.x) << " "
+
5492 << (bbox.z + 0.5 * (bbox.w - bbox.z)) / float(camera_resolution.y) << " " << std::setprecision(6)
+
5493 << std::fixed << (bbox.y - bbox.x) / float(camera_resolution.x) << " "
+
5494 << (bbox.w - bbox.z) / float(camera_resolution.y) << std::endl;
+
5495 }
+
5496
+
5497 label_file.close();
+
5498
+
5499}
+
+
5500
+
+
5501void RadiationModel::writeImageBoundingBoxes_ObjectData(const std::string &cameralabel, const std::string &object_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path, bool append_label_file, int frame){
+
5502
+
5503 if( cameras.find(cameralabel)==cameras.end() ){
+
5504 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Camera '" + cameralabel + "' does not exist." );
+
5505 }
+
5506
+
5507 //Get image UUID labels
+
5508 std::vector<uint> camera_UUIDs;
+
5509 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
+
5510 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
+
5511 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
5512 }
-
5513
-
5514 if( !label_file.is_open() ){
-
5515 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Could not open file '" + outfile.str() + "'." );
-
5516 }
-
5517
-
5518 std::map<int, vec4> pdata_bounds;
-
5519
-
5520 for (int j = 0; j < camera_resolution.y; j++) {
-
5521 for (int i = 0; i < camera_resolution.x; i++) {
-
5522 uint ii = camera_resolution.x - i -1;
-
5523 uint UUID = pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
-
5524
-
5525 if ( !context->doesPrimitiveExist(UUID) ){
-
5526 continue;
-
5527 }
+
5513 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
+
5514 std::vector<uint> pixel_UUIDs = camera_UUIDs;
+
5515 int2 camera_resolution = cameras.at(cameralabel).resolution;
+
5516
+
5517 std::string frame_str;
+
5518 if( frame>=0 ) {
+
5519 frame_str = std::to_string(frame);
+
5520 }
+
5521
+
5522 std::string output_path = image_path;
+
5523 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
5524 helios_runtime_error("ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
5525 }else if( !getFileName(output_path).empty() ){
+
5526 helios_runtime_error("ERROR(RadiationModel::writeImageBoundingBoxes_ObjectData): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
5527 }
5528
-
5529 uint objID = context->getPrimitiveParentObjectID(UUID);
-
5530
-
5531 if ( !context->doesObjectExist(objID) || !context->doesObjectDataExist(objID,object_data_label.c_str())) {
-
5532 continue;
-
5533 }
-
5534
-
5535 uint labeldata;
-
5536
-
5537 HeliosDataType datatype = context->getObjectDataType(objID,object_data_label.c_str());
-
5538 if (datatype == HELIOS_TYPE_UINT){
-
5539 uint labeldata_ui;
-
5540 context->getObjectData(objID,object_data_label.c_str(),labeldata_ui);
-
5541 labeldata = labeldata_ui;
-
5542 }
-
5543 else if (datatype == HELIOS_TYPE_INT){
-
5544 int labeldata_i;
-
5545 context->getObjectData(objID,object_data_label.c_str(),labeldata_i);
-
5546 labeldata = (uint)labeldata_i;
-
5547 }else{
-
5548 continue;
-
5549 }
-
5550
-
5551 if( pdata_bounds.find(labeldata) == pdata_bounds.end() ) {
-
5552 pdata_bounds[labeldata] = make_vec4(1e6, -1, 1e6, -1);
-
5553 }
-
5554
-
5555 if( i<pdata_bounds[labeldata].x ){
-
5556 pdata_bounds[labeldata].x = i;
-
5557 }
-
5558 if( i>pdata_bounds[labeldata].y ){
-
5559 pdata_bounds[labeldata].y = i;
-
5560 }
-
5561 if( j<pdata_bounds[labeldata].z ){
-
5562 pdata_bounds[labeldata].z = j;
-
5563 }
-
5564 if( j>pdata_bounds[labeldata].w ){
-
5565 pdata_bounds[labeldata].w = j;
-
5566 }
-
5567
-
5568 }
-
5569 }
-
5570
-
5571 for( auto box : pdata_bounds ){
-
5572 vec4 bbox = box.second;
-
5573 if( bbox.x==bbox.y || bbox.z==bbox.w ){ //filter boxes of zeros size
-
5574 continue;
-
5575 }
-
5576 label_file << object_class_ID << " " << (bbox.x + 0.5 * (bbox.y - bbox.x)) / float(camera_resolution.x) << " "
-
5577 << (bbox.z + 0.5 * (bbox.w - bbox.z)) / float(camera_resolution.y) << " " << std::setprecision(6)
-
5578 << std::fixed << (bbox.y - bbox.x) / float(camera_resolution.x) << " "
-
5579 << (bbox.w - bbox.z) / float(camera_resolution.y) << std::endl;
-
5580 }
-
5581
-
5582 label_file.close();
-
5583
-
5584}
-
-
5585
+
5529 std::ostringstream outfile;
+
5530 outfile << output_path;
+
5531
+
5532 if( frame>=0 ) {
+
5533 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
+
5534 }else{
+
5535 outfile << cameralabel << "_" << imagefile_base << ".txt";
+
5536 }
+
5537
+
5538 //Output label image in ".txt" format
+
5539 std::ofstream label_file;
+
5540 if( append_label_file ){
+
5541 label_file.open(outfile.str(), std::ios::out | std::ios::app);
+
5542 }else{
+
5543 label_file.open(outfile.str());
+
5544 }
+
5545
+
5546 if( !label_file.is_open() ){
+
5547 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Could not open file '" + outfile.str() + "'." );
+
5548 }
+
5549
+
5550 std::map<int, vec4> pdata_bounds;
+
5551
+
5552 for (int j = 0; j < camera_resolution.y; j++) {
+
5553 for (int i = 0; i < camera_resolution.x; i++) {
+
5554 uint ii = camera_resolution.x - i -1;
+
5555 uint UUID = pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
+
5556
+
5557 if ( !context->doesPrimitiveExist(UUID) ){
+
5558 continue;
+
5559 }
+
5560
+
5561 uint objID = context->getPrimitiveParentObjectID(UUID);
+
5562
+
5563 if ( !context->doesObjectExist(objID) || !context->doesObjectDataExist(objID,object_data_label.c_str())) {
+
5564 continue;
+
5565 }
+
5566
+
5567 uint labeldata;
+
5568
+
5569 HeliosDataType datatype = context->getObjectDataType(objID,object_data_label.c_str());
+
5570 if (datatype == HELIOS_TYPE_UINT){
+
5571 uint labeldata_ui;
+
5572 context->getObjectData(objID,object_data_label.c_str(),labeldata_ui);
+
5573 labeldata = labeldata_ui;
+
5574 }
+
5575 else if (datatype == HELIOS_TYPE_INT){
+
5576 int labeldata_i;
+
5577 context->getObjectData(objID,object_data_label.c_str(),labeldata_i);
+
5578 labeldata = (uint)labeldata_i;
+
5579 }else{
+
5580 continue;
+
5581 }
+
5582
+
5583 if( pdata_bounds.find(labeldata) == pdata_bounds.end() ) {
+
5584 pdata_bounds[labeldata] = make_vec4(1e6, -1, 1e6, -1);
+
5585 }
5586
-
-
5587void RadiationModel::setPadValue(const std::string &cameralabel, const std::vector<std::string> &bandlabels, const std::vector<float> &padvalues) {
-
5588 for (uint b = 0; b < bandlabels.size(); b++) {
-
5589 std::string bandlabel = bandlabels.at(b);
-
5590
-
5591 std::string image_value_label = "camera_" + cameralabel + "_" + bandlabel;
-
5592 std::vector<float> cameradata;
-
5593 context->getGlobalData(image_value_label.c_str(), cameradata);
-
5594
-
5595 std::vector<uint> camera_UUIDs;
-
5596 std::string image_UUID_label = "camera_" + cameralabel + "_pixel_UUID";
-
5597 context->getGlobalData(image_UUID_label.c_str(), camera_UUIDs);
-
5598
-
5599 for (uint i = 0; i < cameradata.size(); i++) {
-
5600 uint UUID = camera_UUIDs.at(i)-1;
-
5601 if (!context->doesPrimitiveExist(UUID)) {
-
5602 cameradata.at(i) = padvalues.at(b);
-
5603 }
-
5604 }
-
5605 context->setGlobalData(image_value_label.c_str(), HELIOS_TYPE_FLOAT, cameradata.size(), &cameradata[0]);
-
5606 }
-
5607}
+
5587 if( i<pdata_bounds[labeldata].x ){
+
5588 pdata_bounds[labeldata].x = i;
+
5589 }
+
5590 if( i>pdata_bounds[labeldata].y ){
+
5591 pdata_bounds[labeldata].y = i;
+
5592 }
+
5593 if( j<pdata_bounds[labeldata].z ){
+
5594 pdata_bounds[labeldata].z = j;
+
5595 }
+
5596 if( j>pdata_bounds[labeldata].w ){
+
5597 pdata_bounds[labeldata].w = j;
+
5598 }
+
5599
+
5600 }
+
5601 }
+
5602
+
5603 for( auto box : pdata_bounds ){
+
5604 vec4 bbox = box.second;
+
5605 if( bbox.x==bbox.y || bbox.z==bbox.w ){ //filter boxes of zeros size
+
5606 continue;
+
5607 }
+
5608 label_file << object_class_ID << " " << (bbox.x + 0.5 * (bbox.y - bbox.x)) / float(camera_resolution.x) << " "
+
5609 << (bbox.z + 0.5 * (bbox.w - bbox.z)) / float(camera_resolution.y) << " " << std::setprecision(6)
+
5610 << std::fixed << (bbox.y - bbox.x) / float(camera_resolution.x) << " "
+
5611 << (bbox.w - bbox.z) / float(camera_resolution.y) << std::endl;
+
5612 }
+
5613
+
5614 label_file.close();
+
5615
+
5616}
-
5608
-
-
5609void RadiationModel::calibrateCamera(const std::string &originalcameralabel, const std::vector<std::string> &sourcelabels,
-
5610 const std::vector<std::string>& cameraresplabels_raw, const std::vector<std::string> &bandlabels, const float scalefactor,
-
5611 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark) {
-
5612
-
5613 if( cameras.find(originalcameralabel) == cameras.end() ){
-
5614 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): Camera " + originalcameralabel + " does not exist.");
-
5615 }else if( radiation_sources.empty() ){
-
5616 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): No radiation sources were added to the radiation model. Cannot perform calibration.");
-
5617 }
+
5617
5618
-
5619 CameraCalibration cameracalibration_(context);
-
5620 if (!calibration_flag){
-
5621 std::cout<< "No color board added, use default color calibration." <<std::endl;
-
5622 cameracalibration = &cameracalibration_;
-
5623 vec3 centrelocation =make_vec3(0,0,0.2); // Location of color board
-
5624 vec3 rotationrad =make_vec3(0,0,1.5705); // Rotation angle of color board
-
5625 cameracalibration->addDefaultColorboard(centrelocation, 0.1, rotationrad);
-
5626 }
-
5627 vec2 wavelengthrange = make_vec2(-10000,10000);
-
5628
-
5629 // Calibrated camera response labels
-
5630 std::vector<std::string> cameraresplabels_cal(cameraresplabels_raw.size());
-
5631
-
5632 for (int iband=0;iband<bandlabels.size();iband++){
-
5633 cameraresplabels_cal.at(iband) = calibratedmark + "_" + cameraresplabels_raw.at(iband);
-
5634 }
-
5635
-
5636 RadiationModel::runRadiationImaging(originalcameralabel, sourcelabels, bandlabels, cameraresplabels_raw, wavelengthrange, 1, 0);
-
5637 // Update camera responses
-
5638 RadiationModel::updateCameraResponse(originalcameralabel, sourcelabels, cameraresplabels_raw, wavelengthrange, truevalues, calibratedmark);
-
5639
-
5640 float camerascale = RadiationModel::getCameraResponseScale(originalcameralabel, cameraresplabels_cal, bandlabels,sourcelabels, wavelengthrange, truevalues);
-
5641
-
5642 std::cout << "Camera response scale: " << camerascale << std::endl;
-
5643 // Scale and write calibrated camera responses
-
5644 cameracalibration->writeCalibratedCameraResponses(cameraresplabels_raw, calibratedmark, camerascale*scalefactor);
-
5645
-
5646}
+
+
5619void RadiationModel::setPadValue(const std::string &cameralabel, const std::vector<std::string> &bandlabels, const std::vector<float> &padvalues) {
+
5620 for (uint b = 0; b < bandlabels.size(); b++) {
+
5621 std::string bandlabel = bandlabels.at(b);
+
5622
+
5623 std::string image_value_label = "camera_" + cameralabel + "_" + bandlabel;
+
5624 std::vector<float> cameradata;
+
5625 context->getGlobalData(image_value_label.c_str(), cameradata);
+
5626
+
5627 std::vector<uint> camera_UUIDs;
+
5628 std::string image_UUID_label = "camera_" + cameralabel + "_pixel_UUID";
+
5629 context->getGlobalData(image_UUID_label.c_str(), camera_UUIDs);
+
5630
+
5631 for (uint i = 0; i < cameradata.size(); i++) {
+
5632 uint UUID = camera_UUIDs.at(i)-1;
+
5633 if (!context->doesPrimitiveExist(UUID)) {
+
5634 cameradata.at(i) = padvalues.at(b);
+
5635 }
+
5636 }
+
5637 context->setGlobalData(image_value_label.c_str(), HELIOS_TYPE_FLOAT, cameradata.size(), &cameradata[0]);
+
5638 }
+
5639}
-
5647
-
-
5648void RadiationModel::calibrateCamera(const std::string &originalcameralabel, const float scalefactor, const std::vector<std::vector<float>> &truevalues,
-
5649 const std::string &calibratedmark) {
+
5640
+
+
5641void RadiationModel::calibrateCamera(const std::string &originalcameralabel, const std::vector<std::string> &sourcelabels,
+
5642 const std::vector<std::string>& cameraresplabels_raw, const std::vector<std::string> &bandlabels, const float scalefactor,
+
5643 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark) {
+
5644
+
5645 if( cameras.find(originalcameralabel) == cameras.end() ){
+
5646 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): Camera " + originalcameralabel + " does not exist.");
+
5647 }else if( radiation_sources.empty() ){
+
5648 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): No radiation sources were added to the radiation model. Cannot perform calibration.");
+
5649 }
5650
-
5651 if( cameras.find(originalcameralabel) == cameras.end() ){
-
5652 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): Camera " + originalcameralabel + " does not exist.");
-
5653 }else if( radiation_sources.empty() ){
-
5654 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): No radiation sources were added to the radiation model. Cannot perform calibration.");
-
5655 }
-
5656
-
5657 CameraCalibration cameracalibration_(context);
-
5658 if (!calibration_flag){
-
5659 std::cout<< "No color board added, use default color calibration." <<std::endl;
-
5660 vec3 centrelocation =make_vec3(0,0,0.2); // Location of color board
-
5661 vec3 rotationrad =make_vec3(0,0,1.5705); // Rotation angle of color board
-
5662 cameracalibration_.addDefaultColorboard(centrelocation, 0.1, rotationrad);
-
5663 RadiationModel::setCameraCalibration(&cameracalibration_);
-
5664 }
-
5665
-
5666 vec2 wavelengthrange = make_vec2(-10000,10000);
+
5651 CameraCalibration cameracalibration_(context);
+
5652 if (!calibration_flag){
+
5653 std::cout<< "No color board added, use default color calibration." <<std::endl;
+
5654 cameracalibration = &cameracalibration_;
+
5655 vec3 centrelocation =make_vec3(0,0,0.2); // Location of color board
+
5656 vec3 rotationrad =make_vec3(0,0,1.5705); // Rotation angle of color board
+
5657 cameracalibration->addDefaultColorboard(centrelocation, 0.1, rotationrad);
+
5658 }
+
5659 vec2 wavelengthrange = make_vec2(-10000,10000);
+
5660
+
5661 // Calibrated camera response labels
+
5662 std::vector<std::string> cameraresplabels_cal(cameraresplabels_raw.size());
+
5663
+
5664 for (int iband=0;iband<bandlabels.size();iband++){
+
5665 cameraresplabels_cal.at(iband) = calibratedmark + "_" + cameraresplabels_raw.at(iband);
+
5666 }
5667
-
5668 std::vector<std::string> bandlabels = cameras.at(originalcameralabel).band_labels;
-
5669
-
5670 // Get camera response spectra labels from camera
-
5671 std::vector<std::string> cameraresplabels_cal(cameras.at(originalcameralabel).band_spectral_response.size() );
-
5672 std::vector<std::string> cameraresplabels_raw = cameraresplabels_cal;
+
5668 RadiationModel::runRadiationImaging(originalcameralabel, sourcelabels, bandlabels, cameraresplabels_raw, wavelengthrange, 1, 0);
+
5669 // Update camera responses
+
5670 RadiationModel::updateCameraResponse(originalcameralabel, sourcelabels, cameraresplabels_raw, wavelengthrange, truevalues, calibratedmark);
+
5671
+
5672 float camerascale = RadiationModel::getCameraResponseScale(originalcameralabel, cameraresplabels_cal, bandlabels,sourcelabels, wavelengthrange, truevalues);
5673
-
5674 int iband = 0;
-
5675 for( auto &band : cameras.at(originalcameralabel).band_spectral_response ){
-
5676 cameraresplabels_raw.at(iband) = band.second;
-
5677 cameraresplabels_cal.at(iband) = calibratedmark + "_" + band.second;
-
5678 iband++;
-
5679 }
-
5680
-
5681 // Get labels of radiation sources from camera
-
5682 std::vector<std::string> sourcelabels(radiation_sources.size());
-
5683 int isource = 0;
-
5684 for( auto &source : radiation_sources ){
-
5685 if( source.source_spectrum.empty() ){
-
5686 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): A spectral distribution was not specified for source " + source.source_spectrum_label + ". Cannot perform camera calibration.");
-
5687 }
-
5688 sourcelabels.at(isource) = source.source_spectrum_label;
-
5689 isource++;
-
5690 }
-
5691
- -
5693 RadiationModel::runBand(bandlabels);
-
5694 // Update camera responses
-
5695 RadiationModel::updateCameraResponse(originalcameralabel, sourcelabels, cameraresplabels_raw, wavelengthrange, truevalues, calibratedmark);
-
5696
-
5697 float camerascale = RadiationModel::getCameraResponseScale(originalcameralabel, cameraresplabels_cal, bandlabels,sourcelabels, wavelengthrange, truevalues);
-
5698
-
5699 std::cout << "Camera response scale: " << camerascale << std::endl;
-
5700 // Scale and write calibrated camera responses
-
5701 cameracalibration->writeCalibratedCameraResponses(cameraresplabels_raw, calibratedmark, camerascale*scalefactor);
-
5702
-
5703}
+
5674 std::cout << "Camera response scale: " << camerascale << std::endl;
+
5675 // Scale and write calibrated camera responses
+
5676 cameracalibration->writeCalibratedCameraResponses(cameraresplabels_raw, calibratedmark, camerascale*scalefactor);
+
5677
+
5678}
-
5704
-
5705std::vector<helios::vec2> RadiationModel::generateGaussianCameraResponse(float FWHM, float mu, float centrawavelength, const helios::int2 &wavebanrange){
-
5706
-
5707 // Convert FWHM to sigma
-
5708 float sigma = FWHM / (2 * std::sqrt(2 * std::log(2)));
-
5709
-
5710 size_t lenspectra = wavebanrange.y - wavebanrange.x;
-
5711 std::vector<helios::vec2> cameraresponse(lenspectra);
+
5679
+
+
5680void RadiationModel::calibrateCamera(const std::string &originalcameralabel, const float scalefactor, const std::vector<std::vector<float>> &truevalues,
+
5681 const std::string &calibratedmark) {
+
5682
+
5683 if( cameras.find(originalcameralabel) == cameras.end() ){
+
5684 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): Camera " + originalcameralabel + " does not exist.");
+
5685 }else if( radiation_sources.empty() ){
+
5686 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): No radiation sources were added to the radiation model. Cannot perform calibration.");
+
5687 }
+
5688
+
5689 CameraCalibration cameracalibration_(context);
+
5690 if (!calibration_flag){
+
5691 std::cout<< "No color board added, use default color calibration." <<std::endl;
+
5692 vec3 centrelocation =make_vec3(0,0,0.2); // Location of color board
+
5693 vec3 rotationrad =make_vec3(0,0,1.5705); // Rotation angle of color board
+
5694 cameracalibration_.addDefaultColorboard(centrelocation, 0.1, rotationrad);
+
5695 RadiationModel::setCameraCalibration(&cameracalibration_);
+
5696 }
+
5697
+
5698 vec2 wavelengthrange = make_vec2(-10000,10000);
+
5699
+
5700 std::vector<std::string> bandlabels = cameras.at(originalcameralabel).band_labels;
+
5701
+
5702 // Get camera response spectra labels from camera
+
5703 std::vector<std::string> cameraresplabels_cal(cameras.at(originalcameralabel).band_spectral_response.size() );
+
5704 std::vector<std::string> cameraresplabels_raw = cameraresplabels_cal;
+
5705
+
5706 int iband = 0;
+
5707 for( auto &band : cameras.at(originalcameralabel).band_spectral_response ){
+
5708 cameraresplabels_raw.at(iband) = band.second;
+
5709 cameraresplabels_cal.at(iband) = calibratedmark + "_" + band.second;
+
5710 iband++;
+
5711 }
5712
-
5713
-
5714 for (int i = 0; i < lenspectra; ++i) {
-
5715 cameraresponse.at(i).x = float(wavebanrange.x + i);
-
5716 }
-
5717
-
5718 // Gaussian function
-
5719 for (size_t i = 0; i < lenspectra; ++i) {
-
5720 cameraresponse.at(i).y = centrawavelength * std::exp(-std::pow((cameraresponse.at(i).x - mu), 2) / (2 * std::pow(sigma, 2)));
-
5721 }
-
5722
+
5713 // Get labels of radiation sources from camera
+
5714 std::vector<std::string> sourcelabels(radiation_sources.size());
+
5715 int isource = 0;
+
5716 for( auto &source : radiation_sources ){
+
5717 if( source.source_spectrum.empty() ){
+
5718 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): A spectral distribution was not specified for source " + source.source_spectrum_label + ". Cannot perform camera calibration.");
+
5719 }
+
5720 sourcelabels.at(isource) = source.source_spectrum_label;
+
5721 isource++;
+
5722 }
5723
-
5724 return cameraresponse;
-
5725}
-
5726
-
-
5727bool validateOutputPath(std::ostringstream &output_directory){
+ +
5725 RadiationModel::runBand(bandlabels);
+
5726 // Update camera responses
+
5727 RadiationModel::updateCameraResponse(originalcameralabel, sourcelabels, cameraresplabels_raw, wavelengthrange, truevalues, calibratedmark);
5728
-
5729 // Make sure directory has a trailing slash
-
5730 if( output_directory.str().find_last_of('/')!=output_directory.str().length()-1 ) {
-
5731 output_directory << "/";
-
5732 }
-
5733
-
5734 // Create the output directory if it does not exist
-
5735 if( !std::filesystem::exists(output_directory.str()) ){
-
5736 if( !std::filesystem::create_directory(output_directory.str()) ){
-
5737 return false;
-
5738 }
-
5739 }
-
5740
-
5741 return true;
-
5742
-
5743}
+
5729 float camerascale = RadiationModel::getCameraResponseScale(originalcameralabel, cameraresplabels_cal, bandlabels,sourcelabels, wavelengthrange, truevalues);
+
5730
+
5731 std::cout << "Camera response scale: " << camerascale << std::endl;
+
5732 // Scale and write calibrated camera responses
+
5733 cameracalibration->writeCalibratedCameraResponses(cameraresplabels_raw, calibratedmark, camerascale*scalefactor);
+
5734
+
5735}
+
5736
+
5737std::vector<helios::vec2> RadiationModel::generateGaussianCameraResponse(float FWHM, float mu, float centrawavelength, const helios::int2 &wavebanrange){
+
5738
+
5739 // Convert FWHM to sigma
+
5740 float sigma = FWHM / (2 * std::sqrt(2 * std::log(2)));
+
5741
+
5742 size_t lenspectra = wavebanrange.y - wavebanrange.x;
+
5743 std::vector<helios::vec2> cameraresponse(lenspectra);
5744
-
5745void sutilHandleError(RTcontext context, RTresult code, const char* file, int line)
-
5746{
-
5747 const char* message;
-
5748 char s[2048];
-
5749 rtContextGetErrorString(context, code, &message);
-
5750 sprintf(s, "%s\n(%s:%d)", message, file, line);
-
5751 sutilReportError( s );
-
5752 exit(1);
-
5753}
+
5745
+
5746 for (int i = 0; i < lenspectra; ++i) {
+
5747 cameraresponse.at(i).x = float(wavebanrange.x + i);
+
5748 }
+
5749
+
5750 // Gaussian function
+
5751 for (size_t i = 0; i < lenspectra; ++i) {
+
5752 cameraresponse.at(i).y = centrawavelength * std::exp(-std::pow((cameraresponse.at(i).x - mu), 2) / (2 * std::pow(sigma, 2)));
+
5753 }
5754
-
5755void sutilReportError(const char* message)
-
5756{
-
5757 fprintf( stderr, "OptiX Error: %s\n", message );
-
5758#if defined(_WIN32) && defined(RELEASE_PUBLIC)
-
5759 {
-
5760 char s[2048];
-
5761 sprintf( s, "OptiX Error: %s", message );
-
5762 MessageBox( 0, s, "OptiX Error", MB_OK|MB_ICONWARNING|MB_SYSTEMMODAL );
-
5763 }
-
5764#endif
-
5765}
+
5755
+
5756 return cameraresponse;
+
5757}
+
5758
+
5759void sutilHandleError(RTcontext context, RTresult code, const char* file, int line)
+
5760{
+
5761 const char* message;
+
5762 char s[2048];
+
5763 rtContextGetErrorString(context, code, &message);
+
5764 sprintf(s, "%s\n(%s:%d)", message, file, line);
+
5765 sutilReportError( s );
+
5766 exit(1);
+
5767}
+
5768
+
5769void sutilReportError(const char* message)
+
5770{
+
5771 fprintf( stderr, "OptiX Error: %s\n", message );
+
5772#if defined(_WIN32) && defined(RELEASE_PUBLIC)
+
5773 {
+
5774 char s[2048];
+
5775 sprintf( s, "OptiX Error: %s", message );
+
5776 MessageBox( 0, s, "OptiX Error", MB_OK|MB_ICONWARNING|MB_SYSTEMMODAL );
+
5777 }
+
5778#endif
+
5779}
HeliosDataType
Data types.
Definition Context.h:41
@ HELIOS_TYPE_DOUBLE
double data type
Definition Context.h:49
@ HELIOS_TYPE_VEC2
helios::vec2 data type
Definition Context.h:51
@@ -6064,13 +6076,11 @@
@ PRIMITIVE_TYPE_VOXEL
Rectangular prism primitive.
Definition Context.h:37
@ PRIMITIVE_TYPE_TRIANGLE
< Triangular primitive
Definition Context.h:35
@ OBJECT_TYPE_TILE
< Tile
Definition Context.h:130
-
bool validateOutputPath(std::ostringstream &output_directory)
Validates the file path for output file writing by 1) making sure the directory string has a trailing...
-
bool validateOutputPath(std::ostringstream &output_directory)
Validates the file path for output file writing by 1) making sure the directory string has a trailing...
helios::SphericalCoord getCameraOrientation(const std::string &camera_label) const
Get the orientation of the radiation camera based on a spherical coordinate.
void setSourceSpectrumIntegral(uint source_ID, float source_integral)
Set the integral of the source spectral flux distribution across all possible wavelengths (=∫Sdλ)
void deleteRadiationSource(uint sourceID)
Delete an existing radiation source (any type)
-
float calculateGtheta(helios::Context *context, helios::vec3 view_direction)
Calculate G(theta) (i.e., projected area fraction) for a group of primitives given a certain viewing ...
+
float calculateGtheta(helios::Context *context, helios::vec3 view_direction)
Calculate G(theta) (i.e., projected area fraction) for a group of primitives given a certain viewing ...
void disableMessages()
Disable/silence status messages.
void setCameraSpectralResponse(const std::string &camera_label, const std::string &band_label, const std::string &global_data)
Set the spectral response of a camera band based on reference to global data. This function version u...
void setSourceFlux(uint source_ID, const std::string &band_label, float flux)
Set the flux of radiation source for this band.
@@ -6084,36 +6094,36 @@
float integrateSpectrum(const std::vector< helios::vec2 > &object_spectrum, float wavelength1, float wavelength2) const
Integrate a spectral distribution between two wavelength bounds.
void setDirectRayCount(const std::string &label, size_t N)
Sets variable directRayCount, the number of rays to be used in direct radiation model.
void copyRadiationBand(const std::string &old_label, const std::string &new_label)
Copy a spectral radiation band based on a previously created band.
-
void writeCameraImageData(const std::string &camera, const std::string &band, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1)
Write camera data for one band to an ASCII text file.
-
void writeImageBoundingBoxes(const std::string &cameralabel, const std::string &primitive_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path="./", bool append_label_file=false, int frame=-1)
Write bounding boxes based on primitive data labels (Ultralytic's YOLO format). Primitive data must h...
+
void writeCameraImageData(const std::string &camera, const std::string &band, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1)
Write camera data for one band to an ASCII text file.
+
void writeImageBoundingBoxes(const std::string &cameralabel, const std::string &primitive_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path="./", bool append_label_file=false, int frame=-1)
Write bounding boxes based on primitive data labels (Ultralytic's YOLO format). Primitive data must h...
void enableLightModelVisualization()
Add a 3D model of the light source (rectangular, disk, and sphere) to the Context for visualization p...
-
std::vector< float > getTotalAbsorbedFlux()
Get the total absorbed radiation flux summed over all bands for each primitive.
-
void writeNormCameraImage(const std::string &camera, const std::vector< std::string > &bands, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1)
Write normalized camera data (maximum value is 1) for one or more bands to a JPEG image.
-
void writeNormDepthImage(const std::string &cameralabel, const std::string &imagefile_base, float max_depth, const std::string &image_path="./", int frame=-1)
Write depth image file, with grayscale normalized to the minimum and maximum depth values.
+
std::vector< float > getTotalAbsorbedFlux()
Get the total absorbed radiation flux summed over all bands for each primitive.
+
void writeNormCameraImage(const std::string &camera, const std::vector< std::string > &bands, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1)
Write normalized camera data (maximum value is 1) for one or more bands to a JPEG image.
+
void writeNormDepthImage(const std::string &cameralabel, const std::string &imagefile_base, float max_depth, const std::string &image_path="./", int frame=-1)
Write depth image file, with grayscale normalized to the minimum and maximum depth values.
helios::vec3 getCameraPosition(const std::string &camera_label) const
Get the position of the radiation camera.
void setMinScatterEnergy(const std::string &label, uint energy)
Set the energy threshold used to terminate scattering iterations. Scattering iterations are terminate...
helios::vec3 getCameraLookat(const std::string &camera_label) const
Get the position the radiation camera is pointed toward (used to calculate camera orientation)
void disableCameraModelVisualization()
Remove the 3D model of the camera from the Context.
void setDiffuseSpectrumIntegral(float spectrum_integral)
Set the integral of the diffuse spectral flux distribution across all possible wavelengths FOR ALL EX...
void setScatteringDepth(const std::string &label, uint depth)
Set the number of scattering iterations for a certain band.
-
void runRadiationImaging(const std::string &cameralabel, const std::vector< std::string > &sourcelabels, const std::vector< std::string > &bandlabels, const std::vector< std::string > &cameraresponselabels, helios::vec2 wavelengthrange, float fluxscale=1, float diffusefactor=0.0005, uint scatteringdepth=4)
Run radiation imaging simulation.
-
void setPadValue(const std::string &cameralabel, const std::vector< std::string > &bandlabels, const std::vector< float > &padvalues)
Set padding value for pixels do not have valid values.
+
void runRadiationImaging(const std::string &cameralabel, const std::vector< std::string > &sourcelabels, const std::vector< std::string > &bandlabels, const std::vector< std::string > &cameraresponselabels, helios::vec2 wavelengthrange, float fluxscale=1, float diffusefactor=0.0005, uint scatteringdepth=4)
Run radiation imaging simulation.
+
void setPadValue(const std::string &cameralabel, const std::vector< std::string > &bandlabels, const std::vector< float > &padvalues)
Set padding value for pixels do not have valid values.
void disableEmission(const std::string &label)
Disable emission calculations for all primitives in this band.
-
void writePrimitiveDataLabelMap(const std::string &cameralabel, const std::string &primitive_data_label, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1, float padvalue=NAN)
Write image pixel labels to text file based on primitive data. Primitive data must have type 'float',...
+
void writePrimitiveDataLabelMap(const std::string &cameralabel, const std::string &primitive_data_label, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1, float padvalue=NAN)
Write image pixel labels to text file based on primitive data. Primitive data must have type 'float',...
void setSourceSpectrum(uint source_ID, const std::vector< helios::vec2 > &spectrum)
Set the spectral distribution of a radiation source according to a vector of wavelength-intensity pai...
void enableEmission(const std::string &label)
Enable emission calculations for all primitives in this band.
-
void runBand(const std::string &label)
Run the simulation for a single radiative band.
+
void runBand(const std::string &label)
Run the simulation for a single radiative band.
void setCameraLookat(const std::string &camera_label, const helios::vec3 &lookat)
Set the position the radiation camera is pointed toward (used to calculate camera orientation)
uint addSunSphereRadiationSource()
Add a sphere radiation source that models the sun assuming the default direction of (0,...
uint addDiskRadiationSource(const helios::vec3 &position, float radius, const helios::vec3 &rotation)
Add planar circular radiation source.
bool doesBandExist(const std::string &label) const
Check if a radiation band exists based on its label.
-
float getSkyEnergy()
Get the radiative energy lost to the sky (surroundings)
+
float getSkyEnergy()
Get the radiative energy lost to the sky (surroundings)
float getSourceFlux(uint source_ID, const std::string &band_label) const
Get the flux of radiation source for this band.
void setCameraPosition(const std::string &camera_label, const helios::vec3 &position)
Set the position of the radiation camera.
void setSourcePosition(uint source_ID, const helios::vec3 &position)
Set the position/direction of radiation source based on a Cartesian vector.
void writeCameraImage(const std::string &camera, const std::vector< std::string > &bands, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1, float flux_to_pixel_conversion=1.f)
Write camera data for one or more bands to a JPEG image.
void setDiffuseRadiationFlux(const std::string &label, float flux)
Diffuse (ambient) radiation flux.
-
void calibrateCamera(const std::string &orginalcameralabel, const std::vector< std::string > &sourcelabels, const std::vector< std::string > &cameraresponselabels, const std::vector< std::string > &bandlabels, const float scalefactor, const std::vector< std::vector< float > > &truevalues, const std::string &calibratedmark)
Calibrate camera.
+
void calibrateCamera(const std::string &orginalcameralabel, const std::vector< std::string > &sourcelabels, const std::vector< std::string > &cameraresponselabels, const std::vector< std::string > &bandlabels, const float scalefactor, const std::vector< std::vector< float > > &truevalues, const std::string &calibratedmark)
Calibrate camera.
void setDiffuseRayCount(const std::string &label, size_t N)
Sets variable diffuseRayCount, the number of rays to be used in diffuse (ambient) radiation model.
helios::vec3 getSourcePosition(uint source_ID) const
Get the position/direction of radiation source.
uint addRectangleRadiationSource(const helios::vec3 &position, const helios::vec2 &size, const helios::vec3 &rotation)
Add planar rectangular radiation source.
@@ -6121,22 +6131,22 @@
void disableLightModelVisualization()
Remove the 3D model of the light source from the Context.
void scaleSpectrumRandomly(const std::string &existing_global_data_label, const std::string &new_global_data_label, float minimum_scale_factor, float maximum_scale_factor) const
Scale an entire spectrum by a random factor following a uniform distribution.
void optionalOutputPrimitiveData(const char *label)
Add optional output primitive data values to the Context.
-
void writeImageBoundingBoxes_ObjectData(const std::string &cameralabel, const std::string &object_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path="./", bool append_label_file=false, int frame=-1)
Write bounding boxes based on object data labels (Ultralytic's YOLO format). Object data must have ty...
+
void writeImageBoundingBoxes_ObjectData(const std::string &cameralabel, const std::string &object_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path="./", bool append_label_file=false, int frame=-1)
Write bounding boxes based on object data labels (Ultralytic's YOLO format). Object data must have ty...
void setDiffuseRadiationExtinctionCoeff(const std::string &label, float K, const helios::vec3 &peak_dir)
Extinction coefficient of diffuse ambient radiation.
-
void updateGeometry()
Adds all geometric primitives from the Context to OptiX.
+
void updateGeometry()
Adds all geometric primitives from the Context to OptiX.
RadiationModel(helios::Context *context)
Default constructor.
void addRadiationBand(const std::string &label)
Add a spectral radiation band to the model.
void enableCameraModelVisualization()
Add a 3D model of the camera to the Context for visualization purposes.
-
void writeDepthImageData(const std::string &cameralabel, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1)
Write depth image data to text file.
-
float getCameraResponseScale(const std::string &orginalcameralabel, const std::vector< std::string > &cameraresponselabels, const std::vector< std::string > &bandlabels, const std::vector< std::string > &sourcelabels, helios::vec2 &wavelengthrange, const std::vector< std::vector< float > > &truevalues)
Get the scale factor of the camera response for a given camera.
+
void writeDepthImageData(const std::string &cameralabel, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1)
Write depth image data to text file.
+
float getCameraResponseScale(const std::string &orginalcameralabel, const std::vector< std::string > &cameraresponselabels, const std::vector< std::string > &bandlabels, const std::vector< std::string > &sourcelabels, helios::vec2 &wavelengthrange, const std::vector< std::vector< float > > &truevalues)
Get the scale factor of the camera response for a given camera.
uint addCollimatedRadiationSource()
Add an external source of collimated radiation (i.e., source at infinite distance with parallel rays)...
~RadiationModel()
Destructor.
void addRadiationCamera(const std::string &camera_label, const std::vector< std::string > &band_label, const helios::vec3 &position, const helios::vec3 &lookat, const CameraProperties &camera_properties, uint antialiasing_samples)
Add a radiation camera sensor.
void setDiffuseSpectrum(const std::string &spectrum_label)
Set the spectral distribution of diffuse ambient radiation FOR ALL BANDS based on global data of wave...
float getDiffuseFlux(const std::string &band_label) const
Get the diffuse flux for a given band.
-
void updateCameraResponse(const std::string &orginalcameralabel, const std::vector< std::string > &sourcelabels_raw, const std::vector< std::string > &cameraresponselabels, helios::vec2 &wavelengthrange, const std::vector< std::vector< float > > &truevalues, const std::string &calibratedmark)
Update the camera response for a given camera based on color board.
+
void updateCameraResponse(const std::string &orginalcameralabel, const std::vector< std::string > &sourcelabels_raw, const std::vector< std::string > &cameraresponselabels, helios::vec2 &wavelengthrange, const std::vector< std::vector< float > > &truevalues, const std::string &calibratedmark)
Update the camera response for a given camera based on color board.
float integrateSourceSpectrum(uint source_ID, float wavelength1, float wavelength2) const
Integrate a source spectral distribution between two wavelength bounds.
-
void writeObjectDataLabelMap(const std::string &cameralabel, const std::string &object_data_label, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1, float padvalue=NAN)
Write image pixel labels to text file based on object data. Object data must have type 'float',...
+
void writeObjectDataLabelMap(const std::string &cameralabel, const std::string &object_data_label, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1, float padvalue=NAN)
Write image pixel labels to text file based on object data. Object data must have type 'float',...
helios::ObjectType getObjectType() const
Get an enumeration specifying the type of the object.
Definition Context.cpp:2227
void getTransformationMatrix(float(&T)[16]) const
Method to return the Affine transformation matrix of a Compound Object.
Definition Context.cpp:2483
Stores the state associated with simulation.
Definition Context.h:1882
@@ -6161,7 +6171,7 @@
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:6928
helios::vec3 getVoxelSize(uint UUID) const
Get the size of a voxel element.
Definition Context.cpp:1731
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
-
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...
+
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:2026
HeliosDataType getGlobalDataType(const char *label) const
Get the Helios data type of global data.
void getGlobalData(const char *label, int &data) const
Get global data value (scalar integer)
@@ -6182,6 +6192,8 @@
helios::int2 getSubdivisionCount() const
Get the number of sub-patch divisions of the tile.
Definition Context.cpp:3323
std::vector< helios::vec3 > getVertices() const
Get the Cartesian coordinates of each of the four corners of the tile object.
Definition Context.cpp:3332
float interp1(const std::vector< helios::vec2 > &points, float x)
Function to perform linear interpolation based on a vector of discrete (x,y) values.
Definition global.cpp:2940
+
bool validateOutputPath(std::string &output_directory, const std::vector< std::string > &allowable_file_extensions={})
Check whether output file and/or directory is valid. Add a trailing slash if it is a directory.
Definition global.cpp:3020
+
std::string getFileName(const std::string &filepath)
Parse a file string to get the filename including extension.
Definition global.cpp:3003
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
void writeJPEG(const std::string &filename, uint width, uint height, const std::vector< helios::RGBcolor > &pixel_data)
Function to write a JPEG image based on pixel data.
Definition global.cpp:1786
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:1861
diff --git a/doc/html/_radiation_model_8h.html b/doc/html/_radiation_model_8h.html index 72a1872a1..1aee9f562 100644 --- a/doc/html/_radiation_model_8h.html +++ b/doc/html/_radiation_model_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -158,9 +158,6 @@ - - - @@ -194,7 +191,7 @@

sutilHandleError( OptiX_Context, code, __FILE__, __LINE__ ); \
} while(0)
-

Definition at line 1669 of file RadiationModel.h.

+

Definition at line 1662 of file RadiationModel.h.

@@ -247,7 +244,7 @@

-

Definition at line 5745 of file RadiationModel.cpp.

+

Definition at line 5759 of file RadiationModel.cpp.

@@ -266,35 +263,7 @@

-

Definition at line 5755 of file RadiationModel.cpp.

- - - - -

◆ validateOutputPath()

- -
-
-

Functions

bool validateOutputPath (std::ostringstream &output_directory)
 Validates the file path for output file writing by 1) making sure the directory string has a trailing slash, 2) creating the output directory if it does not exist.
 
void sutilHandleError (RTcontext context, RTresult code, const char *file, int line)
 
void sutilReportError (const char *message)
- - - - - - -
bool validateOutputPath (std::ostringstream & output_directory)
-
- -

Validates the file path for output file writing by 1) making sure the directory string has a trailing slash, 2) creating the output directory if it does not exist.

-
Parameters
- - -
[in,out]output_directoryPath to the directory where output files will be written. If the directory does not exist, it will be created.
-
-
-
Returns
True if the output directory is valid, false otherwise.
- -

Definition at line 5727 of file RadiationModel.cpp.

+

Definition at line 5769 of file RadiationModel.cpp.

diff --git a/doc/html/_radiation_model_8h_source.html b/doc/html/_radiation_model_8h_source.html index a7ab75625..64a1c56aa 100644 --- a/doc/html/_radiation_model_8h_source.html +++ b/doc/html/_radiation_model_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -1035,31 +1035,27 @@
1655};
1656
+
1657void sutilHandleError(RTcontext context, RTresult code, const char* file, int line);
1658
-
1662bool validateOutputPath(std::ostringstream &output_directory);
-
1663
-
1664void sutilHandleError(RTcontext context, RTresult code, const char* file, int line);
-
1665
-
1666void sutilReportError(const char* message);
-
1667
-
1668/* assumes current scope has Context variable named 'OptiX_Context' */
-
1669#define RT_CHECK_ERROR( func ) \
-
1670 do { \
-
1671 RTresult code = func; \
-
1672 if( code != RT_SUCCESS ) \
-
1673 sutilHandleError( OptiX_Context, code, __FILE__, __LINE__ ); \
-
1674 } while(0)
-
1675
-
1676#endif
+
1659void sutilReportError(const char* message);
+
1660
+
1661/* assumes current scope has Context variable named 'OptiX_Context' */
+
1662#define RT_CHECK_ERROR( func ) \
+
1663 do { \
+
1664 RTresult code = func; \
+
1665 if( code != RT_SUCCESS ) \
+
1666 sutilHandleError( OptiX_Context, code, __FILE__, __LINE__ ); \
+
1667 } while(0)
+
1668
+
1669#endif
-
bool validateOutputPath(std::ostringstream &output_directory)
Validates the file path for output file writing by 1) making sure the directory string has a trailing...
RadiationSourceType
Possible types of radiation sources.
Radiation transport model plugin.
helios::SphericalCoord getCameraOrientation(const std::string &camera_label) const
Get the orientation of the radiation camera based on a spherical coordinate.
void setSourceSpectrumIntegral(uint source_ID, float source_integral)
Set the integral of the source spectral flux distribution across all possible wavelengths (=∫Sdλ)
void deleteRadiationSource(uint sourceID)
Delete an existing radiation source (any type)
-
float calculateGtheta(helios::Context *context, helios::vec3 view_direction)
Calculate G(theta) (i.e., projected area fraction) for a group of primitives given a certain viewing ...
+
float calculateGtheta(helios::Context *context, helios::vec3 view_direction)
Calculate G(theta) (i.e., projected area fraction) for a group of primitives given a certain viewing ...
void disableMessages()
Disable/silence status messages.
void setCameraSpectralResponse(const std::string &camera_label, const std::string &band_label, const std::string &global_data)
Set the spectral response of a camera band based on reference to global data. This function version u...
void setSourceFlux(uint source_ID, const std::string &band_label, float flux)
Set the flux of radiation source for this band.
@@ -1074,36 +1070,36 @@
void setDirectRayCount(const std::string &label, size_t N)
Sets variable directRayCount, the number of rays to be used in direct radiation model.
int selfTest()
Self-test.
Definition selfTest.cpp:20
void copyRadiationBand(const std::string &old_label, const std::string &new_label)
Copy a spectral radiation band based on a previously created band.
-
void writeCameraImageData(const std::string &camera, const std::string &band, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1)
Write camera data for one band to an ASCII text file.
-
void writeImageBoundingBoxes(const std::string &cameralabel, const std::string &primitive_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path="./", bool append_label_file=false, int frame=-1)
Write bounding boxes based on primitive data labels (Ultralytic's YOLO format). Primitive data must h...
+
void writeCameraImageData(const std::string &camera, const std::string &band, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1)
Write camera data for one band to an ASCII text file.
+
void writeImageBoundingBoxes(const std::string &cameralabel, const std::string &primitive_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path="./", bool append_label_file=false, int frame=-1)
Write bounding boxes based on primitive data labels (Ultralytic's YOLO format). Primitive data must h...
void enableLightModelVisualization()
Add a 3D model of the light source (rectangular, disk, and sphere) to the Context for visualization p...
-
std::vector< float > getTotalAbsorbedFlux()
Get the total absorbed radiation flux summed over all bands for each primitive.
-
void writeNormCameraImage(const std::string &camera, const std::vector< std::string > &bands, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1)
Write normalized camera data (maximum value is 1) for one or more bands to a JPEG image.
-
void writeNormDepthImage(const std::string &cameralabel, const std::string &imagefile_base, float max_depth, const std::string &image_path="./", int frame=-1)
Write depth image file, with grayscale normalized to the minimum and maximum depth values.
+
std::vector< float > getTotalAbsorbedFlux()
Get the total absorbed radiation flux summed over all bands for each primitive.
+
void writeNormCameraImage(const std::string &camera, const std::vector< std::string > &bands, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1)
Write normalized camera data (maximum value is 1) for one or more bands to a JPEG image.
+
void writeNormDepthImage(const std::string &cameralabel, const std::string &imagefile_base, float max_depth, const std::string &image_path="./", int frame=-1)
Write depth image file, with grayscale normalized to the minimum and maximum depth values.
helios::vec3 getCameraPosition(const std::string &camera_label) const
Get the position of the radiation camera.
void setMinScatterEnergy(const std::string &label, uint energy)
Set the energy threshold used to terminate scattering iterations. Scattering iterations are terminate...
helios::vec3 getCameraLookat(const std::string &camera_label) const
Get the position the radiation camera is pointed toward (used to calculate camera orientation)
void disableCameraModelVisualization()
Remove the 3D model of the camera from the Context.
void setDiffuseSpectrumIntegral(float spectrum_integral)
Set the integral of the diffuse spectral flux distribution across all possible wavelengths FOR ALL EX...
void setScatteringDepth(const std::string &label, uint depth)
Set the number of scattering iterations for a certain band.
-
void runRadiationImaging(const std::string &cameralabel, const std::vector< std::string > &sourcelabels, const std::vector< std::string > &bandlabels, const std::vector< std::string > &cameraresponselabels, helios::vec2 wavelengthrange, float fluxscale=1, float diffusefactor=0.0005, uint scatteringdepth=4)
Run radiation imaging simulation.
-
void setPadValue(const std::string &cameralabel, const std::vector< std::string > &bandlabels, const std::vector< float > &padvalues)
Set padding value for pixels do not have valid values.
+
void runRadiationImaging(const std::string &cameralabel, const std::vector< std::string > &sourcelabels, const std::vector< std::string > &bandlabels, const std::vector< std::string > &cameraresponselabels, helios::vec2 wavelengthrange, float fluxscale=1, float diffusefactor=0.0005, uint scatteringdepth=4)
Run radiation imaging simulation.
+
void setPadValue(const std::string &cameralabel, const std::vector< std::string > &bandlabels, const std::vector< float > &padvalues)
Set padding value for pixels do not have valid values.
void disableEmission(const std::string &label)
Disable emission calculations for all primitives in this band.
-
void writePrimitiveDataLabelMap(const std::string &cameralabel, const std::string &primitive_data_label, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1, float padvalue=NAN)
Write image pixel labels to text file based on primitive data. Primitive data must have type 'float',...
+
void writePrimitiveDataLabelMap(const std::string &cameralabel, const std::string &primitive_data_label, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1, float padvalue=NAN)
Write image pixel labels to text file based on primitive data. Primitive data must have type 'float',...
void setSourceSpectrum(uint source_ID, const std::vector< helios::vec2 > &spectrum)
Set the spectral distribution of a radiation source according to a vector of wavelength-intensity pai...
void enableEmission(const std::string &label)
Enable emission calculations for all primitives in this band.
-
void runBand(const std::string &label)
Run the simulation for a single radiative band.
+
void runBand(const std::string &label)
Run the simulation for a single radiative band.
void setCameraLookat(const std::string &camera_label, const helios::vec3 &lookat)
Set the position the radiation camera is pointed toward (used to calculate camera orientation)
uint addSunSphereRadiationSource()
Add a sphere radiation source that models the sun assuming the default direction of (0,...
uint addDiskRadiationSource(const helios::vec3 &position, float radius, const helios::vec3 &rotation)
Add planar circular radiation source.
bool doesBandExist(const std::string &label) const
Check if a radiation band exists based on its label.
-
float getSkyEnergy()
Get the radiative energy lost to the sky (surroundings)
+
float getSkyEnergy()
Get the radiative energy lost to the sky (surroundings)
float getSourceFlux(uint source_ID, const std::string &band_label) const
Get the flux of radiation source for this band.
void setCameraPosition(const std::string &camera_label, const helios::vec3 &position)
Set the position of the radiation camera.
void setSourcePosition(uint source_ID, const helios::vec3 &position)
Set the position/direction of radiation source based on a Cartesian vector.
void writeCameraImage(const std::string &camera, const std::vector< std::string > &bands, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1, float flux_to_pixel_conversion=1.f)
Write camera data for one or more bands to a JPEG image.
void setDiffuseRadiationFlux(const std::string &label, float flux)
Diffuse (ambient) radiation flux.
-
void calibrateCamera(const std::string &orginalcameralabel, const std::vector< std::string > &sourcelabels, const std::vector< std::string > &cameraresponselabels, const std::vector< std::string > &bandlabels, const float scalefactor, const std::vector< std::vector< float > > &truevalues, const std::string &calibratedmark)
Calibrate camera.
+
void calibrateCamera(const std::string &orginalcameralabel, const std::vector< std::string > &sourcelabels, const std::vector< std::string > &cameraresponselabels, const std::vector< std::string > &bandlabels, const float scalefactor, const std::vector< std::vector< float > > &truevalues, const std::string &calibratedmark)
Calibrate camera.
void setDiffuseRayCount(const std::string &label, size_t N)
Sets variable diffuseRayCount, the number of rays to be used in diffuse (ambient) radiation model.
helios::vec3 getSourcePosition(uint source_ID) const
Get the position/direction of radiation source.
uint addRectangleRadiationSource(const helios::vec3 &position, const helios::vec2 &size, const helios::vec3 &rotation)
Add planar rectangular radiation source.
@@ -1111,22 +1107,22 @@
void disableLightModelVisualization()
Remove the 3D model of the light source from the Context.
void scaleSpectrumRandomly(const std::string &existing_global_data_label, const std::string &new_global_data_label, float minimum_scale_factor, float maximum_scale_factor) const
Scale an entire spectrum by a random factor following a uniform distribution.
void optionalOutputPrimitiveData(const char *label)
Add optional output primitive data values to the Context.
-
void writeImageBoundingBoxes_ObjectData(const std::string &cameralabel, const std::string &object_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path="./", bool append_label_file=false, int frame=-1)
Write bounding boxes based on object data labels (Ultralytic's YOLO format). Object data must have ty...
+
void writeImageBoundingBoxes_ObjectData(const std::string &cameralabel, const std::string &object_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path="./", bool append_label_file=false, int frame=-1)
Write bounding boxes based on object data labels (Ultralytic's YOLO format). Object data must have ty...
void setDiffuseRadiationExtinctionCoeff(const std::string &label, float K, const helios::vec3 &peak_dir)
Extinction coefficient of diffuse ambient radiation.
-
void updateGeometry()
Adds all geometric primitives from the Context to OptiX.
+
void updateGeometry()
Adds all geometric primitives from the Context to OptiX.
RadiationModel(helios::Context *context)
Default constructor.
void addRadiationBand(const std::string &label)
Add a spectral radiation band to the model.
void enableCameraModelVisualization()
Add a 3D model of the camera to the Context for visualization purposes.
-
void writeDepthImageData(const std::string &cameralabel, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1)
Write depth image data to text file.
-
float getCameraResponseScale(const std::string &orginalcameralabel, const std::vector< std::string > &cameraresponselabels, const std::vector< std::string > &bandlabels, const std::vector< std::string > &sourcelabels, helios::vec2 &wavelengthrange, const std::vector< std::vector< float > > &truevalues)
Get the scale factor of the camera response for a given camera.
+
void writeDepthImageData(const std::string &cameralabel, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1)
Write depth image data to text file.
+
float getCameraResponseScale(const std::string &orginalcameralabel, const std::vector< std::string > &cameraresponselabels, const std::vector< std::string > &bandlabels, const std::vector< std::string > &sourcelabels, helios::vec2 &wavelengthrange, const std::vector< std::vector< float > > &truevalues)
Get the scale factor of the camera response for a given camera.
uint addCollimatedRadiationSource()
Add an external source of collimated radiation (i.e., source at infinite distance with parallel rays)...
~RadiationModel()
Destructor.
void addRadiationCamera(const std::string &camera_label, const std::vector< std::string > &band_label, const helios::vec3 &position, const helios::vec3 &lookat, const CameraProperties &camera_properties, uint antialiasing_samples)
Add a radiation camera sensor.
void setDiffuseSpectrum(const std::string &spectrum_label)
Set the spectral distribution of diffuse ambient radiation FOR ALL BANDS based on global data of wave...
float getDiffuseFlux(const std::string &band_label) const
Get the diffuse flux for a given band.
-
void updateCameraResponse(const std::string &orginalcameralabel, const std::vector< std::string > &sourcelabels_raw, const std::vector< std::string > &cameraresponselabels, helios::vec2 &wavelengthrange, const std::vector< std::vector< float > > &truevalues, const std::string &calibratedmark)
Update the camera response for a given camera based on color board.
+
void updateCameraResponse(const std::string &orginalcameralabel, const std::vector< std::string > &sourcelabels_raw, const std::vector< std::string > &cameraresponselabels, helios::vec2 &wavelengthrange, const std::vector< std::vector< float > > &truevalues, const std::string &calibratedmark)
Update the camera response for a given camera based on color board.
float integrateSourceSpectrum(uint source_ID, float wavelength1, float wavelength2) const
Integrate a source spectral distribution between two wavelength bounds.
-
void writeObjectDataLabelMap(const std::string &cameralabel, const std::string &object_data_label, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1, float padvalue=NAN)
Write image pixel labels to text file based on object data. Object data must have type 'float',...
+
void writeObjectDataLabelMap(const std::string &cameralabel, const std::string &object_data_label, const std::string &imagefile_base, const std::string &image_path="./", int frame=-1, float padvalue=NAN)
Write image pixel labels to text file based on object data. Object data must have type 'float',...
Stores the state associated with simulation.
Definition Context.h:1882
int2 make_int2(int x, int y)
Make an int2 vector from two ints.
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
diff --git a/doc/html/_ray_tracing_8cu_8h.html b/doc/html/_ray_tracing_8cu_8h.html index 37ce6b556..5146ee5cb 100644 --- a/doc/html/_ray_tracing_8cu_8h.html +++ b/doc/html/_ray_tracing_8cu_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_ray_tracing_8cu_8h_source.html b/doc/html/_ray_tracing_8cu_8h_source.html index 97619bad7..c2dabe059 100644 --- a/doc/html/_ray_tracing_8cu_8h_source.html +++ b/doc/html/_ray_tracing_8cu_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_solar_position_8cpp.html b/doc/html/_solar_position_8cpp.html index 60fa1611e..68028a2cb 100644 --- a/doc/html/_solar_position_8cpp.html +++ b/doc/html/_solar_position_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_solar_position_8cpp_source.html b/doc/html/_solar_position_8cpp_source.html index 1bac29231..19c829815 100644 --- a/doc/html/_solar_position_8cpp_source.html +++ b/doc/html/_solar_position_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_solar_position_8h.html b/doc/html/_solar_position_8h.html index b889ae232..b4b6902bc 100644 --- a/doc/html/_solar_position_8h.html +++ b/doc/html/_solar_position_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_solar_position_8h_source.html b/doc/html/_solar_position_8h_source.html index 69dead0da..38e1ef5b3 100644 --- a/doc/html/_solar_position_8h_source.html +++ b/doc/html/_solar_position_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_solar_position_doc.html b/doc/html/_solar_position_doc.html index da4ea0927..9a9f26fa2 100644 --- a/doc/html/_solar_position_doc.html +++ b/doc/html/_solar_position_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_stomatal_conductance_model_8cpp.html b/doc/html/_stomatal_conductance_model_8cpp.html index b51c1018b..a347d36f3 100644 --- a/doc/html/_stomatal_conductance_model_8cpp.html +++ b/doc/html/_stomatal_conductance_model_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_stomatal_conductance_model_8cpp_source.html b/doc/html/_stomatal_conductance_model_8cpp_source.html index ab603068f..2fb00577b 100644 --- a/doc/html/_stomatal_conductance_model_8cpp_source.html +++ b/doc/html/_stomatal_conductance_model_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_stomatal_conductance_model_8h.html b/doc/html/_stomatal_conductance_model_8h.html index a76a83392..5b6210035 100644 --- a/doc/html/_stomatal_conductance_model_8h.html +++ b/doc/html/_stomatal_conductance_model_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_stomatal_conductance_model_8h_source.html b/doc/html/_stomatal_conductance_model_8h_source.html index 58299a66a..e3fb27821 100644 --- a/doc/html/_stomatal_conductance_model_8h_source.html +++ b/doc/html/_stomatal_conductance_model_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_stomatal_doc.html b/doc/html/_stomatal_doc.html index 5c2283baf..05d1f9e9e 100644 --- a/doc/html/_stomatal_doc.html +++ b/doc/html/_stomatal_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_synthetic_annotation_8cpp.html b/doc/html/_synthetic_annotation_8cpp.html index 96bdc6807..9f6f290d2 100644 --- a/doc/html/_synthetic_annotation_8cpp.html +++ b/doc/html/_synthetic_annotation_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_synthetic_annotation_8cpp_source.html b/doc/html/_synthetic_annotation_8cpp_source.html index 0762b479d..84c5839b4 100644 --- a/doc/html/_synthetic_annotation_8cpp_source.html +++ b/doc/html/_synthetic_annotation_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_synthetic_annotation_8h.html b/doc/html/_synthetic_annotation_8h.html index c6bd535e2..28014dbb5 100644 --- a/doc/html/_synthetic_annotation_8h.html +++ b/doc/html/_synthetic_annotation_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_synthetic_annotation_8h_source.html b/doc/html/_synthetic_annotation_8h_source.html index 509b1ea7a..6ca0e1e6b 100644 --- a/doc/html/_synthetic_annotation_8h_source.html +++ b/doc/html/_synthetic_annotation_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_tutorials.html b/doc/html/_tutorials.html index ead5d7567..176ebc797 100644 --- a/doc/html/_tutorials.html +++ b/doc/html/_tutorials.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_visualizer_8cpp.html b/doc/html/_visualizer_8cpp.html index 3d91e2ca5..0540ec087 100644 --- a/doc/html/_visualizer_8cpp.html +++ b/doc/html/_visualizer_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_visualizer_8cpp_source.html b/doc/html/_visualizer_8cpp_source.html index a3e90b700..4b026b88b 100644 --- a/doc/html/_visualizer_8cpp_source.html +++ b/doc/html/_visualizer_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_visualizer_8h.html b/doc/html/_visualizer_8h.html index 6b0f9783b..b04aab32b 100644 --- a/doc/html/_visualizer_8h.html +++ b/doc/html/_visualizer_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_visualizer_8h_source.html b/doc/html/_visualizer_8h_source.html index b17efa671..ff5922d57 100644 --- a/doc/html/_visualizer_8h_source.html +++ b/doc/html/_visualizer_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_visualizer_doc.html b/doc/html/_visualizer_doc.html index ce9f3fcc0..00c394668 100644 --- a/doc/html/_visualizer_doc.html +++ b/doc/html/_visualizer_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_voxel_intersection_8cpp.html b/doc/html/_voxel_intersection_8cpp.html index 2a407fad1..160da056a 100644 --- a/doc/html/_voxel_intersection_8cpp.html +++ b/doc/html/_voxel_intersection_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_voxel_intersection_8cpp_source.html b/doc/html/_voxel_intersection_8cpp_source.html index faf6c3edd..4868469c6 100644 --- a/doc/html/_voxel_intersection_8cpp_source.html +++ b/doc/html/_voxel_intersection_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_voxel_intersection_8cu.html b/doc/html/_voxel_intersection_8cu.html index af9f2b507..530d113a1 100644 --- a/doc/html/_voxel_intersection_8cu.html +++ b/doc/html/_voxel_intersection_8cu.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_voxel_intersection_8cu_source.html b/doc/html/_voxel_intersection_8cu_source.html index ba8d4268e..308c023d5 100644 --- a/doc/html/_voxel_intersection_8cu_source.html +++ b/doc/html/_voxel_intersection_8cu_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_voxel_intersection_8h.html b/doc/html/_voxel_intersection_8h.html index c8447c853..463397198 100644 --- a/doc/html/_voxel_intersection_8h.html +++ b/doc/html/_voxel_intersection_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_voxel_intersection_8h_source.html b/doc/html/_voxel_intersection_8h_source.html index 01dce7592..15be3bb38 100644 --- a/doc/html/_voxel_intersection_8h_source.html +++ b/doc/html/_voxel_intersection_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_voxel_intersection_doc.html b/doc/html/_voxel_intersection_doc.html index 922599274..698bae1a1 100644 --- a/doc/html/_voxel_intersection_doc.html +++ b/doc/html/_voxel_intersection_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_weber_penn_doc.html b/doc/html/_weber_penn_doc.html index 3917f308f..15bab3375 100644 --- a/doc/html/_weber_penn_doc.html +++ b/doc/html/_weber_penn_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_weber_penn_tree_8cpp.html b/doc/html/_weber_penn_tree_8cpp.html index ac634156a..40bd75187 100644 --- a/doc/html/_weber_penn_tree_8cpp.html +++ b/doc/html/_weber_penn_tree_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_weber_penn_tree_8cpp_source.html b/doc/html/_weber_penn_tree_8cpp_source.html index ab61d4379..5ca50bed7 100644 --- a/doc/html/_weber_penn_tree_8cpp_source.html +++ b/doc/html/_weber_penn_tree_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_weber_penn_tree_8h.html b/doc/html/_weber_penn_tree_8h.html index 3d0e9684e..c5b12401a 100644 --- a/doc/html/_weber_penn_tree_8h.html +++ b/doc/html/_weber_penn_tree_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/_weber_penn_tree_8h_source.html b/doc/html/_weber_penn_tree_8h_source.html index d779615fb..ef02ea674 100644 --- a/doc/html/_weber_penn_tree_8h_source.html +++ b/doc/html/_weber_penn_tree_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/aeriallidar_2include_2random_8h_source.html b/doc/html/aeriallidar_2include_2random_8h_source.html index 8eb4b1b22..5ccfa4e3b 100644 --- a/doc/html/aeriallidar_2include_2random_8h_source.html +++ b/doc/html/aeriallidar_2include_2random_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/aeriallidar_2src_2file_i_o_8cpp.html b/doc/html/aeriallidar_2src_2file_i_o_8cpp.html index 10dce3d30..42e5f1162 100644 --- a/doc/html/aeriallidar_2src_2file_i_o_8cpp.html +++ b/doc/html/aeriallidar_2src_2file_i_o_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/aeriallidar_2src_2file_i_o_8cpp_source.html b/doc/html/aeriallidar_2src_2file_i_o_8cpp_source.html index 4a914cdd1..8c78fddd3 100644 --- a/doc/html/aeriallidar_2src_2file_i_o_8cpp_source.html +++ b/doc/html/aeriallidar_2src_2file_i_o_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/annotated.html b/doc/html/annotated.html index 755e9e567..2014b7faf 100644 --- a/doc/html/annotated.html +++ b/doc/html/annotated.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/bean_8cpp_source.html b/doc/html/bean_8cpp_source.html index cfc447eb5..934f96c95 100644 --- a/doc/html/bean_8cpp_source.html +++ b/doc/html/bean_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_aerial_li_d_a_rcloud.html b/doc/html/class_aerial_li_d_a_rcloud.html index 6df667f6a..82a38a3b6 100644 --- a/doc/html/class_aerial_li_d_a_rcloud.html +++ b/doc/html/class_aerial_li_d_a_rcloud.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_b_l_conductance_model.html b/doc/html/class_b_l_conductance_model.html index f1d8463c1..072b6e7aa 100644 --- a/doc/html/class_b_l_conductance_model.html +++ b/doc/html/class_b_l_conductance_model.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_canopy_generator.html b/doc/html/class_canopy_generator.html index 27c1e6dd6..38b506a7d 100644 --- a/doc/html/class_canopy_generator.html +++ b/doc/html/class_canopy_generator.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_dummy_model.html b/doc/html/class_dummy_model.html index 755e20e23..f9542b17b 100644 --- a/doc/html/class_dummy_model.html +++ b/doc/html/class_dummy_model.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_energy_balance_model.html b/doc/html/class_energy_balance_model.html index 4c18c8ade..f55ed01d0 100644 --- a/doc/html/class_energy_balance_model.html +++ b/doc/html/class_energy_balance_model.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_glyph.html b/doc/html/class_glyph.html index 5a517f8e8..994cd669b 100644 --- a/doc/html/class_glyph.html +++ b/doc/html/class_glyph.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_hit_table.html b/doc/html/class_hit_table.html index ab229175f..e1ecc017e 100644 --- a/doc/html/class_hit_table.html +++ b/doc/html/class_hit_table.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_leaf_optics.html b/doc/html/class_leaf_optics.html index 673572db9..17eb88e0a 100644 --- a/doc/html/class_leaf_optics.html +++ b/doc/html/class_leaf_optics.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_li_d_a_rcloud.html b/doc/html/class_li_d_a_rcloud.html index 8d9b33660..4165e2456 100644 --- a/doc/html/class_li_d_a_rcloud.html +++ b/doc/html/class_li_d_a_rcloud.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_photosynthesis_model.html b/doc/html/class_photosynthesis_model.html index ea47f054e..fa8ce3e28 100644 --- a/doc/html/class_photosynthesis_model.html +++ b/doc/html/class_photosynthesis_model.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_plant_architecture.html b/doc/html/class_plant_architecture.html index 1ae4f8380..4d7dcd782 100644 --- a/doc/html/class_plant_architecture.html +++ b/doc/html/class_plant_architecture.html @@ -38,7 +38,7 @@ Logo -
@@ -478,7 +478,7 @@

Returns
ID of the newly generated shoot.
-

Definition at line 1976 of file PlantArchitecture.cpp.

+

Definition at line 1977 of file PlantArchitecture.cpp.

@@ -565,7 +565,7 @@

Returns
ID of the newly generated shoot.
-

Definition at line 2020 of file PlantArchitecture.cpp.

+

Definition at line 2021 of file PlantArchitecture.cpp.

@@ -598,7 +598,7 @@

Returns
ID of the plant instance.
-

Definition at line 2568 of file PlantArchitecture.cpp.

+

Definition at line 2569 of file PlantArchitecture.cpp.

@@ -625,7 +625,7 @@

Definition at line 2682 of file PlantArchitecture.cpp.

+

Definition at line 2683 of file PlantArchitecture.cpp.

@@ -657,7 +657,7 @@

Definition at line 2694 of file PlantArchitecture.cpp.

+

Definition at line 2695 of file PlantArchitecture.cpp.

@@ -720,7 +720,7 @@

Returns
ID of generated phytomer
-

Definition at line 2058 of file PlantArchitecture.cpp.

+

Definition at line 2059 of file PlantArchitecture.cpp.

@@ -801,7 +801,7 @@

Returns
ID of the new shoot to be used to reference it later.
-

Definition at line 1931 of file PlantArchitecture.cpp.

+

Definition at line 1932 of file PlantArchitecture.cpp.

@@ -820,7 +820,7 @@

-

Definition at line 2354 of file PlantArchitecture.cpp.

+

Definition at line 2355 of file PlantArchitecture.cpp.

@@ -957,7 +957,7 @@

Definition at line 2649 of file PlantArchitecture.cpp.

+

Definition at line 2650 of file PlantArchitecture.cpp.

@@ -984,7 +984,7 @@

Definition at line 2637 of file PlantArchitecture.cpp.

+

Definition at line 2638 of file PlantArchitecture.cpp.

@@ -1005,7 +1005,7 @@

Definition at line 2121 of file PlantArchitecture.cpp.

+

Definition at line 2122 of file PlantArchitecture.cpp.

@@ -1026,7 +1026,7 @@

Definition at line 2129 of file PlantArchitecture.cpp.

+

Definition at line 2130 of file PlantArchitecture.cpp.

@@ -1047,7 +1047,7 @@

Definition at line 2125 of file PlantArchitecture.cpp.

+

Definition at line 2126 of file PlantArchitecture.cpp.

@@ -1066,7 +1066,7 @@

-

Definition at line 2673 of file PlantArchitecture.cpp.

+

Definition at line 2674 of file PlantArchitecture.cpp.

@@ -1110,7 +1110,7 @@

Returns
ID of the new plant instance.
-

Definition at line 2584 of file PlantArchitecture.cpp.

+

Definition at line 2585 of file PlantArchitecture.cpp.

@@ -1149,7 +1149,7 @@

Definition at line 2107 of file PlantArchitecture.cpp.

+

Definition at line 2108 of file PlantArchitecture.cpp.

@@ -1176,7 +1176,7 @@

Definition at line 2133 of file PlantArchitecture.cpp.

+

Definition at line 2134 of file PlantArchitecture.cpp.

@@ -1250,7 +1250,7 @@

Returns
Vector of object IDs for all organs in the plant.
-

Definition at line 2396 of file PlantArchitecture.cpp.

+

Definition at line 2397 of file PlantArchitecture.cpp.

@@ -1278,7 +1278,7 @@

Returns
Vector of primitive UUIDs for all primitives in the plant.
-

Definition at line 2426 of file PlantArchitecture.cpp.

+

Definition at line 2427 of file PlantArchitecture.cpp.

@@ -1347,7 +1347,7 @@

-

Definition at line 2284 of file PlantArchitecture.cpp.

+

Definition at line 2285 of file PlantArchitecture.cpp.

@@ -1366,7 +1366,7 @@

-

Definition at line 2254 of file PlantArchitecture.cpp.

+

Definition at line 2255 of file PlantArchitecture.cpp.

@@ -1394,7 +1394,7 @@

Returns
Vector of object IDs for all inflorescences in the plant.
-

Definition at line 2514 of file PlantArchitecture.cpp.

+

Definition at line 2515 of file PlantArchitecture.cpp.

@@ -1422,7 +1422,7 @@

Returns
Vector of object IDs for all fruits in the plant.
-

Definition at line 2541 of file PlantArchitecture.cpp.

+

Definition at line 2542 of file PlantArchitecture.cpp.

@@ -1450,7 +1450,7 @@

Returns
Vector of object IDs for all internodes in the plant.
-

Definition at line 2430 of file PlantArchitecture.cpp.

+

Definition at line 2431 of file PlantArchitecture.cpp.

@@ -1478,7 +1478,7 @@

Returns
Vector of object IDs for all leaves in the plant.
-

Definition at line 2469 of file PlantArchitecture.cpp.

+

Definition at line 2470 of file PlantArchitecture.cpp.

@@ -1506,7 +1506,7 @@

Returns
Vector of object IDs for all peduncles in the plant.
-

Definition at line 2490 of file PlantArchitecture.cpp.

+

Definition at line 2491 of file PlantArchitecture.cpp.

@@ -1534,7 +1534,7 @@

Returns
Vector of object IDs for all petioles in the plant.
-

Definition at line 2448 of file PlantArchitecture.cpp.

+

Definition at line 2449 of file PlantArchitecture.cpp.

@@ -1576,7 +1576,7 @@

-

Definition at line 2365 of file PlantArchitecture.cpp.

+

Definition at line 2366 of file PlantArchitecture.cpp.

@@ -1599,7 +1599,7 @@

-

Definition at line 2374 of file PlantArchitecture.cpp.

+

Definition at line 2375 of file PlantArchitecture.cpp.

@@ -1618,7 +1618,7 @@

-

Definition at line 2293 of file PlantArchitecture.cpp.

+

Definition at line 2294 of file PlantArchitecture.cpp.

@@ -1651,7 +1651,7 @@

-

Definition at line 2181 of file PlantArchitecture.cpp.

+

Definition at line 2182 of file PlantArchitecture.cpp.

@@ -1748,7 +1748,7 @@

-

Definition at line 2344 of file PlantArchitecture.cpp.

+

Definition at line 2345 of file PlantArchitecture.cpp.

@@ -1775,7 +1775,7 @@

Definition at line 3108 of file PlantArchitecture.cpp.

+

Definition at line 3109 of file PlantArchitecture.cpp.

@@ -1802,7 +1802,7 @@

Definition at line 3116 of file PlantArchitecture.cpp.

+

Definition at line 3117 of file PlantArchitecture.cpp.

@@ -1825,7 +1825,7 @@

-

Definition at line 514 of file InputOutput.cpp.

+

Definition at line 519 of file InputOutput.cpp.

@@ -1844,7 +1844,7 @@

-

Definition at line 2332 of file PlantArchitecture.cpp.

+

Definition at line 2333 of file PlantArchitecture.cpp.

@@ -1867,7 +1867,7 @@

-

Definition at line 2315 of file PlantArchitecture.cpp.

+

Definition at line 2316 of file PlantArchitecture.cpp.

@@ -1929,7 +1929,7 @@

-

Definition at line 2217 of file PlantArchitecture.cpp.

+

Definition at line 2218 of file PlantArchitecture.cpp.

@@ -1952,7 +1952,7 @@

-

Definition at line 2279 of file PlantArchitecture.cpp.

+

Definition at line 2280 of file PlantArchitecture.cpp.

@@ -1975,7 +1975,7 @@

-

Definition at line 2239 of file PlantArchitecture.cpp.

+

Definition at line 2240 of file PlantArchitecture.cpp.

@@ -2044,7 +2044,7 @@

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 2657 of file PlantArchitecture.cpp.

+

Definition at line 2658 of file PlantArchitecture.cpp.

@@ -2072,7 +2072,7 @@

Returns
Total one-sided leaf area of all leaves in the plant.
-

Definition at line 2263 of file PlantArchitecture.cpp.

+

Definition at line 2264 of file PlantArchitecture.cpp.

diff --git a/doc/html/class_radiation_model.html b/doc/html/class_radiation_model.html index a09a9da4e..0f42fd0b9 100644 --- a/doc/html/class_radiation_model.html +++ b/doc/html/class_radiation_model.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -1013,7 +1013,7 @@

Returns
Projected area fraction G(theta)
-

Definition at line 4820 of file RadiationModel.cpp.

+

Definition at line 4828 of file RadiationModel.cpp.

@@ -1076,7 +1076,7 @@

Definition at line 5609 of file RadiationModel.cpp.

+

Definition at line 5641 of file RadiationModel.cpp.

@@ -1121,7 +1121,7 @@

Definition at line 5648 of file RadiationModel.cpp.

+

Definition at line 5680 of file RadiationModel.cpp.

@@ -1623,7 +1623,7 @@

Returns
scale factor
-

Definition at line 5051 of file RadiationModel.cpp.

+

Definition at line 5059 of file RadiationModel.cpp.

@@ -1672,7 +1672,7 @@

Definition at line 3709 of file RadiationModel.cpp.

+

Definition at line 3717 of file RadiationModel.cpp.

@@ -1754,7 +1754,7 @@

Definition at line 3721 of file RadiationModel.cpp.

+

Definition at line 3729 of file RadiationModel.cpp.

@@ -2032,7 +2032,7 @@

Note
Before running the band simulation, you must 1) add at least one radiative band to the simulation (see addRadiationBand()), 2) update the Context geometry in the model (see updateGeometry()), and 3) update radiative properties in the model (see updateRadiativeProperties).
-

Definition at line 3098 of file RadiationModel.cpp.

+

Definition at line 3106 of file RadiationModel.cpp.

@@ -2060,7 +2060,7 @@

Note
Before running the band simulation, you must 1) add at least one radiative band to the simulation (see addRadiationBand()), 2) update the Context geometry in the model (see updateGeometry()), and 3) update radiative properties in the model (see updateRadiativeProperties).
-

Definition at line 3103 of file RadiationModel.cpp.

+

Definition at line 3111 of file RadiationModel.cpp.

@@ -2128,7 +2128,7 @@

Definition at line 4966 of file RadiationModel.cpp.

+

Definition at line 4974 of file RadiationModel.cpp.

@@ -2196,7 +2196,7 @@

Definition at line 5007 of file RadiationModel.cpp.

+

Definition at line 5015 of file RadiationModel.cpp.

@@ -2351,7 +2351,7 @@

-

Definition at line 4844 of file RadiationModel.cpp.

+

Definition at line 4852 of file RadiationModel.cpp.

@@ -2960,7 +2960,7 @@

Definition at line 5587 of file RadiationModel.cpp.

+

Definition at line 5619 of file RadiationModel.cpp.

@@ -3392,7 +3392,7 @@

Definition at line 4849 of file RadiationModel.cpp.

+

Definition at line 4857 of file RadiationModel.cpp.

@@ -3414,7 +3414,7 @@

Note
updateGeometry() must be called before simulation can be run
-

Definition at line 1966 of file RadiationModel.cpp.

+

Definition at line 1974 of file RadiationModel.cpp.

@@ -3442,7 +3442,7 @@

Note
updateGeometry() must be called before simulation can be run
-

Definition at line 1970 of file RadiationModel.cpp.

+

Definition at line 1978 of file RadiationModel.cpp.

@@ -3548,7 +3548,7 @@

Definition at line 1420 of file RadiationModel.cpp.

+

Definition at line 1424 of file RadiationModel.cpp.

@@ -3592,7 +3592,7 @@

Definition at line 5249 of file RadiationModel.cpp.

+

Definition at line 5265 of file RadiationModel.cpp.

@@ -3653,7 +3653,7 @@

Definition at line 5368 of file RadiationModel.cpp.

+

Definition at line 5392 of file RadiationModel.cpp.

@@ -3714,7 +3714,7 @@

Definition at line 5473 of file RadiationModel.cpp.

+

Definition at line 5501 of file RadiationModel.cpp.

@@ -3764,7 +3764,7 @@

Definition at line 1386 of file RadiationModel.cpp.

+

Definition at line 1390 of file RadiationModel.cpp.

@@ -3814,7 +3814,7 @@

Definition at line 5301 of file RadiationModel.cpp.

+

Definition at line 5321 of file RadiationModel.cpp.

@@ -3870,7 +3870,7 @@

Definition at line 5161 of file RadiationModel.cpp.

+

Definition at line 5173 of file RadiationModel.cpp.

@@ -3926,7 +3926,7 @@

Definition at line 5074 of file RadiationModel.cpp.

+

Definition at line 5082 of file RadiationModel.cpp.

diff --git a/doc/html/class_solar_position.html b/doc/html/class_solar_position.html index ea82a4f0f..6cf2910c1 100644 --- a/doc/html/class_solar_position.html +++ b/doc/html/class_solar_position.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_stomatal_conductance_model.html b/doc/html/class_stomatal_conductance_model.html index 6287814b2..b774c5128 100644 --- a/doc/html/class_stomatal_conductance_model.html +++ b/doc/html/class_stomatal_conductance_model.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_synthetic_annotation.html b/doc/html/class_synthetic_annotation.html index d2ee9c142..f7a21d443 100644 --- a/doc/html/class_synthetic_annotation.html +++ b/doc/html/class_synthetic_annotation.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_visualizer.html b/doc/html/class_visualizer.html index a2fc9bd82..540907e41 100644 --- a/doc/html/class_visualizer.html +++ b/doc/html/class_visualizer.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_voxel_intersection.html b/doc/html/class_voxel_intersection.html index 24d0a8ac6..a566823b4 100644 --- a/doc/html/class_voxel_intersection.html +++ b/doc/html/class_voxel_intersection.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/class_weber_penn_tree.html b/doc/html/class_weber_penn_tree.html index 902a2b22b..24e13cd0a 100644 --- a/doc/html/class_weber_penn_tree.html +++ b/doc/html/class_weber_penn_tree.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/classes.html b/doc/html/classes.html index a0d2c783e..f89e57672 100644 --- a/doc/html/classes.html +++ b/doc/html/classes.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/classhelios_1_1_box.html b/doc/html/classhelios_1_1_box.html index 91dcd339d..da5dc124d 100644 --- a/doc/html/classhelios_1_1_box.html +++ b/doc/html/classhelios_1_1_box.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/classhelios_1_1_compound_object.html b/doc/html/classhelios_1_1_compound_object.html index 7c27ccf90..1060c40c9 100644 --- a/doc/html/classhelios_1_1_compound_object.html +++ b/doc/html/classhelios_1_1_compound_object.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/classhelios_1_1_cone.html b/doc/html/classhelios_1_1_cone.html index d3d4a3ebd..0624fecb7 100644 --- a/doc/html/classhelios_1_1_cone.html +++ b/doc/html/classhelios_1_1_cone.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/classhelios_1_1_context.html b/doc/html/classhelios_1_1_context.html index a6bb27ed5..f9802f5a6 100644 --- a/doc/html/classhelios_1_1_context.html +++ b/doc/html/classhelios_1_1_context.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -10248,7 +10248,7 @@

Definition at line 3734 of file Context_fileIO.cpp.

+

Definition at line 3742 of file Context_fileIO.cpp.

@@ -10311,7 +10311,7 @@

Returns
Vector of UUIDs for each primitive generated from the PLY model
-

Definition at line 3746 of file Context_fileIO.cpp.

+

Definition at line 3754 of file Context_fileIO.cpp.

@@ -10368,7 +10368,7 @@

Returns
Vector of UUIDs for each primitive generated from the OBJ model
-

Definition at line 3738 of file Context_fileIO.cpp.

+

Definition at line 3746 of file Context_fileIO.cpp.

@@ -10431,7 +10431,7 @@

Returns
Vector of UUIDs for each primitive generated from the PLY model
-

Definition at line 3742 of file Context_fileIO.cpp.

+

Definition at line 3750 of file Context_fileIO.cpp.

@@ -10465,7 +10465,7 @@

Returns
Vector of UUIDs for each primitive generated from the PLY model
Note
Assumes default color of blue if no colors are specified in the .ply file
-

Definition at line 3370 of file Context_fileIO.cpp.

+

Definition at line 3378 of file Context_fileIO.cpp.

@@ -10522,7 +10522,7 @@

Returns
Vector of UUIDs for each primitive generated from the PLY model
-

Definition at line 3382 of file Context_fileIO.cpp.

+

Definition at line 3390 of file Context_fileIO.cpp.

@@ -10585,7 +10585,7 @@

Returns
Vector of UUIDs for each primitive generated from the PLY model
-

Definition at line 3386 of file Context_fileIO.cpp.

+

Definition at line 3394 of file Context_fileIO.cpp.

@@ -10643,7 +10643,7 @@

Returns
Vector of UUIDs for each primitive generated from the PLY model
Note
Assumes default color of blue if no colors are specified in the .ply file
-

Definition at line 3378 of file Context_fileIO.cpp.

+

Definition at line 3386 of file Context_fileIO.cpp.

@@ -10695,7 +10695,7 @@

Returns
Vector of UUIDs for each primitive generated from the PLY model
Note
Assumes default color of blue if no colors are specified in the .ply file
-

Definition at line 3374 of file Context_fileIO.cpp.

+

Definition at line 3382 of file Context_fileIO.cpp.

@@ -10735,7 +10735,7 @@

Definition at line 4544 of file Context_fileIO.cpp.

+

Definition at line 4552 of file Context_fileIO.cpp.

@@ -17328,7 +17328,7 @@

Definition at line 4123 of file Context_fileIO.cpp.

+

Definition at line 4131 of file Context_fileIO.cpp.

@@ -17360,7 +17360,7 @@

Definition at line 4127 of file Context_fileIO.cpp.

+

Definition at line 4135 of file Context_fileIO.cpp.

@@ -17398,7 +17398,7 @@

Definition at line 4131 of file Context_fileIO.cpp.

+

Definition at line 4139 of file Context_fileIO.cpp.

@@ -17425,7 +17425,7 @@

Definition at line 3670 of file Context_fileIO.cpp.

+

Definition at line 3678 of file Context_fileIO.cpp.

@@ -17463,7 +17463,7 @@

Definition at line 4465 of file Context_fileIO.cpp.

+

Definition at line 4473 of file Context_fileIO.cpp.

@@ -17507,7 +17507,7 @@

Definition at line 4469 of file Context_fileIO.cpp.

+

Definition at line 4477 of file Context_fileIO.cpp.

diff --git a/doc/html/classhelios_1_1_disk.html b/doc/html/classhelios_1_1_disk.html index 2e63fab9f..963086421 100644 --- a/doc/html/classhelios_1_1_disk.html +++ b/doc/html/classhelios_1_1_disk.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/classhelios_1_1_polymesh.html b/doc/html/classhelios_1_1_polymesh.html index 7a0cf251c..cdccc1689 100644 --- a/doc/html/classhelios_1_1_polymesh.html +++ b/doc/html/classhelios_1_1_polymesh.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/classhelios_1_1_sphere.html b/doc/html/classhelios_1_1_sphere.html index c5c2f5b21..046dbcb67 100644 --- a/doc/html/classhelios_1_1_sphere.html +++ b/doc/html/classhelios_1_1_sphere.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/classhelios_1_1_texture.html b/doc/html/classhelios_1_1_texture.html index 9da5d4f57..7ba41f42e 100644 --- a/doc/html/classhelios_1_1_texture.html +++ b/doc/html/classhelios_1_1_texture.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/classhelios_1_1_tile.html b/doc/html/classhelios_1_1_tile.html index b147d199d..33d282ced 100644 --- a/doc/html/classhelios_1_1_tile.html +++ b/doc/html/classhelios_1_1_tile.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/classhelios_1_1_tube.html b/doc/html/classhelios_1_1_tube.html index 0aaef06ec..4bb2ac171 100644 --- a/doc/html/classhelios_1_1_tube.html +++ b/doc/html/classhelios_1_1_tube.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/classhelios_1_1_x_m_lparser.html b/doc/html/classhelios_1_1_x_m_lparser.html index ea05c654d..dee49150c 100644 --- a/doc/html/classhelios_1_1_x_m_lparser.html +++ b/doc/html/classhelios_1_1_x_m_lparser.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/context_globaldata.html b/doc/html/context_globaldata.html index 456f5f7ab..57c37bb7a 100644 --- a/doc/html/context_globaldata.html +++ b/doc/html/context_globaldata.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/context_primdata.html b/doc/html/context_primdata.html index dd37c0732..f1d8b5ea3 100644 --- a/doc/html/context_primdata.html +++ b/doc/html/context_primdata.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/context_primitives.html b/doc/html/context_primitives.html index 53d8e9f57..6a3e15ffc 100644 --- a/doc/html/context_primitives.html +++ b/doc/html/context_primitives.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/context_selftest.html b/doc/html/context_selftest.html index 19063597e..e1314c358 100644 --- a/doc/html/context_selftest.html +++ b/doc/html/context_selftest.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/context_vectors.html b/doc/html/context_vectors.html index 7283c86c9..98f8ed270 100644 --- a/doc/html/context_vectors.html +++ b/doc/html/context_vectors.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/core_2src_2self_test_8cpp.html b/doc/html/core_2src_2self_test_8cpp.html index cb033755d..359563fd4 100644 --- a/doc/html/core_2src_2self_test_8cpp.html +++ b/doc/html/core_2src_2self_test_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/core_2src_2self_test_8cpp_source.html b/doc/html/core_2src_2self_test_8cpp_source.html index 656c7a96a..63dd84216 100644 --- a/doc/html/core_2src_2self_test_8cpp_source.html +++ b/doc/html/core_2src_2self_test_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -1368,7 +1368,7 @@
std::vector< uint > loadXML(const char *filename, bool quiet=false)
Load inputs specified in an XML file.
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1396
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:6997
-
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.
+
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.
void getPrimitiveData(uint UUID, const char *label, int &data) const
Get data associated with a primitive element.
void deletePrimitive(uint UUID)
Delete a single primitive from the context.
Definition Context.cpp:1526
bool doesObjectDataExist(uint objID, const char *label) const
Check if primitive data 'label' exists.
@@ -1391,7 +1391,7 @@
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:2887
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition Context.cpp:1568
-
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...
+
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 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.
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:1753
@@ -1411,10 +1411,10 @@
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:7066
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
std::string getFileExtension(const std::string &filepath)
Parse a file string to get the extension.
Definition global.cpp:2993
-
std::string getFileName(const std::string &filepath)
Parse a file string to get the filename including extension.
Definition global.cpp:3034
+
std::string getFileName(const std::string &filepath)
Parse a file string to get the filename including extension.
Definition global.cpp:3003
int JulianDay(int day, int month, int year)
Convert calendar day (day,month,year) to Julian day.
Definition global.cpp:1268
-
std::string getFileStem(const std::string &filepath)
Parse a file string to get the filename without extension.
Definition global.cpp:3019
-
std::string getFilePath(const std::string &filepath, bool trailingslash=true)
Parse a file string to get the path (i.e., portion of the string before the file name).
Definition global.cpp:3045
+
std::string getFileStem(const std::string &filepath)
Parse a file string to get the filename without extension.
Definition global.cpp:2998
+
std::string getFilePath(const std::string &filepath, bool trailingslash=true)
Parse a file string to get the path (i.e., portion of the string before the file name).
Definition global.cpp:3008
SphericalCoord nullrotation
Default null SphericalCoord that applies no rotation.
Definition global.cpp:57
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:5200
uint addTubeObject(uint radial_subdivisions, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:4690
diff --git a/doc/html/dir_000a2e4fe776603f09c56917fe929269.html b/doc/html/dir_000a2e4fe776603f09c56917fe929269.html index 433ff3b94..b520f021d 100644 --- a/doc/html/dir_000a2e4fe776603f09c56917fe929269.html +++ b/doc/html/dir_000a2e4fe776603f09c56917fe929269.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_01af3122a6d2fc081d545f111575c8ac.html b/doc/html/dir_01af3122a6d2fc081d545f111575c8ac.html index 65f052f87..df37f0bb3 100644 --- a/doc/html/dir_01af3122a6d2fc081d545f111575c8ac.html +++ b/doc/html/dir_01af3122a6d2fc081d545f111575c8ac.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_0581b1fc91af6cc2594fe789a424270d.html b/doc/html/dir_0581b1fc91af6cc2594fe789a424270d.html index 6726adbb7..b147619f3 100644 --- a/doc/html/dir_0581b1fc91af6cc2594fe789a424270d.html +++ b/doc/html/dir_0581b1fc91af6cc2594fe789a424270d.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_09ba98b3b490a60de71fb62d89fe47cd.html b/doc/html/dir_09ba98b3b490a60de71fb62d89fe47cd.html index d6ed3f722..26db24dbd 100644 --- a/doc/html/dir_09ba98b3b490a60de71fb62d89fe47cd.html +++ b/doc/html/dir_09ba98b3b490a60de71fb62d89fe47cd.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_0b377c449e87c33e20eed98f7cc3a6cc.html b/doc/html/dir_0b377c449e87c33e20eed98f7cc3a6cc.html index 364564c11..01ff44a01 100644 --- a/doc/html/dir_0b377c449e87c33e20eed98f7cc3a6cc.html +++ b/doc/html/dir_0b377c449e87c33e20eed98f7cc3a6cc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_0ed0e5ef04d2b4b7edd36da5802052a6.html b/doc/html/dir_0ed0e5ef04d2b4b7edd36da5802052a6.html index ac5f1e629..232a04d5d 100644 --- a/doc/html/dir_0ed0e5ef04d2b4b7edd36da5802052a6.html +++ b/doc/html/dir_0ed0e5ef04d2b4b7edd36da5802052a6.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_10651e710c37b90bb60afaa4d2c6a975.html b/doc/html/dir_10651e710c37b90bb60afaa4d2c6a975.html index 32e22743d..5952fcc0d 100644 --- a/doc/html/dir_10651e710c37b90bb60afaa4d2c6a975.html +++ b/doc/html/dir_10651e710c37b90bb60afaa4d2c6a975.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.html b/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.html index 2084318d4..557245063 100644 --- a/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.html +++ b/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_1b48a9a5d33ab4b7862a4538757abad5.html b/doc/html/dir_1b48a9a5d33ab4b7862a4538757abad5.html index bcdaa9a0f..d55a9b227 100644 --- a/doc/html/dir_1b48a9a5d33ab4b7862a4538757abad5.html +++ b/doc/html/dir_1b48a9a5d33ab4b7862a4538757abad5.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_1c54673618a694dbf6d60994b9e4cd26.html b/doc/html/dir_1c54673618a694dbf6d60994b9e4cd26.html index 86de8cf59..361a9436a 100644 --- a/doc/html/dir_1c54673618a694dbf6d60994b9e4cd26.html +++ b/doc/html/dir_1c54673618a694dbf6d60994b9e4cd26.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.html b/doc/html/dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.html index 4ae3d64ce..74c1359d6 100644 --- a/doc/html/dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.html +++ b/doc/html/dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.html b/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.html index 1c16f128c..651e10ab4 100644 --- a/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.html +++ b/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_2dbe15cacd8389cc56dad1ecef740014.html b/doc/html/dir_2dbe15cacd8389cc56dad1ecef740014.html index 0285204c0..be3e62b92 100644 --- a/doc/html/dir_2dbe15cacd8389cc56dad1ecef740014.html +++ b/doc/html/dir_2dbe15cacd8389cc56dad1ecef740014.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_311a8078924eda44cf0bc3884606fa36.html b/doc/html/dir_311a8078924eda44cf0bc3884606fa36.html index a0b08da2e..b9edde429 100644 --- a/doc/html/dir_311a8078924eda44cf0bc3884606fa36.html +++ b/doc/html/dir_311a8078924eda44cf0bc3884606fa36.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_324b51d306f9962e8d7b85b82cd2c869.html b/doc/html/dir_324b51d306f9962e8d7b85b82cd2c869.html index cbb6e30fc..dcfe9f39d 100644 --- a/doc/html/dir_324b51d306f9962e8d7b85b82cd2c869.html +++ b/doc/html/dir_324b51d306f9962e8d7b85b82cd2c869.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_3771cc92d713de3e5272f9ad4d0b1912.html b/doc/html/dir_3771cc92d713de3e5272f9ad4d0b1912.html index 4783e3306..f3ece665e 100644 --- a/doc/html/dir_3771cc92d713de3e5272f9ad4d0b1912.html +++ b/doc/html/dir_3771cc92d713de3e5272f9ad4d0b1912.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_38c8d24aef3972a7f87b834274e76e31.html b/doc/html/dir_38c8d24aef3972a7f87b834274e76e31.html index efab481d0..33f15babc 100644 --- a/doc/html/dir_38c8d24aef3972a7f87b834274e76e31.html +++ b/doc/html/dir_38c8d24aef3972a7f87b834274e76e31.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_3b948ba013618d5b0560477725ec43e1.html b/doc/html/dir_3b948ba013618d5b0560477725ec43e1.html index 7758a63c8..96fc8bc2c 100644 --- a/doc/html/dir_3b948ba013618d5b0560477725ec43e1.html +++ b/doc/html/dir_3b948ba013618d5b0560477725ec43e1.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_3d4da5c581737ecd0f864ccf0711fd92.html b/doc/html/dir_3d4da5c581737ecd0f864ccf0711fd92.html index 06b854264..c0956a005 100644 --- a/doc/html/dir_3d4da5c581737ecd0f864ccf0711fd92.html +++ b/doc/html/dir_3d4da5c581737ecd0f864ccf0711fd92.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_3d6a603070d279a42ac417e5c8a6aba1.html b/doc/html/dir_3d6a603070d279a42ac417e5c8a6aba1.html index 564499585..4a8529e54 100644 --- a/doc/html/dir_3d6a603070d279a42ac417e5c8a6aba1.html +++ b/doc/html/dir_3d6a603070d279a42ac417e5c8a6aba1.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_40ea2a4aa4adfc7dc77aa13d0834001b.html b/doc/html/dir_40ea2a4aa4adfc7dc77aa13d0834001b.html index 099a43bac..7368ce278 100644 --- a/doc/html/dir_40ea2a4aa4adfc7dc77aa13d0834001b.html +++ b/doc/html/dir_40ea2a4aa4adfc7dc77aa13d0834001b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_418637634c2136ee3716f84b17e3fdeb.html b/doc/html/dir_418637634c2136ee3716f84b17e3fdeb.html index 334cd6416..9be49efcf 100644 --- a/doc/html/dir_418637634c2136ee3716f84b17e3fdeb.html +++ b/doc/html/dir_418637634c2136ee3716f84b17e3fdeb.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_4270bfced15e0e73154b13468c7c9ad9.html b/doc/html/dir_4270bfced15e0e73154b13468c7c9ad9.html index 0d429fb98..56a14dd30 100644 --- a/doc/html/dir_4270bfced15e0e73154b13468c7c9ad9.html +++ b/doc/html/dir_4270bfced15e0e73154b13468c7c9ad9.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_4942485e7dfd848fb997bfbb4ff4feb4.html b/doc/html/dir_4942485e7dfd848fb997bfbb4ff4feb4.html index 282f8642a..dfb75ebd9 100644 --- a/doc/html/dir_4942485e7dfd848fb997bfbb4ff4feb4.html +++ b/doc/html/dir_4942485e7dfd848fb997bfbb4ff4feb4.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_4ccbab8385dcba906f6a2cce80a3b511.html b/doc/html/dir_4ccbab8385dcba906f6a2cce80a3b511.html index 3a5503a06..e49797640 100644 --- a/doc/html/dir_4ccbab8385dcba906f6a2cce80a3b511.html +++ b/doc/html/dir_4ccbab8385dcba906f6a2cce80a3b511.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_51eab06546c34d501c6cf953a16a9cc5.html b/doc/html/dir_51eab06546c34d501c6cf953a16a9cc5.html index dd1af95a3..c390aca38 100644 --- a/doc/html/dir_51eab06546c34d501c6cf953a16a9cc5.html +++ b/doc/html/dir_51eab06546c34d501c6cf953a16a9cc5.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_53e799243804d32eb30709605e43a53b.html b/doc/html/dir_53e799243804d32eb30709605e43a53b.html index f5d4a66e6..b52fe85d2 100644 --- a/doc/html/dir_53e799243804d32eb30709605e43a53b.html +++ b/doc/html/dir_53e799243804d32eb30709605e43a53b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_562cb346de9113a49164a1513c42aa1c.html b/doc/html/dir_562cb346de9113a49164a1513c42aa1c.html index e5ea5da4c..bb277128e 100644 --- a/doc/html/dir_562cb346de9113a49164a1513c42aa1c.html +++ b/doc/html/dir_562cb346de9113a49164a1513c42aa1c.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_577e0cdb3e2614f5a260ea490887b143.html b/doc/html/dir_577e0cdb3e2614f5a260ea490887b143.html index 0893fbb3d..a5804d065 100644 --- a/doc/html/dir_577e0cdb3e2614f5a260ea490887b143.html +++ b/doc/html/dir_577e0cdb3e2614f5a260ea490887b143.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_58badfc9ced8151ac5118cd2e12bebf1.html b/doc/html/dir_58badfc9ced8151ac5118cd2e12bebf1.html index b14ae059c..6e3978488 100644 --- a/doc/html/dir_58badfc9ced8151ac5118cd2e12bebf1.html +++ b/doc/html/dir_58badfc9ced8151ac5118cd2e12bebf1.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_594f7d9c1b5f727f933fa022588b0b7d.html b/doc/html/dir_594f7d9c1b5f727f933fa022588b0b7d.html index a8bde1ce5..0e923c5b7 100644 --- a/doc/html/dir_594f7d9c1b5f727f933fa022588b0b7d.html +++ b/doc/html/dir_594f7d9c1b5f727f933fa022588b0b7d.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_59c6a555a98729b3f6a8f77608cc74a4.html b/doc/html/dir_59c6a555a98729b3f6a8f77608cc74a4.html index 86aec2f68..3034a78cb 100644 --- a/doc/html/dir_59c6a555a98729b3f6a8f77608cc74a4.html +++ b/doc/html/dir_59c6a555a98729b3f6a8f77608cc74a4.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_615177bc4a60bdbaf2db637460677b64.html b/doc/html/dir_615177bc4a60bdbaf2db637460677b64.html index 786a96a4a..f2ce51342 100644 --- a/doc/html/dir_615177bc4a60bdbaf2db637460677b64.html +++ b/doc/html/dir_615177bc4a60bdbaf2db637460677b64.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_6252300d35bf0f8a4d6b5ccb98672957.html b/doc/html/dir_6252300d35bf0f8a4d6b5ccb98672957.html index 0efeb9599..4c3c474bd 100644 --- a/doc/html/dir_6252300d35bf0f8a4d6b5ccb98672957.html +++ b/doc/html/dir_6252300d35bf0f8a4d6b5ccb98672957.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_6576ef5c45e1ae696f88b82c16a4c6c0.html b/doc/html/dir_6576ef5c45e1ae696f88b82c16a4c6c0.html index 3140e355c..ca4d8dd6f 100644 --- a/doc/html/dir_6576ef5c45e1ae696f88b82c16a4c6c0.html +++ b/doc/html/dir_6576ef5c45e1ae696f88b82c16a4c6c0.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_676c0954ed84853013df50d94356577b.html b/doc/html/dir_676c0954ed84853013df50d94356577b.html index 861974438..0214365a5 100644 --- a/doc/html/dir_676c0954ed84853013df50d94356577b.html +++ b/doc/html/dir_676c0954ed84853013df50d94356577b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_67ef339cfff2cfda5a7b1755578ee854.html b/doc/html/dir_67ef339cfff2cfda5a7b1755578ee854.html index 37a94ac40..8a3c8d739 100644 --- a/doc/html/dir_67ef339cfff2cfda5a7b1755578ee854.html +++ b/doc/html/dir_67ef339cfff2cfda5a7b1755578ee854.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_6d823072f66bbcb32b0d3acc588685b0.html b/doc/html/dir_6d823072f66bbcb32b0d3acc588685b0.html index 5a4364778..539b55182 100644 --- a/doc/html/dir_6d823072f66bbcb32b0d3acc588685b0.html +++ b/doc/html/dir_6d823072f66bbcb32b0d3acc588685b0.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.html b/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.html index 2562ed7c0..19543d761 100644 --- a/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.html +++ b/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_7f186228a2612084b0fc24dff2e535bf.html b/doc/html/dir_7f186228a2612084b0fc24dff2e535bf.html index c5e5ddc52..f1bea32e3 100644 --- a/doc/html/dir_7f186228a2612084b0fc24dff2e535bf.html +++ b/doc/html/dir_7f186228a2612084b0fc24dff2e535bf.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_8a62bca5fa5119ede20b35462196f194.html b/doc/html/dir_8a62bca5fa5119ede20b35462196f194.html index 3f518cd48..30bf619a8 100644 --- a/doc/html/dir_8a62bca5fa5119ede20b35462196f194.html +++ b/doc/html/dir_8a62bca5fa5119ede20b35462196f194.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_8add51f561986f34dfac90d296d2ac1f.html b/doc/html/dir_8add51f561986f34dfac90d296d2ac1f.html index f4845096d..30afd8b54 100644 --- a/doc/html/dir_8add51f561986f34dfac90d296d2ac1f.html +++ b/doc/html/dir_8add51f561986f34dfac90d296d2ac1f.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_9018c8dc5d181eb1cb047286a97fa87b.html b/doc/html/dir_9018c8dc5d181eb1cb047286a97fa87b.html index 261557f03..16f6cbf92 100644 --- a/doc/html/dir_9018c8dc5d181eb1cb047286a97fa87b.html +++ b/doc/html/dir_9018c8dc5d181eb1cb047286a97fa87b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_90fd98a0ba30abf7a6068a44995d2d6b.html b/doc/html/dir_90fd98a0ba30abf7a6068a44995d2d6b.html index 9124685a9..fce4f9d50 100644 --- a/doc/html/dir_90fd98a0ba30abf7a6068a44995d2d6b.html +++ b/doc/html/dir_90fd98a0ba30abf7a6068a44995d2d6b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_98f1c86a7f536ff9d6c61df9d8c64baa.html b/doc/html/dir_98f1c86a7f536ff9d6c61df9d8c64baa.html index 953b11005..70e6213b4 100644 --- a/doc/html/dir_98f1c86a7f536ff9d6c61df9d8c64baa.html +++ b/doc/html/dir_98f1c86a7f536ff9d6c61df9d8c64baa.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_9a3b5787d2329f793333f6962c777986.html b/doc/html/dir_9a3b5787d2329f793333f6962c777986.html index 63ac79fd7..66bd7041d 100644 --- a/doc/html/dir_9a3b5787d2329f793333f6962c777986.html +++ b/doc/html/dir_9a3b5787d2329f793333f6962c777986.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_9a6cc15fde559dad335c1dc145a826ea.html b/doc/html/dir_9a6cc15fde559dad335c1dc145a826ea.html index 449f66222..2b4b5359c 100644 --- a/doc/html/dir_9a6cc15fde559dad335c1dc145a826ea.html +++ b/doc/html/dir_9a6cc15fde559dad335c1dc145a826ea.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_a2b45ea1295f1e42b26af05f3b546a5b.html b/doc/html/dir_a2b45ea1295f1e42b26af05f3b546a5b.html index 5b1898a9c..adb405756 100644 --- a/doc/html/dir_a2b45ea1295f1e42b26af05f3b546a5b.html +++ b/doc/html/dir_a2b45ea1295f1e42b26af05f3b546a5b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_a4ee10e64f839049093220f98040855a.html b/doc/html/dir_a4ee10e64f839049093220f98040855a.html index a840270aa..0f5013b57 100644 --- a/doc/html/dir_a4ee10e64f839049093220f98040855a.html +++ b/doc/html/dir_a4ee10e64f839049093220f98040855a.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_a604905e97bad612ecdda55ac09d6396.html b/doc/html/dir_a604905e97bad612ecdda55ac09d6396.html index 32340277d..11a413220 100644 --- a/doc/html/dir_a604905e97bad612ecdda55ac09d6396.html +++ b/doc/html/dir_a604905e97bad612ecdda55ac09d6396.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_a8babb820ec20ecec6aebc09dbfb576c.html b/doc/html/dir_a8babb820ec20ecec6aebc09dbfb576c.html index 03eef78e8..3e81c28d5 100644 --- a/doc/html/dir_a8babb820ec20ecec6aebc09dbfb576c.html +++ b/doc/html/dir_a8babb820ec20ecec6aebc09dbfb576c.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_b81f286eb903e0c3ba53b620487c01ae.html b/doc/html/dir_b81f286eb903e0c3ba53b620487c01ae.html index afe24512e..33cdd5931 100644 --- a/doc/html/dir_b81f286eb903e0c3ba53b620487c01ae.html +++ b/doc/html/dir_b81f286eb903e0c3ba53b620487c01ae.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_b867f472847a1f099af0eb422541f49e.html b/doc/html/dir_b867f472847a1f099af0eb422541f49e.html index 22014d789..d1a2d42e6 100644 --- a/doc/html/dir_b867f472847a1f099af0eb422541f49e.html +++ b/doc/html/dir_b867f472847a1f099af0eb422541f49e.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_bc56ed6b0b97565306d951dc61815da9.html b/doc/html/dir_bc56ed6b0b97565306d951dc61815da9.html index 0d8a50fa9..1e32aa018 100644 --- a/doc/html/dir_bc56ed6b0b97565306d951dc61815da9.html +++ b/doc/html/dir_bc56ed6b0b97565306d951dc61815da9.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_c2e785b0428381d295aba3d86e865907.html b/doc/html/dir_c2e785b0428381d295aba3d86e865907.html index c3fc18c6f..47000a6cc 100644 --- a/doc/html/dir_c2e785b0428381d295aba3d86e865907.html +++ b/doc/html/dir_c2e785b0428381d295aba3d86e865907.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_d11e5a89bd40b12607fdeb823ca30c1a.html b/doc/html/dir_d11e5a89bd40b12607fdeb823ca30c1a.html index fba5b727c..0fa0924f1 100644 --- a/doc/html/dir_d11e5a89bd40b12607fdeb823ca30c1a.html +++ b/doc/html/dir_d11e5a89bd40b12607fdeb823ca30c1a.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_d346877beec799c6cac1a2fc56d1c290.html b/doc/html/dir_d346877beec799c6cac1a2fc56d1c290.html index 04be35521..c1c49bf6c 100644 --- a/doc/html/dir_d346877beec799c6cac1a2fc56d1c290.html +++ b/doc/html/dir_d346877beec799c6cac1a2fc56d1c290.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_d39c4dd70ac914a319fbf3979f3cb0cd.html b/doc/html/dir_d39c4dd70ac914a319fbf3979f3cb0cd.html index 45607d05c..034a17a16 100644 --- a/doc/html/dir_d39c4dd70ac914a319fbf3979f3cb0cd.html +++ b/doc/html/dir_d39c4dd70ac914a319fbf3979f3cb0cd.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_d684e7c998fb76edbfb655ffd4cf6611.html b/doc/html/dir_d684e7c998fb76edbfb655ffd4cf6611.html index 08d221e96..5d5245ed4 100644 --- a/doc/html/dir_d684e7c998fb76edbfb655ffd4cf6611.html +++ b/doc/html/dir_d684e7c998fb76edbfb655ffd4cf6611.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_d6ff66ea9f957e81b4485948f070bc7c.html b/doc/html/dir_d6ff66ea9f957e81b4485948f070bc7c.html index ad821a94c..bada20bed 100644 --- a/doc/html/dir_d6ff66ea9f957e81b4485948f070bc7c.html +++ b/doc/html/dir_d6ff66ea9f957e81b4485948f070bc7c.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_daed1286feb5181d9374e50e34ff739d.html b/doc/html/dir_daed1286feb5181d9374e50e34ff739d.html index 280d24f5f..bf008afb5 100644 --- a/doc/html/dir_daed1286feb5181d9374e50e34ff739d.html +++ b/doc/html/dir_daed1286feb5181d9374e50e34ff739d.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_e68e8157741866f444e17edd764ebbae.html b/doc/html/dir_e68e8157741866f444e17edd764ebbae.html index f047d2bdc..b810b3eaf 100644 --- a/doc/html/dir_e68e8157741866f444e17edd764ebbae.html +++ b/doc/html/dir_e68e8157741866f444e17edd764ebbae.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_e725f6d562ac5b3216da834679296cd3.html b/doc/html/dir_e725f6d562ac5b3216da834679296cd3.html index e8ace17d8..73ecb8110 100644 --- a/doc/html/dir_e725f6d562ac5b3216da834679296cd3.html +++ b/doc/html/dir_e725f6d562ac5b3216da834679296cd3.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_e771e57a540d4f14ef5ec2c81b56a7b6.html b/doc/html/dir_e771e57a540d4f14ef5ec2c81b56a7b6.html index accc69a7b..7cdd0010f 100644 --- a/doc/html/dir_e771e57a540d4f14ef5ec2c81b56a7b6.html +++ b/doc/html/dir_e771e57a540d4f14ef5ec2c81b56a7b6.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html b/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html index e0df667ba..fcc6f10ed 100644 --- a/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html +++ b/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_ee14773baee519b082f78b85b263aa48.html b/doc/html/dir_ee14773baee519b082f78b85b263aa48.html index a9813652f..48c6393b8 100644 --- a/doc/html/dir_ee14773baee519b082f78b85b263aa48.html +++ b/doc/html/dir_ee14773baee519b082f78b85b263aa48.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_f54e10c7807847345da870f7da42cdf0.html b/doc/html/dir_f54e10c7807847345da870f7da42cdf0.html index cb8b0421b..b61e9e658 100644 --- a/doc/html/dir_f54e10c7807847345da870f7da42cdf0.html +++ b/doc/html/dir_f54e10c7807847345da870f7da42cdf0.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_f93a58e1b1064abf3e9af98b74e2f5d5.html b/doc/html/dir_f93a58e1b1064abf3e9af98b74e2f5d5.html index aa7652d9d..35c4f40ad 100644 --- a/doc/html/dir_f93a58e1b1064abf3e9af98b74e2f5d5.html +++ b/doc/html/dir_f93a58e1b1064abf3e9af98b74e2f5d5.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/dir_fceca22ca0920a3e9321d273c935ca85.html b/doc/html/dir_fceca22ca0920a3e9321d273c935ca85.html index 815368ca7..ef168828e 100644 --- a/doc/html/dir_fceca22ca0920a3e9321d273c935ca85.html +++ b/doc/html/dir_fceca22ca0920a3e9321d273c935ca85.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/doxygen_crawl.html b/doc/html/doxygen_crawl.html index d63d00208..d4e13b5e8 100644 --- a/doc/html/doxygen_crawl.html +++ b/doc/html/doxygen_crawl.html @@ -794,9 +794,7 @@ - - @@ -2338,6 +2336,7 @@ + @@ -2691,6 +2690,7 @@ + diff --git a/doc/html/files.html b/doc/html/files.html index 97509af7d..250316599 100644 --- a/doc/html/files.html +++ b/doc/html/files.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/form_162.png b/doc/html/form_162.png index 5fc6c6ec9..6c6cef462 100644 Binary files a/doc/html/form_162.png and b/doc/html/form_162.png differ diff --git a/doc/html/formula.repository b/doc/html/formula.repository index 136c7c1a4..eee0be36d 100644 --- a/doc/html/formula.repository +++ b/doc/html/formula.repository @@ -172,8 +172,8 @@ \_form#159=11x11:${\mu}$ \_form#160=17x15:$k_C$ \_form#161=41x12:$A=0$ -\_form#162=191x32:\[ - d\theta = \frac{1}{2}\left(C_g-\theta\right)dL + T\xi(dL) +\_form#162=165x32:\[ + d\theta = -\frac{1}{2}\left(\theta\right)dL + T\xi(dL) \] \_form#163=15x12:$d\theta$ \_form#164=18x12:$dL$ diff --git a/doc/html/functions.html b/doc/html/functions.html index f7bf5712b..5eff121d0 100644 --- a/doc/html/functions.html +++ b/doc/html/functions.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_b.html b/doc/html/functions_b.html index ae51309c3..c67679445 100644 --- a/doc/html/functions_b.html +++ b/doc/html/functions_b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_c.html b/doc/html/functions_c.html index 49e03416e..5e828acc7 100644 --- a/doc/html/functions_c.html +++ b/doc/html/functions_c.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_d.html b/doc/html/functions_d.html index d9f1d8b3d..b7363feed 100644 --- a/doc/html/functions_d.html +++ b/doc/html/functions_d.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_e.html b/doc/html/functions_e.html index 50df41f4e..17b550265 100644 --- a/doc/html/functions_e.html +++ b/doc/html/functions_e.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_enum.html b/doc/html/functions_enum.html index cb3542992..55c85f8fe 100644 --- a/doc/html/functions_enum.html +++ b/doc/html/functions_enum.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_eval.html b/doc/html/functions_eval.html index 3640065cd..4c2b39d4b 100644 --- a/doc/html/functions_eval.html +++ b/doc/html/functions_eval.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_f.html b/doc/html/functions_f.html index 218ff21af..2bc48bdf3 100644 --- a/doc/html/functions_f.html +++ b/doc/html/functions_f.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func.html b/doc/html/functions_func.html index 8b41d422c..03d0ff81b 100644 --- a/doc/html/functions_func.html +++ b/doc/html/functions_func.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_b.html b/doc/html/functions_func_b.html index 954e479c8..58ffdc4e4 100644 --- a/doc/html/functions_func_b.html +++ b/doc/html/functions_func_b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_c.html b/doc/html/functions_func_c.html index 4933cf602..60a013fa9 100644 --- a/doc/html/functions_func_c.html +++ b/doc/html/functions_func_c.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_d.html b/doc/html/functions_func_d.html index 25472b775..319053cb3 100644 --- a/doc/html/functions_func_d.html +++ b/doc/html/functions_func_d.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_e.html b/doc/html/functions_func_e.html index 4753b05a6..eac7d0eb2 100644 --- a/doc/html/functions_func_e.html +++ b/doc/html/functions_func_e.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_f.html b/doc/html/functions_func_f.html index 326728734..d725599ed 100644 --- a/doc/html/functions_func_f.html +++ b/doc/html/functions_func_f.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_g.html b/doc/html/functions_func_g.html index e36c227e6..448a418f1 100644 --- a/doc/html/functions_func_g.html +++ b/doc/html/functions_func_g.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_h.html b/doc/html/functions_func_h.html index 3b14cae32..c046835db 100644 --- a/doc/html/functions_func_h.html +++ b/doc/html/functions_func_h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_i.html b/doc/html/functions_func_i.html index dd4527471..8ae32e287 100644 --- a/doc/html/functions_func_i.html +++ b/doc/html/functions_func_i.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_j.html b/doc/html/functions_func_j.html index 34b5efd5e..25fba375a 100644 --- a/doc/html/functions_func_j.html +++ b/doc/html/functions_func_j.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_l.html b/doc/html/functions_func_l.html index cf440ecf7..0be28c77b 100644 --- a/doc/html/functions_func_l.html +++ b/doc/html/functions_func_l.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_m.html b/doc/html/functions_func_m.html index bcda002ac..c954ed2ee 100644 --- a/doc/html/functions_func_m.html +++ b/doc/html/functions_func_m.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_n.html b/doc/html/functions_func_n.html index 8b871291e..8414ea1fd 100644 --- a/doc/html/functions_func_n.html +++ b/doc/html/functions_func_n.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_o.html b/doc/html/functions_func_o.html index ce9199aec..adb4ebdaa 100644 --- a/doc/html/functions_func_o.html +++ b/doc/html/functions_func_o.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_p.html b/doc/html/functions_func_p.html index b6e3c12af..c0808590c 100644 --- a/doc/html/functions_func_p.html +++ b/doc/html/functions_func_p.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_q.html b/doc/html/functions_func_q.html index be6c441c1..a4073ce83 100644 --- a/doc/html/functions_func_q.html +++ b/doc/html/functions_func_q.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_r.html b/doc/html/functions_func_r.html index 887f0ee92..c54f9b00f 100644 --- a/doc/html/functions_func_r.html +++ b/doc/html/functions_func_r.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_s.html b/doc/html/functions_func_s.html index ea11e0e50..970d059bb 100644 --- a/doc/html/functions_func_s.html +++ b/doc/html/functions_func_s.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_t.html b/doc/html/functions_func_t.html index e6f9e9e5e..3ee16ad7e 100644 --- a/doc/html/functions_func_t.html +++ b/doc/html/functions_func_t.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_u.html b/doc/html/functions_func_u.html index 57bc2ee3b..6ce16a244 100644 --- a/doc/html/functions_func_u.html +++ b/doc/html/functions_func_u.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_v.html b/doc/html/functions_func_v.html index 66bf5ab27..c8ac37b5e 100644 --- a/doc/html/functions_func_v.html +++ b/doc/html/functions_func_v.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_w.html b/doc/html/functions_func_w.html index dc7d1e1bd..8d64f78f9 100644 --- a/doc/html/functions_func_w.html +++ b/doc/html/functions_func_w.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_x.html b/doc/html/functions_func_x.html index 8df828d85..40834827e 100644 --- a/doc/html/functions_func_x.html +++ b/doc/html/functions_func_x.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_func_~.html b/doc/html/functions_func_~.html index ac6aac5e1..6ac63b531 100644 --- a/doc/html/functions_func_~.html +++ b/doc/html/functions_func_~.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_g.html b/doc/html/functions_g.html index 0a376de43..f1e364273 100644 --- a/doc/html/functions_g.html +++ b/doc/html/functions_g.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_h.html b/doc/html/functions_h.html index f1218beb7..f3707d6ec 100644 --- a/doc/html/functions_h.html +++ b/doc/html/functions_h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_i.html b/doc/html/functions_i.html index 72c23b55c..04fde02c0 100644 --- a/doc/html/functions_i.html +++ b/doc/html/functions_i.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_j.html b/doc/html/functions_j.html index ee0b304e1..6924e1153 100644 --- a/doc/html/functions_j.html +++ b/doc/html/functions_j.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_l.html b/doc/html/functions_l.html index 86ba9aeec..58ec2233c 100644 --- a/doc/html/functions_l.html +++ b/doc/html/functions_l.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_m.html b/doc/html/functions_m.html index 1095c092b..b1841dbab 100644 --- a/doc/html/functions_m.html +++ b/doc/html/functions_m.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_n.html b/doc/html/functions_n.html index c6bbd4458..3aae43950 100644 --- a/doc/html/functions_n.html +++ b/doc/html/functions_n.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_o.html b/doc/html/functions_o.html index 9a8861782..8efe05056 100644 --- a/doc/html/functions_o.html +++ b/doc/html/functions_o.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_p.html b/doc/html/functions_p.html index 48961b421..c9df43906 100644 --- a/doc/html/functions_p.html +++ b/doc/html/functions_p.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_q.html b/doc/html/functions_q.html index b95d6e355..cae901f14 100644 --- a/doc/html/functions_q.html +++ b/doc/html/functions_q.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_r.html b/doc/html/functions_r.html index ca99ee728..1804d5847 100644 --- a/doc/html/functions_r.html +++ b/doc/html/functions_r.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_rela.html b/doc/html/functions_rela.html index 7c25a669a..9811ccb8a 100644 --- a/doc/html/functions_rela.html +++ b/doc/html/functions_rela.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_s.html b/doc/html/functions_s.html index 547e7cf77..643e9c763 100644 --- a/doc/html/functions_s.html +++ b/doc/html/functions_s.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_t.html b/doc/html/functions_t.html index b0e0c7b1e..fc101f76b 100644 --- a/doc/html/functions_t.html +++ b/doc/html/functions_t.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_u.html b/doc/html/functions_u.html index 0755382fc..b6ebf61bf 100644 --- a/doc/html/functions_u.html +++ b/doc/html/functions_u.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_v.html b/doc/html/functions_v.html index f29923117..58a17804e 100644 --- a/doc/html/functions_v.html +++ b/doc/html/functions_v.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars.html b/doc/html/functions_vars.html index dfb3364a9..5126bec89 100644 --- a/doc/html/functions_vars.html +++ b/doc/html/functions_vars.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_b.html b/doc/html/functions_vars_b.html index ebaac7773..838237b36 100644 --- a/doc/html/functions_vars_b.html +++ b/doc/html/functions_vars_b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_c.html b/doc/html/functions_vars_c.html index 46f23cbdf..07303a522 100644 --- a/doc/html/functions_vars_c.html +++ b/doc/html/functions_vars_c.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_d.html b/doc/html/functions_vars_d.html index 723fd3045..41e8d7ad9 100644 --- a/doc/html/functions_vars_d.html +++ b/doc/html/functions_vars_d.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_e.html b/doc/html/functions_vars_e.html index c9fe683e5..b4887f1d8 100644 --- a/doc/html/functions_vars_e.html +++ b/doc/html/functions_vars_e.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_f.html b/doc/html/functions_vars_f.html index 30f4b3442..cf9bd6c62 100644 --- a/doc/html/functions_vars_f.html +++ b/doc/html/functions_vars_f.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_g.html b/doc/html/functions_vars_g.html index fbc362902..10fbd5f4c 100644 --- a/doc/html/functions_vars_g.html +++ b/doc/html/functions_vars_g.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_h.html b/doc/html/functions_vars_h.html index 1301491c9..e287dd398 100644 --- a/doc/html/functions_vars_h.html +++ b/doc/html/functions_vars_h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_l.html b/doc/html/functions_vars_l.html index 05d65027a..eba70f299 100644 --- a/doc/html/functions_vars_l.html +++ b/doc/html/functions_vars_l.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_m.html b/doc/html/functions_vars_m.html index f3ffe08e3..d5a3b2c86 100644 --- a/doc/html/functions_vars_m.html +++ b/doc/html/functions_vars_m.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_n.html b/doc/html/functions_vars_n.html index 5b67768b4..5858524fa 100644 --- a/doc/html/functions_vars_n.html +++ b/doc/html/functions_vars_n.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_o.html b/doc/html/functions_vars_o.html index a89f2173e..611be86c5 100644 --- a/doc/html/functions_vars_o.html +++ b/doc/html/functions_vars_o.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_p.html b/doc/html/functions_vars_p.html index 15774bb6e..8a92dc8a8 100644 --- a/doc/html/functions_vars_p.html +++ b/doc/html/functions_vars_p.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_r.html b/doc/html/functions_vars_r.html index 9460b9b23..68b96533b 100644 --- a/doc/html/functions_vars_r.html +++ b/doc/html/functions_vars_r.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_s.html b/doc/html/functions_vars_s.html index cb842ce9c..f92407766 100644 --- a/doc/html/functions_vars_s.html +++ b/doc/html/functions_vars_s.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_t.html b/doc/html/functions_vars_t.html index b9f6f0800..a1a5dfd71 100644 --- a/doc/html/functions_vars_t.html +++ b/doc/html/functions_vars_t.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_w.html b/doc/html/functions_vars_w.html index a999a3b6e..a608a8ab5 100644 --- a/doc/html/functions_vars_w.html +++ b/doc/html/functions_vars_w.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_x.html b/doc/html/functions_vars_x.html index 43f67ca82..ddb0397ab 100644 --- a/doc/html/functions_vars_x.html +++ b/doc/html/functions_vars_x.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_y.html b/doc/html/functions_vars_y.html index 6eb66ddae..d093ef0f1 100644 --- a/doc/html/functions_vars_y.html +++ b/doc/html/functions_vars_y.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_vars_z.html b/doc/html/functions_vars_z.html index bd7d3ed32..6534a646c 100644 --- a/doc/html/functions_vars_z.html +++ b/doc/html/functions_vars_z.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_w.html b/doc/html/functions_w.html index 4caaaf8ed..2d4cd46ef 100644 --- a/doc/html/functions_w.html +++ b/doc/html/functions_w.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_x.html b/doc/html/functions_x.html index 348f11acf..7531b3697 100644 --- a/doc/html/functions_x.html +++ b/doc/html/functions_x.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_y.html b/doc/html/functions_y.html index 29d1c4416..4844d7fee 100644 --- a/doc/html/functions_y.html +++ b/doc/html/functions_y.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_z.html b/doc/html/functions_z.html index 84d891327..aea9795de 100644 --- a/doc/html/functions_z.html +++ b/doc/html/functions_z.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/functions_~.html b/doc/html/functions_~.html index 77b039fff..a907b8264 100644 --- a/doc/html/functions_~.html +++ b/doc/html/functions_~.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/global_8cpp.html b/doc/html/global_8cpp.html index c9decad11..2f15eb17b 100644 --- a/doc/html/global_8cpp.html +++ b/doc/html/global_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
diff --git a/doc/html/global_8cpp_source.html b/doc/html/global_8cpp_source.html index 3b72258de..fb49e2e9f 100644 --- a/doc/html/global_8cpp_source.html +++ b/doc/html/global_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -3338,96 +3338,103 @@
2992
2993std::string helios::getFileExtension( const std::string &filepath ){
-
2994 std::string ext;
-
2995
-
2996 if( filepath.find_last_of('.')<filepath.size() ){
-
2997 ext = filepath.substr(filepath.find_last_of('.'));
-
2998 }else { // does not contain any .'s
-
2999 return "";
-
3000 }
-
3001
-
3002 //edge case when filepath starts with '.' and there is no file extension (e.g., './myfile')
-
3003 if( filepath.find_last_of('.')==0 ){
-
3004 ext = "";
-
3005
-
3006 //edge case when file is in a hidden directory AND there is no file extension (return empty string)
-
3007 }else if( filepath.find_last_of('/')<filepath.size() && filepath.at(filepath.find_last_of('.')-1)=='/' ){
-
3008 ext = "";
-
3009 }
-
3010
-
3011 //edge case when file is in a hidden directory AND there is no file extension AND file path starts with '.' (return empty string)
-
3012 if( filepath.find_last_of('.')==0 ){
-
3013 ext = "";
-
3014 }
-
3015
-
3016 return ext;
-
3017}
-
-
3018
-
-
3019std::string helios::getFileStem( const std::string &filepath ){
-
3020 std::string fn = filepath;
-
3021 if( filepath.find('/')<filepath.size() ) {
-
3022 fn = filepath.substr(filepath.find_last_of('/') + 1);
-
3023 }else if( filepath.find('\\')<filepath.size() ){
-
3024 fn = filepath.substr(filepath.find_last_of('\\') + 1);
-
3025 }
-
3026
-
3027 if( fn.find('.')<fn.size() ) {
-
3028 fn = fn.substr( 0, fn.find_last_of('.') );
-
3029 }
-
3030
-
3031 return fn;
-
3032}
-
+
2994 std::filesystem::path output_path_fs = filepath;
+
2995 return output_path_fs.extension().string();
+
2996}
+
+
2997
+
+
2998std::string helios::getFileStem( const std::string &filepath ){
+
2999 std::filesystem::path output_path_fs = filepath;
+
3000 return output_path_fs.stem().string();
+
3001}
+
+
3002
+
+
3003std::string helios::getFileName( const std::string &filepath ){
+
3004 std::filesystem::path output_path_fs = filepath;
+
3005 return output_path_fs.filename().string();
+
3006}
+
+
3007
+
+
3008std::string helios::getFilePath( const std::string &filepath, bool trailingslash ){
+
3009 std::filesystem::path output_path_fs = filepath;
+
3010 std::string output_path = output_path_fs.parent_path().string();
+
3011 if( trailingslash ) {
+
3012 if (output_path.find_last_of('/') != output_path.length() - 1) {
+
3013 output_path += "/";
+
3014 }
+
3015 }
+
3016
+
3017 return output_path;
+
3018}
+
+
3019
+
+
3020bool helios::validateOutputPath(std::string &output_path, const std::vector<std::string> &allowable_file_extensions){
+
3021
+
3022 if( output_path.empty() ){ //path was empty
+
3023 return false;
+
3024 }
+
3025
+
3026 std::filesystem::path output_path_fs = output_path;
+
3027
+
3028 std::string output_file = output_path_fs.filename().string();
+
3029 std::string output_file_ext = output_path_fs.extension().string();
+
3030 std::string output_dir = output_path_fs.parent_path().string();
+
3031
+
3032 if( output_file.empty() ) { //path was a directory without a file
3033
-
-
3034std::string helios::getFileName( const std::string &filepath ){
-
3035 if( filepath.find('/')<filepath.size() ) {
-
3036 return filepath.substr(filepath.find_last_of('/') + 1);
-
3037 }else if( filepath.find('\\')==filepath.size() ) {
-
3038 return filepath.substr(filepath.find_last_of('\\') + 1);
-
3039 }else{
-
3040 return filepath;
-
3041 }
-
3042
-
3043}
-
-
3044
-
-
3045std::string helios::getFilePath( const std::string &filepath, bool trailingslash ){
-
3046 if( filepath.find('/')==filepath.size() ){
-
3047 if( trailingslash ){
-
3048 std::string str = "/";
-
3049 return str;
-
3050 }else {
-
3051 std::string str;
-
3052 return str;
-
3053 }
-
3054 }else{
-
3055 if( trailingslash ) {
-
3056 return filepath.substr(0, filepath.find_last_of('/') + 1);
-
3057 }else{
-
3058 return filepath.substr(0, filepath.find_last_of('/'));
-
3059 }
-
3060 }
-
3061}
-
-
3062
-
-
3063std::vector<float> helios::importVectorFromFile(const std::string &filepath){
-
3064
-
3065 std::ifstream stream(filepath.c_str());
-
3066
-
3067 if( !stream.is_open() ){
-
3068 helios_runtime_error("ERROR (helios::importVectorFromFile): File " + filepath + " could not be opened for reading. Check that it exists and that you have permission to read it.");
-
3069 }
-
3070
-
3071 std::istream_iterator<float> start(stream), end;
-
3072 std::vector<float> vec(start, end);
-
3073 return vec;
-
3074
-
3075}
+
3034 // Make sure directory has a trailing slash
+
3035 if (output_dir.find_last_of('/') != output_dir.length() - 1) {
+
3036 output_path += "/";
+
3037 }
+
3038
+
3039 }
+
3040
+
3041 // Create the output directory if it does not exist
+
3042 if ( !output_dir.empty() && !std::filesystem::exists(output_dir)) {
+
3043 if (!std::filesystem::create_directory(output_dir)) {
+
3044 return false;
+
3045 }
+
3046 }
+
3047
+
3048 if( !output_file.empty() && !allowable_file_extensions.empty() ){
+
3049
+
3050 //validate file extension
+
3051 bool valid_extension = false;
+
3052 for( const auto &ext : allowable_file_extensions ){
+
3053 if( output_file_ext == ext ){
+
3054 valid_extension = true;
+
3055 break;
+
3056 }
+
3057 }
+
3058 if( !valid_extension ){
+
3059 return false;
+
3060 }
+
3061
+
3062 }
+
3063
+
3064 return true;
+
3065
+
3066}
+
+
3067
+
+
3068std::vector<float> helios::importVectorFromFile(const std::string &filepath){
+
3069
+
3070 std::ifstream stream(filepath.c_str());
+
3071
+
3072 if( !stream.is_open() ){
+
3073 helios_runtime_error("ERROR (helios::importVectorFromFile): File " + filepath + " could not be opened for reading. Check that it exists and that you have permission to read it.");
+
3074 }
+
3075
+
3076 std::istream_iterator<float> start(stream), end;
+
3077 std::vector<float> vec(start, end);
+
3078 return vec;
+
3079
+
3080}
bool parse_double(const std::string &input_string, double &converted_double)
Convert a string into a double with error checking.
Definition global.cpp:779
@@ -3435,7 +3442,7 @@
bool PNGHasAlpha(const char *filename)
Check whether PNG image file has an alpha/transparency channel.
Definition global.cpp:1352
helios::int4 XMLloadint4(pugi::xml_node node, const char *field)
Function to load and convert a field in a pugi XML node into a int4.
Definition global.cpp:2850
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:140
-
std::vector< float > importVectorFromFile(const std::string &filepath)
Read values contained in a text file into a one-dimensional vector of floats.
Definition global.cpp:3063
+
std::vector< float > importVectorFromFile(const std::string &filepath)
Read values contained in a text file into a one-dimensional vector of floats.
Definition global.cpp:3068
helios::RGBAcolor XMLloadrgba(pugi::xml_node node, const char *field)
Function to load and convert a field in a pugi XML node into an RGBA color vector.
Definition global.cpp:2880
bool parse_float(const std::string &input_string, float &converted_float)
Convert a string into a float with error checking.
Definition global.cpp:763
RGBcolor blend(const RGBcolor &color0, const RGBcolor &color1, float weight)
Blend two RGB colors together.
Definition global.cpp:60
@@ -3452,7 +3459,8 @@
float point_distance(const helios::vec3 &p1, const helios::vec3 &p2)
Function to calculate the distance between two points.
Definition global.cpp:2989
bool parse_uint(const std::string &input_string, uint &converted_uint)
Convert a string into an unsigned integer with error checking.
Definition global.cpp:809
std::string getFileExtension(const std::string &filepath)
Parse a file string to get the extension.
Definition global.cpp:2993
-
std::string getFileName(const std::string &filepath)
Parse a file string to get the filename including extension.
Definition global.cpp:3034
+
bool validateOutputPath(std::string &output_directory, const std::vector< std::string > &allowable_file_extensions={})
Check whether output file and/or directory is valid. Add a trailing slash if it is a directory.
Definition global.cpp:3020
+
std::string getFileName(const std::string &filepath)
Parse a file string to get the filename including extension.
Definition global.cpp:3003
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
bool parse_int(const std::string &input_string, int &converted_int)
Convert a string into an integer with error checking.
Definition global.cpp:794
vec2 parse_xml_tag_vec2(const pugi::xml_node &node, const std::string &tag, const std::string &calling_function)
Parse an XML tag containing a vec2 value (i.e., two space delimited floats)
Definition global.cpp:884
@@ -3465,11 +3473,11 @@
helios::int2 getImageResolutionJPEG(const std::string &filename)
Function to read a JPEG image file into pixel data array.
Definition global.cpp:1744
void writeJPEG(const std::string &filename, uint width, uint height, const std::vector< helios::RGBcolor > &pixel_data)
Function to write a JPEG image based on pixel data.
Definition global.cpp:1786
void readPNG(const std::string &filename, uint &width, uint &height, std::vector< helios::RGBAcolor > &pixel_data)
Function to read a PNG image file into pixel data array.
Definition global.cpp:1505
-
std::string getFileStem(const std::string &filepath)
Parse a file string to get the filename without extension.
Definition global.cpp:3019
+
std::string getFileStem(const std::string &filepath)
Parse a file string to get the filename without extension.
Definition global.cpp:2998
helios::vec3 XMLloadvec3(pugi::xml_node node, const char *field)
Function to load and convert a field in a pugi XML node into a vec3.
Definition global.cpp:2790
void makeIdentityMatrix(float(&T)[16])
Construct an identity matrix.
Definition global.cpp:555
helios::RGBcolor XMLloadrgb(pugi::xml_node node, const char *field)
Function to load and convert a field in a pugi XML node into an RGB color vector.
Definition global.cpp:2865
-
std::string getFilePath(const std::string &filepath, bool trailingslash=true)
Parse a file string to get the path (i.e., portion of the string before the file name).
Definition global.cpp:3045
+
std::string getFilePath(const std::string &filepath, bool trailingslash=true)
Parse a file string to get the path (i.e., portion of the string before the file name).
Definition global.cpp:3008
SphericalCoord nullrotation
Default null SphericalCoord that applies no rotation.
Definition global.cpp:57
std::vector< std::vector< bool > > readPNGAlpha(const std::string &filename)
Function to read the alpha channel from a PNG image.
Definition global.cpp:1406
helios::int3 XMLloadint3(pugi::xml_node node, const char *field)
Function to load and convert a field in a pugi XML node into a int3.
Definition global.cpp:2835
diff --git a/doc/html/global_8h.html b/doc/html/global_8h.html index 574a37702..8b2f15809 100644 --- a/doc/html/global_8h.html +++ b/doc/html/global_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -540,6 +540,9 @@ std::string helios::getFilePath (const std::string &filepath, bool trailingslash=true)  Parse a file string to get the path (i.e., portion of the string before the file name).
  +bool helios::validateOutputPath (std::string &output_directory, const std::vector< std::string > &allowable_file_extensions={}) + Check whether output file and/or directory is valid. Add a trailing slash if it is a directory.
+  std::vector< float > helios::importVectorFromFile (const std::string &filepath)  Read values contained in a text file into a one-dimensional vector of floats.
  @@ -841,7 +844,7 @@

Returns
Filename including extension contained in input string
Note
If the string does not contain a file name, an empty string is returned
-

Definition at line 3034 of file global.cpp.

+

Definition at line 3003 of file global.cpp.

@@ -875,7 +878,7 @@

Returns
File path contained in input string
Note
If the string does not contain a path, an empty string is returned
-

Definition at line 3045 of file global.cpp.

+

Definition at line 3008 of file global.cpp.

@@ -904,7 +907,7 @@

Returns
Filename without extension contained in input string
Note
If the string does not contain a file name, an empty string is returned
-

Definition at line 3019 of file global.cpp.

+

Definition at line 2998 of file global.cpp.

@@ -986,7 +989,7 @@

Returns
One-dimensional vector of floats contained in text file
-

Definition at line 3063 of file global.cpp.

+

Definition at line 3068 of file global.cpp.

@@ -1725,6 +1728,39 @@

Definition at line 140 of file global.cpp.

+

+
+ +

◆ validateOutputPath()

+ +
+
+ + + + + + + + + + + +
bool helios::validateOutputPath (std::string & output_directory,
const std::vector< std::string > & allowable_file_extensions = {} )
+
+ +

Check whether output file and/or directory is valid. Add a trailing slash if it is a directory.

+
Parameters
+ + + +
[in,out]output_path
[in]allowable_file_extensions
+
+
+
Returns
True if directory/file was valid, false otherwise
+ +

Definition at line 3020 of file global.cpp.

+
diff --git a/doc/html/global_8h_source.html b/doc/html/global_8h_source.html index 0e3a20451..656cb7c6a 100644 --- a/doc/html/global_8h_source.html +++ b/doc/html/global_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -591,17 +591,21 @@
1048 std::string getFilePath( const std::string &filepath, bool trailingslash = true );
1049
1051
-
1055 std::vector<float> importVectorFromFile(const std::string &filepath);
-
1056
-
1058 extern SphericalCoord nullrotation;
-
1060 extern vec3 nullorigin;
-
1061
-
1062}
-
1063
-
1064#endif
+
1056 bool validateOutputPath(std::string &output_directory, const std::vector<std::string> &allowable_file_extensions = {});
+
1057
+
1059
+
1063 std::vector<float> importVectorFromFile(const std::string &filepath);
+
1064
+
1066 extern SphericalCoord nullrotation;
+
1068 extern vec3 nullorigin;
+
1069
+
1070}
+
1071
+
1072#endif
bool parse_double(const std::string &input_string, double &converted_double)
Convert a string into a double with error checking.
Definition global.cpp:779
float parse_xml_tag_float(const pugi::xml_node &node, const std::string &tag, const std::string &calling_function)
Parse an XML tag containing a float value.
Definition global.cpp:872
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:140
+
std::vector< float > importVectorFromFile(const std::string &filepath)
Read values contained in a text file into a one-dimensional vector of floats.
Definition global.cpp:3068
bool parse_float(const std::string &input_string, float &converted_float)
Convert a string into a float with error checking.
Definition global.cpp:763
RGBcolor blend(const RGBcolor &color0, const RGBcolor &color1, float weight)
Blend two RGB colors together.
Definition global.cpp:60
vec3 parse_xml_tag_vec3(const pugi::xml_node &node, const std::string &tag, const std::string &calling_function)
Parse an XML tag containing a vec3 value (i.e., three space delimited floats)
Definition global.cpp:896
@@ -614,8 +618,10 @@
bool parse_int(const std::string &input_string, int &converted_int)
Convert a string into an integer with error checking.
Definition global.cpp:794
vec2 parse_xml_tag_vec2(const pugi::xml_node &node, const std::string &tag, const std::string &calling_function)
Parse an XML tag containing a vec2 value (i.e., two space delimited floats)
Definition global.cpp:884
int JulianDay(int day, int month, int year)
Convert calendar day (day,month,year) to Julian day.
Definition global.cpp:1268
+
vec3 nullorigin
Default null vec3 that gives the origin (0,0,0)
Definition global.cpp:58
std::string parse_xml_tag_string(const pugi::xml_node &node, const std::string &tag, const std::string &calling_function)
Parse an XML tag containing a string.
Definition global.cpp:908
void makeIdentityMatrix(float(&T)[16])
Construct an identity matrix.
Definition global.cpp:555
+
SphericalCoord nullrotation
Default null SphericalCoord that applies no rotation.
Definition global.cpp:57
void vecmult(const float M[16], const float v[3], float(&result)[3])
Multiply 4x4 transformation matrix by 3-element vector: T=M*v.
Definition global.cpp:539
int parse_xml_tag_int(const pugi::xml_node &node, const std::string &tag, const std::string &calling_function)
Parse an XML tag containing an integer value.
Definition global.cpp:860
float randu()
Random number from a uniform distribution between 0 and 1.
Definition global.cpp:223
diff --git a/doc/html/globals.html b/doc/html/globals.html index a37918dde..726050183 100644 --- a/doc/html/globals.html +++ b/doc/html/globals.html @@ -38,7 +38,7 @@ Logo -
 v1.3.20 +
 v1.3.21
@@ -154,7 +154,6 @@

- t -

    - v -

    diff --git a/doc/html/globals_enum.html b/doc/html/globals_enum.html index 93fbad592..b153d39a5 100644 --- a/doc/html/globals_enum.html +++ b/doc/html/globals_enum.html @@ -38,7 +38,7 @@ Logo -
     v1.3.20 +
     v1.3.21
    diff --git a/doc/html/globals_func.html b/doc/html/globals_func.html index 4e169b258..706fe4b3e 100644 --- a/doc/html/globals_func.html +++ b/doc/html/globals_func.html @@ -38,7 +38,7 @@ Logo -
     v1.3.20 +
     v1.3.21
    @@ -153,7 +153,6 @@

    - t -

      - v -

      diff --git a/doc/html/grapevine_8cpp.html b/doc/html/grapevine_8cpp.html index a8a81a7fd..1001e917c 100644 --- a/doc/html/grapevine_8cpp.html +++ b/doc/html/grapevine_8cpp.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/grapevine_8cpp_source.html b/doc/html/grapevine_8cpp_source.html index 20114292b..556b61be1 100644 --- a/doc/html/grapevine_8cpp_source.html +++ b/doc/html/grapevine_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/group__compoundobjects.html b/doc/html/group__compoundobjects.html index 2b52cddbd..f0a556d10 100644 --- a/doc/html/group__compoundobjects.html +++ b/doc/html/group__compoundobjects.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/group__functions.html b/doc/html/group__functions.html index 275ae65eb..cfae22ad1 100644 --- a/doc/html/group__functions.html +++ b/doc/html/group__functions.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/group__primitives.html b/doc/html/group__primitives.html index c1eceb107..069202154 100644 --- a/doc/html/group__primitives.html +++ b/doc/html/group__primitives.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/group__timeseries.html b/doc/html/group__timeseries.html index 8ca00bf7b..e1d57eeff 100644 --- a/doc/html/group__timeseries.html +++ b/doc/html/group__timeseries.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/group__vectors.html b/doc/html/group__vectors.html index 9d96724ba..512a79472 100644 --- a/doc/html/group__vectors.html +++ b/doc/html/group__vectors.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/helios__vector__types_8h.html b/doc/html/helios__vector__types_8h.html index c71b2570c..4a42b80ef 100644 --- a/doc/html/helios__vector__types_8h.html +++ b/doc/html/helios__vector__types_8h.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/helios__vector__types_8h_source.html b/doc/html/helios__vector__types_8h_source.html index 7df394c6a..48b3dd04e 100644 --- a/doc/html/helios__vector__types_8h_source.html +++ b/doc/html/helios__vector__types_8h_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/hierarchy.html b/doc/html/hierarchy.html index 08383e175..2b3d78b71 100644 --- a/doc/html/hierarchy.html +++ b/doc/html/hierarchy.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/index.html b/doc/html/index.html index e6acd74d9..3706fe81a 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      @@ -97,7 +97,7 @@
      -
      Helios Documentation v1.3.20
      +
      Helios Documentation v1.3.21


      diff --git a/doc/html/lidar_2include_2random_8h_source.html b/doc/html/lidar_2include_2random_8h_source.html index bdab370fd..73afa6d6e 100644 --- a/doc/html/lidar_2include_2random_8h_source.html +++ b/doc/html/lidar_2include_2random_8h_source.html @@ -38,7 +38,7 @@ Logo -

       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/lidar_2src_2file_i_o_8cpp.html b/doc/html/lidar_2src_2file_i_o_8cpp.html index 75edfc1c3..bfd081bf1 100644 --- a/doc/html/lidar_2src_2file_i_o_8cpp.html +++ b/doc/html/lidar_2src_2file_i_o_8cpp.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/lidar_2src_2file_i_o_8cpp_source.html b/doc/html/lidar_2src_2file_i_o_8cpp_source.html index 297b66f4c..4ca7086b8 100644 --- a/doc/html/lidar_2src_2file_i_o_8cpp_source.html +++ b/doc/html/lidar_2src_2file_i_o_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/main_8cpp_source.html b/doc/html/main_8cpp_source.html index 7581a9d25..57052b7fb 100644 --- a/doc/html/main_8cpp_source.html +++ b/doc/html/main_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      @@ -200,8 +200,8 @@
      Class for visualization of simulation results.
      Definition Visualizer.h:259
      Stores the state associated with simulation.
      Definition Context.h:1882
      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...
      -
      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.
      +
      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...
      +
      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.
      void setDate(int day, int month, int year)
      Set simulation date by day, month, year.
      Definition Context.cpp:1057
      helios::Time getTime() const
      Get the simulation time.
      Definition Context.cpp:1164
      void duplicatePrimitiveData(uint UUID, const char *old_label, const char *new_label)
      Duplicate/copy primitive data.
      diff --git a/doc/html/pages.html b/doc/html/pages.html index 9ce8e6376..e1ff8036a 100644 --- a/doc/html/pages.html +++ b/doc/html/pages.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/plugins_2lidar_2src_2self_test_8cpp.html b/doc/html/plugins_2lidar_2src_2self_test_8cpp.html index a8f4bbca7..48fb7de7a 100644 --- a/doc/html/plugins_2lidar_2src_2self_test_8cpp.html +++ b/doc/html/plugins_2lidar_2src_2self_test_8cpp.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/plugins_2lidar_2src_2self_test_8cpp_source.html b/doc/html/plugins_2lidar_2src_2self_test_8cpp_source.html index 88bb2c30a..832c8d342 100644 --- a/doc/html/plugins_2lidar_2src_2self_test_8cpp_source.html +++ b/doc/html/plugins_2lidar_2src_2self_test_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      @@ -406,7 +406,7 @@
      float getPrimitiveArea(uint UUID) const
      Method to return the surface area of a Primitive.
      Definition Context.cpp:6997
      void getPrimitiveData(uint UUID, const char *label, int &data) const
      Get data associated with a primitive element.
      bool doesPrimitiveDataExist(uint UUID, const char *label) const
      Check if primitive data 'label' exists.
      -
      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...
      +
      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...
      std::vector< uint > getAllUUIDs() const
      Get all primitive UUIDs currently in the Context.
      Definition Context.cpp:1753
      helios::vec3 getPrimitiveNormal(uint UUID) const
      Method to return the normal vector of a Primitive.
      Definition Context.cpp:7048
      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:7066
      diff --git a/doc/html/plugins_2plantarchitecture_2src_2self_test_8cpp.html b/doc/html/plugins_2plantarchitecture_2src_2self_test_8cpp.html index c49721a70..bc6edc746 100644 --- a/doc/html/plugins_2plantarchitecture_2src_2self_test_8cpp.html +++ b/doc/html/plugins_2plantarchitecture_2src_2self_test_8cpp.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/plugins_2plantarchitecture_2src_2self_test_8cpp_source.html b/doc/html/plugins_2plantarchitecture_2src_2self_test_8cpp_source.html index 94fcf7712..65f4a67b9 100644 --- a/doc/html/plugins_2plantarchitecture_2src_2self_test_8cpp_source.html +++ b/doc/html/plugins_2plantarchitecture_2src_2self_test_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/plugins_2radiation_2src_2self_test_8cpp.html b/doc/html/plugins_2radiation_2src_2self_test_8cpp.html index 95eecfef4..cac8cb697 100644 --- a/doc/html/plugins_2radiation_2src_2self_test_8cpp.html +++ b/doc/html/plugins_2radiation_2src_2self_test_8cpp.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/plugins_2radiation_2src_2self_test_8cpp_source.html b/doc/html/plugins_2radiation_2src_2self_test_8cpp_source.html index b4121fd20..fe0a4a464 100644 --- a/doc/html/plugins_2radiation_2src_2self_test_8cpp_source.html +++ b/doc/html/plugins_2radiation_2src_2self_test_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      @@ -1868,14 +1868,14 @@
      void setScatteringDepth(const std::string &label, uint depth)
      Set the number of scattering iterations for a certain band.
      void disableEmission(const std::string &label)
      Disable emission calculations for all primitives in this band.
      void setSourceSpectrum(uint source_ID, const std::vector< helios::vec2 > &spectrum)
      Set the spectral distribution of a radiation source according to a vector of wavelength-intensity pai...
      -
      void runBand(const std::string &label)
      Run the simulation for a single radiative band.
      +
      void runBand(const std::string &label)
      Run the simulation for a single radiative band.
      uint addSunSphereRadiationSource()
      Add a sphere radiation source that models the sun assuming the default direction of (0,...
      uint addDiskRadiationSource(const helios::vec3 &position, float radius, const helios::vec3 &rotation)
      Add planar circular radiation source.
      void setDiffuseRadiationFlux(const std::string &label, float flux)
      Diffuse (ambient) radiation flux.
      void setDiffuseRayCount(const std::string &label, size_t N)
      Sets variable diffuseRayCount, the number of rays to be used in diffuse (ambient) radiation model.
      uint addRectangleRadiationSource(const helios::vec3 &position, const helios::vec2 &size, const helios::vec3 &rotation)
      Add planar rectangular radiation source.
      void setDiffuseRadiationExtinctionCoeff(const std::string &label, float K, const helios::vec3 &peak_dir)
      Extinction coefficient of diffuse ambient radiation.
      -
      void updateGeometry()
      Adds all geometric primitives from the Context to OptiX.
      +
      void updateGeometry()
      Adds all geometric primitives from the Context to OptiX.
      void addRadiationBand(const std::string &label)
      Add a spectral radiation band to the model.
      uint addCollimatedRadiationSource()
      Add an external source of collimated radiation (i.e., source at infinite distance with parallel rays)...
      void addRadiationCamera(const std::string &camera_label, const std::vector< std::string > &band_label, const helios::vec3 &position, const helios::vec3 &lookat, const CameraProperties &camera_properties, uint antialiasing_samples)
      Add a radiation camera sensor.
      diff --git a/doc/html/plugins_2solarposition_2src_2self_test_8cpp_source.html b/doc/html/plugins_2solarposition_2src_2self_test_8cpp_source.html index 5c3b1f335..200a29211 100644 --- a/doc/html/plugins_2solarposition_2src_2self_test_8cpp_source.html +++ b/doc/html/plugins_2solarposition_2src_2self_test_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/primitive_intersection_8cu.html b/doc/html/primitive_intersection_8cu.html index ae3c8f8f6..7ddba7339 100644 --- a/doc/html/primitive_intersection_8cu.html +++ b/doc/html/primitive_intersection_8cu.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/primitive_intersection_8cu_source.html b/doc/html/primitive_intersection_8cu_source.html index 51f48f2df..e3dcd53eb 100644 --- a/doc/html/primitive_intersection_8cu_source.html +++ b/doc/html/primitive_intersection_8cu_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/radiation_2include_2random_8h_source.html b/doc/html/radiation_2include_2random_8h_source.html index 4138aac4c..67d871852 100644 --- a/doc/html/radiation_2include_2random_8h_source.html +++ b/doc/html/radiation_2include_2random_8h_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/radiation__beers_law.html b/doc/html/radiation__beers_law.html index 78775397c..95ebb53e8 100644 --- a/doc/html/radiation__beers_law.html +++ b/doc/html/radiation__beers_law.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/radiation_basics.html b/doc/html/radiation_basics.html index 5275d0b43..799867807 100644 --- a/doc/html/radiation_basics.html +++ b/doc/html/radiation_basics.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/ray_generation_8cu.html b/doc/html/ray_generation_8cu.html index f49745796..364462bf5 100644 --- a/doc/html/ray_generation_8cu.html +++ b/doc/html/ray_generation_8cu.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/ray_generation_8cu_source.html b/doc/html/ray_generation_8cu_source.html index 3acef1486..2b7145397 100644 --- a/doc/html/ray_generation_8cu_source.html +++ b/doc/html/ray_generation_8cu_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/ray_hit_8cu.html b/doc/html/ray_hit_8cu.html index d75def0d1..bc2cbb67f 100644 --- a/doc/html/ray_hit_8cu.html +++ b/doc/html/ray_hit_8cu.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/ray_hit_8cu_source.html b/doc/html/ray_hit_8cu_source.html index f3b707235..7a3ab1bec 100644 --- a/doc/html/ray_hit_8cu_source.html +++ b/doc/html/ray_hit_8cu_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/s__hull__pro_8h_source.html b/doc/html/s__hull__pro_8h_source.html index fbbb22cb2..613c50671 100644 --- a/doc/html/s__hull__pro_8h_source.html +++ b/doc/html/s__hull__pro_8h_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/search/all_10.js b/doc/html/search/all_10.js index 4a3243120..5b7f61ec8 100644 --- a/doc/html/search/all_10.js +++ b/doc/html/search/all_10.js @@ -6,7 +6,7 @@ var searchData= ['height_20maps_3',['2D raster height maps',['../_aerial_li_d_a_r_doc.html#AerialRasters',1,'']]], ['helios_4',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]], ['helios_20context_5',['The Helios Context',['../_overview.html#ContextOverview',1,'']]], - ['helios_20documentation_20v1_203_2020_6',['Helios Documentation v1.3.20',['../index.html',1,'']]], + ['helios_20documentation_20v1_203_2021_6',['Helios Documentation v1.3.21',['../index.html',1,'']]], ['helios_20prerequisites_7',['Helios Prerequisites',['../_overview.html#PrereqsHelios',1,'']]], ['helios_20programming_8',['Which platform to use for Helios programming?',['../_dependent_software.html#WhichPlatform',1,'']]], ['helios_20vector_20types_20tutorial_9',['Tutorial 1: Helios Vector Types Tutorial',['../context_vectors.html',1,'Tutorials']]], diff --git a/doc/html/search/all_1e.js b/doc/html/search/all_1e.js index df4aabaf5..177e2cea3 100644 --- a/doc/html/search/all_1e.js +++ b/doc/html/search/all_1e.js @@ -1,7 +1,7 @@ var searchData= [ - ['v1_203_2020_0',['Helios Documentation v1.3.20',['../index.html',1,'']]], - ['validateoutputpath_1',['validateOutputPath',['../_radiation_model_8h.html#a2d93cfc62b5e610b18411a9e87547f81',1,'validateOutputPath(std::ostringstream &output_directory): RadiationModel.cpp'],['../_radiation_model_8cpp.html#a2d93cfc62b5e610b18411a9e87547f81',1,'validateOutputPath(std::ostringstream &output_directory): RadiationModel.cpp']]], + ['v1_203_2021_0',['Helios Documentation v1.3.21',['../index.html',1,'']]], + ['validateoutputpath_1',['validateOutputPath',['../global_8h.html#a614486c4ac0686c5b58813f03f0cedf9',1,'helios']]], ['values_2',['Values',['../_a_p_i.html#GetPrimData',1,'Getting Primitive Data Values'],['../_canopy_generator_doc.html#CGenParameterMod',1,'Modifying Geometric Parameters from Default Values'],['../_a_p_i.html#SetPrimData',1,'Setting Primitive Data Values']]], ['values_3',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]], ['variables_4',['Variables',['../_b_l_conductance_doc.html#BLPrimData',1,'Input Variables'],['../_energy_balance_doc.html#EBPrimData',1,'Input Variables'],['../_photosynthesis_doc.html#PhotoVars',1,'Summary of Empirical Model Independent Variables'],['../_photosynthesis_doc.html#FvCBPhotoVars',1,'Summary of FvCB Model Independent Variables']]], diff --git a/doc/html/search/all_2.js b/doc/html/search/all_2.js index fc37edefc..750b3804e 100644 --- a/doc/html/search/all_2.js +++ b/doc/html/search/all_2.js @@ -5,10 +5,10 @@ var searchData= ['2_20radiation_20model_20set_20up_2',['2. Radiation model set-up',['../radiation_basics.html#Tutorial10_rad',1,'']]], ['2_20rotating_20and_20cropping_20optional_3',['2. Rotating and cropping (OPTIONAL)',['../_making_masks.html#Two',1,'']]], ['2_20slicing_20and_20cropping_20primitives_20on_20the_20boundaries_4',['2. Slicing and cropping primitives on the boundaries',['../radiation__beers_law.html#tutorial11_slice',1,'']]], - ['20_5',['Helios Documentation v1.3.20',['../index.html',1,'']]], - ['2003_20model_20simplified_20version_20given_20in_20buckley_20turnbull_20and_20adams_202012_6',['Buckley, Mott, Farquhar (2003) Model (simplified version given in Buckley, Turnbull, and Adams 2012)',['../_stomatal_doc.html#BMFTheory',1,'']]], - ['2011_20optimality_20based_20model_7',['Medlyn et al. (2011) Optimality-Based Model',['../_stomatal_doc.html#MoptTheory',1,'']]], - ['2012_8',['Buckley, Mott, Farquhar (2003) Model (simplified version given in Buckley, Turnbull, and Adams 2012)',['../_stomatal_doc.html#BMFTheory',1,'']]], + ['2003_20model_20simplified_20version_20given_20in_20buckley_20turnbull_20and_20adams_202012_5',['Buckley, Mott, Farquhar (2003) Model (simplified version given in Buckley, Turnbull, and Adams 2012)',['../_stomatal_doc.html#BMFTheory',1,'']]], + ['2011_20optimality_20based_20model_6',['Medlyn et al. (2011) Optimality-Based Model',['../_stomatal_doc.html#MoptTheory',1,'']]], + ['2012_7',['Buckley, Mott, Farquhar (2003) Model (simplified version given in Buckley, Turnbull, and Adams 2012)',['../_stomatal_doc.html#BMFTheory',1,'']]], + ['21_8',['Helios Documentation v1.3.21',['../index.html',1,'']]], ['2_3a_20working_20with_20context_20geometry_9',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]], ['2d_20raster_20ground_20cover_20fraction_10',['2D raster ground cover fraction',['../_aerial_li_d_a_r_doc.html#AerialGroundCover',1,'']]], ['2d_20raster_20height_20maps_11',['2D raster height maps',['../_aerial_li_d_a_r_doc.html#AerialRasters',1,'']]] diff --git a/doc/html/search/all_3.js b/doc/html/search/all_3.js index 70098134e..e6ba469cb 100644 --- a/doc/html/search/all_3.js +++ b/doc/html/search/all_3.js @@ -1,6 +1,6 @@ var searchData= [ - ['3_2020_0',['Helios Documentation v1.3.20',['../index.html',1,'']]], + ['3_2021_0',['Helios Documentation v1.3.21',['../index.html',1,'']]], ['3_20laminar_20flow_20around_20a_20sphere_1',['3. Laminar flow around a sphere',['../_b_l_conductance_doc.html#BLC3',1,'']]], ['3_20modify_20visualizer_20options_2',['Step 3. Modify Visualizer options',['../visualizer_basics.html#vis_step3',1,'']]], ['3_20radiation_20model_20set_20up_3',['3. Radiation model set-up',['../radiation__beers_law.html#tutorial11_rad',1,'']]], diff --git a/doc/html/search/all_c.js b/doc/html/search/all_c.js index 17f6999ab..f03c235c2 100644 --- a/doc/html/search/all_c.js +++ b/doc/html/search/all_c.js @@ -88,7 +88,7 @@ var searchData= ['distribution_20and_20normalization_85',['Setting the Radiation Source Spectral Distribution and Normalization',['../_radiation_doc.html#SourceDist',1,'']]], ['distribution_20functions_86',['User-Defined Leaf Angle Distribution Functions',['../_weber_penn_doc.html#WPTgL',1,'']]], ['documentation_87',['Documentation',['../_aerial_li_d_a_r_doc.html',1,'Aerial LiDAR Point Cloud Plugin Documentation'],['../_b_l_conductance_doc.html',1,'Boundary-Layer Conductance Model Plugin Documentation'],['../_canopy_generator_doc.html',1,'Canopy Generator Plugin Documentation'],['../_dummy.html',1,'Dummy Model Plugin Documentation'],['../_energy_balance_doc.html',1,'Energy Balance Model Plugin Documentation'],['../_li_d_a_r_doc.html',1,'LiDAR Point Cloud Plugin Documentation'],['../_photosynthesis_doc.html',1,'Photosynthesis Model Plugin Documentation'],['../_plant_architecture_doc.html',1,'Plant Architecture Model Plugin Documentation'],['../_radiation_doc.html',1,'Radiation Model Plugin Documentation'],['../_solar_position_doc.html',1,'Solar Position Plugin Documentation'],['../_stomatal_doc.html',1,'Stomatal Conductance Model Plugin Documentation'],['../_overview.html#DocOverview',1,'Using the Documentation'],['../_visualizer_doc.html',1,'Visualizer Plugin Documentation'],['../_voxel_intersection_doc.html',1,'Voxel Intersection Plugin Documentation'],['../_weber_penn_doc.html',1,'Weber-Penn Tree Plugin Documentation'],['../_plugins.html#PluginWriting',1,'Writing Documentation']]], - ['documentation_20v1_203_2020_88',['Helios Documentation v1.3.20',['../index.html',1,'']]], + ['documentation_20v1_203_2021_88',['Helios Documentation v1.3.21',['../index.html',1,'']]], ['doesbandexist_89',['doesBandExist',['../class_radiation_model.html#a966780925811e3a710a6d91f4ac852fb',1,'RadiationModel']]], ['doesglobaldataexist_90',['doesGlobalDataExist',['../classhelios_1_1_context.html#a65ad9cb057b0cb2be3ef2734847608cc',1,'helios::Context']]], ['doeshitdataexist_91',['doesHitDataExist',['../class_aerial_li_d_a_rcloud.html#a9b5aa652c94d4dee19a4f956a62f2ab1',1,'AerialLiDARcloud::doesHitDataExist()'],['../class_li_d_a_rcloud.html#aabb8d404b7f3fa00d8281cb6b74f90c0',1,'LiDARcloud::doesHitDataExist()']]], diff --git a/doc/html/search/functions_14.js b/doc/html/search/functions_14.js index a699af3e2..782161bec 100644 --- a/doc/html/search/functions_14.js +++ b/doc/html/search/functions_14.js @@ -1,6 +1,6 @@ var searchData= [ - ['validateoutputpath_0',['validateOutputPath',['../_radiation_model_8h.html#a2d93cfc62b5e610b18411a9e87547f81',1,'validateOutputPath(std::ostringstream &output_directory): RadiationModel.cpp'],['../_radiation_model_8cpp.html#a2d93cfc62b5e610b18411a9e87547f81',1,'validateOutputPath(std::ostringstream &output_directory): RadiationModel.cpp']]], + ['validateoutputpath_0',['validateOutputPath',['../global_8h.html#a614486c4ac0686c5b58813f03f0cedf9',1,'helios']]], ['vec2_1',['vec2',['../structhelios_1_1vec2.html#a951e897069d3cc32a062667a54422882',1,'helios::vec2::vec2()'],['../structhelios_1_1vec2.html#a4b3c6f1a3d5f981fd5c0b858088462aa',1,'helios::vec2::vec2(const std::vector< float > &v)'],['../structhelios_1_1vec2.html#a61b92b2d15fa008486ca55b7baf3d8ce',1,'helios::vec2::vec2(const float v[2])'],['../structhelios_1_1vec2.html#af23055ca8145b094c275e9790c1ef8c2',1,'helios::vec2::vec2(float v0, float v1)']]], ['vec3_2',['vec3',['../structhelios_1_1vec3.html#a872ffa408ca0c7a9ae8f48bdcb1ff59f',1,'helios::vec3::vec3()'],['../structhelios_1_1vec3.html#ad72bf7ebc0bf7a337c33fd804b047f17',1,'helios::vec3::vec3(const std::vector< float > &v)'],['../structhelios_1_1vec3.html#a674873bc59af57ba7149ad5339e45266',1,'helios::vec3::vec3(const float v[3])'],['../structhelios_1_1vec3.html#a98f0ea866d759cc41f85af848bd47392',1,'helios::vec3::vec3(float v0, float v1, float v2)']]], ['vec4_3',['vec4',['../structhelios_1_1vec4.html#a94756adab8fcf1382e2bde79c00014f0',1,'helios::vec4::vec4()'],['../structhelios_1_1vec4.html#a2fbcf26c016cdceafd9f3354b430363d',1,'helios::vec4::vec4(const std::vector< float > &v)'],['../structhelios_1_1vec4.html#ab92cc5f8e93238b01c9639f011347281',1,'helios::vec4::vec4(const float v[4])'],['../structhelios_1_1vec4.html#ade4e8c762963b0ce0a195805f1ebccbd',1,'helios::vec4::vec4(float v0, float v1, float v2, float v3)']]], diff --git a/doc/html/search/pages_19.js b/doc/html/search/pages_19.js index c3c145cde..91c14dfcb 100644 --- a/doc/html/search/pages_19.js +++ b/doc/html/search/pages_19.js @@ -1,6 +1,6 @@ var searchData= [ - ['v1_203_2020_0',['Helios Documentation v1.3.20',['../index.html',1,'']]], + ['v1_203_2021_0',['Helios Documentation v1.3.21',['../index.html',1,'']]], ['values_1',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]], ['vector_20types_20tutorial_2',['Tutorial 1: Helios Vector Types Tutorial',['../context_vectors.html',1,'Tutorials']]], ['version_3',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]], diff --git a/doc/html/search/pages_2.js b/doc/html/search/pages_2.js index 8faf38e53..aeca192e7 100644 --- a/doc/html/search/pages_2.js +++ b/doc/html/search/pages_2.js @@ -1,5 +1,5 @@ var searchData= [ - ['20_0',['Helios Documentation v1.3.20',['../index.html',1,'']]], + ['21_0',['Helios Documentation v1.3.21',['../index.html',1,'']]], ['2_3a_20working_20with_20context_20geometry_1',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]] ]; diff --git a/doc/html/search/pages_3.js b/doc/html/search/pages_3.js index 11c4a7ee0..39ecc1a40 100644 --- a/doc/html/search/pages_3.js +++ b/doc/html/search/pages_3.js @@ -1,4 +1,4 @@ var searchData= [ - ['3_2020_0',['Helios Documentation v1.3.20',['../index.html',1,'']]] + ['3_2021_0',['Helios Documentation v1.3.21',['../index.html',1,'']]] ]; diff --git a/doc/html/search/pages_b.js b/doc/html/search/pages_b.js index bcba025e6..a551f08b9 100644 --- a/doc/html/search/pages_b.js +++ b/doc/html/search/pages_b.js @@ -3,7 +3,7 @@ var searchData= ['data_0',['Data',['../context_primdata.html',1,'Tutorial 5: Primitive Data'],['../context_globaldata.html',1,'Tutorial 6: Global Data']]], ['data_20values_1',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]], ['documentation_2',['Documentation',['../_aerial_li_d_a_r_doc.html',1,'Aerial LiDAR Point Cloud Plugin Documentation'],['../_b_l_conductance_doc.html',1,'Boundary-Layer Conductance Model Plugin Documentation'],['../_canopy_generator_doc.html',1,'Canopy Generator Plugin Documentation'],['../_dummy.html',1,'Dummy Model Plugin Documentation'],['../_energy_balance_doc.html',1,'Energy Balance Model Plugin Documentation'],['../_li_d_a_r_doc.html',1,'LiDAR Point Cloud Plugin Documentation'],['../_photosynthesis_doc.html',1,'Photosynthesis Model Plugin Documentation'],['../_plant_architecture_doc.html',1,'Plant Architecture Model Plugin Documentation'],['../_radiation_doc.html',1,'Radiation Model Plugin Documentation'],['../_solar_position_doc.html',1,'Solar Position Plugin Documentation'],['../_stomatal_doc.html',1,'Stomatal Conductance Model Plugin Documentation'],['../_visualizer_doc.html',1,'Visualizer Plugin Documentation'],['../_voxel_intersection_doc.html',1,'Voxel Intersection Plugin Documentation'],['../_weber_penn_doc.html',1,'Weber-Penn Tree Plugin Documentation']]], - ['documentation_20v1_203_2020_3',['Helios Documentation v1.3.20',['../index.html',1,'']]], + ['documentation_20v1_203_2021_3',['Helios Documentation v1.3.21',['../index.html',1,'']]], ['driver_20timeout_4',['Increasing graphics driver timeout',['../_p_c_g_p_u_timeout.html',1,'']]], ['dummy_20model_20plugin_20documentation_5',['Dummy Model Plugin Documentation',['../_dummy.html',1,'']]] ]; diff --git a/doc/html/search/pages_f.js b/doc/html/search/pages_f.js index 471254293..2ac7291d1 100644 --- a/doc/html/search/pages_f.js +++ b/doc/html/search/pages_f.js @@ -1,7 +1,7 @@ var searchData= [ ['helios_0',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]], - ['helios_20documentation_20v1_203_2020_1',['Helios Documentation v1.3.20',['../index.html',1,'']]], + ['helios_20documentation_20v1_203_2021_1',['Helios Documentation v1.3.21',['../index.html',1,'']]], ['helios_20vector_20types_20tutorial_2',['Tutorial 1: Helios Vector Types Tutorial',['../context_vectors.html',1,'Tutorials']]], ['homogeneous_20canopy_3',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]] ]; diff --git a/doc/html/sorghum_8cpp_source.html b/doc/html/sorghum_8cpp_source.html index 13b0a0979..afd9dc643 100644 --- a/doc/html/sorghum_8cpp_source.html +++ b/doc/html/sorghum_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/strawberry_8cpp_source.html b/doc/html/strawberry_8cpp_source.html index cdf810850..d767a4f0e 100644 --- a/doc/html/strawberry_8cpp_source.html +++ b/doc/html/strawberry_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_aerial_hit_point.html b/doc/html/struct_aerial_hit_point.html index d4534c09a..3a828ba2d 100644 --- a/doc/html/struct_aerial_hit_point.html +++ b/doc/html/struct_aerial_hit_point.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_aerial_scan_metadata.html b/doc/html/struct_aerial_scan_metadata.html index 45467df7c..47de8edd2 100644 --- a/doc/html/struct_aerial_scan_metadata.html +++ b/doc/html/struct_aerial_scan_metadata.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_axis_rotation.html b/doc/html/struct_axis_rotation.html index e7257d8af..8840fd9ea 100644 --- a/doc/html/struct_axis_rotation.html +++ b/doc/html/struct_axis_rotation.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_b_b_lcoefficients.html b/doc/html/struct_b_b_lcoefficients.html index faa930f63..6b42bb354 100644 --- a/doc/html/struct_b_b_lcoefficients.html +++ b/doc/html/struct_b_b_lcoefficients.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_b_bcoefficients.html b/doc/html/struct_b_bcoefficients.html index 3be20acca..870352ddb 100644 --- a/doc/html/struct_b_bcoefficients.html +++ b/doc/html/struct_b_bcoefficients.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_b_m_fcoefficients.html b/doc/html/struct_b_m_fcoefficients.html index 300e9322d..d379ec429 100644 --- a/doc/html/struct_b_m_fcoefficients.html +++ b/doc/html/struct_b_m_fcoefficients.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_b_w_bcoefficients.html b/doc/html/struct_b_w_bcoefficients.html index 31c6c19f8..11a9757e6 100644 --- a/doc/html/struct_b_w_bcoefficients.html +++ b/doc/html/struct_b_w_bcoefficients.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_base_canopy_parameters.html b/doc/html/struct_base_canopy_parameters.html index 2885cb519..f0657a348 100644 --- a/doc/html/struct_base_canopy_parameters.html +++ b/doc/html/struct_base_canopy_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_base_grape_vine_parameters.html b/doc/html/struct_base_grape_vine_parameters.html index 9111cf44d..30f219a5d 100644 --- a/doc/html/struct_base_grape_vine_parameters.html +++ b/doc/html/struct_base_grape_vine_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_bean_parameters.html b/doc/html/struct_bean_parameters.html index 57a64634b..b24dd0402 100644 --- a/doc/html/struct_bean_parameters.html +++ b/doc/html/struct_bean_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_camera_calibration.html b/doc/html/struct_camera_calibration.html index 70ba19fcc..868ba194c 100644 --- a/doc/html/struct_camera_calibration.html +++ b/doc/html/struct_camera_calibration.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_camera_calibration_1_1_gradient_descent_parameters.html b/doc/html/struct_camera_calibration_1_1_gradient_descent_parameters.html index c3370c093..c98866d26 100644 --- a/doc/html/struct_camera_calibration_1_1_gradient_descent_parameters.html +++ b/doc/html/struct_camera_calibration_1_1_gradient_descent_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_camera_properties.html b/doc/html/struct_camera_properties.html index 9b5486bfb..004ca12b5 100644 --- a/doc/html/struct_camera_properties.html +++ b/doc/html/struct_camera_properties.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_colormap.html b/doc/html/struct_colormap.html index ebfc8405d..b2b7cd2bf 100644 --- a/doc/html/struct_colormap.html +++ b/doc/html/struct_colormap.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_conical_crowns_canopy_parameters.html b/doc/html/struct_conical_crowns_canopy_parameters.html index 3a664d729..9ea0abcd9 100644 --- a/doc/html/struct_conical_crowns_canopy_parameters.html +++ b/doc/html/struct_conical_crowns_canopy_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_dupex.html b/doc/html/struct_dupex.html index 5a652ebf1..17afa4a60 100644 --- a/doc/html/struct_dupex.html +++ b/doc/html/struct_dupex.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_empirical_model_coefficients.html b/doc/html/struct_empirical_model_coefficients.html index 841d6938c..1569ebbb8 100644 --- a/doc/html/struct_empirical_model_coefficients.html +++ b/doc/html/struct_empirical_model_coefficients.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_farquhar_model_coefficients.html b/doc/html/struct_farquhar_model_coefficients.html index 3a2ff150d..f54249885 100644 --- a/doc/html/struct_farquhar_model_coefficients.html +++ b/doc/html/struct_farquhar_model_coefficients.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_floral_bud.html b/doc/html/struct_floral_bud.html index aecd8d789..350d34397 100644 --- a/doc/html/struct_floral_bud.html +++ b/doc/html/struct_floral_bud.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_goblet_grapevine_parameters.html b/doc/html/struct_goblet_grapevine_parameters.html index 9e94c3394..6a1baaf93 100644 --- a/doc/html/struct_goblet_grapevine_parameters.html +++ b/doc/html/struct_goblet_grapevine_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_grid_cell.html b/doc/html/struct_grid_cell.html index c019b1c21..cbff13723 100644 --- a/doc/html/struct_grid_cell.html +++ b/doc/html/struct_grid_cell.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_hit_point.html b/doc/html/struct_hit_point.html index 43e8d9cd7..f04d7155d 100644 --- a/doc/html/struct_hit_point.html +++ b/doc/html/struct_hit_point.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_homogeneous_canopy_parameters.html b/doc/html/struct_homogeneous_canopy_parameters.html index 9092eb6de..1faa0d005 100644 --- a/doc/html/struct_homogeneous_canopy_parameters.html +++ b/doc/html/struct_homogeneous_canopy_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_leaf_optics_properties.html b/doc/html/struct_leaf_optics_properties.html index 7fc8363e1..115d96d5b 100644 --- a/doc/html/struct_leaf_optics_properties.html +++ b/doc/html/struct_leaf_optics_properties.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_m_o_p_tcoefficients.html b/doc/html/struct_m_o_p_tcoefficients.html index 42b820f2c..363f09faf 100644 --- a/doc/html/struct_m_o_p_tcoefficients.html +++ b/doc/html/struct_m_o_p_tcoefficients.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_per_ray_data.html b/doc/html/struct_per_ray_data.html index f0293b644..1afadaad4 100644 --- a/doc/html/struct_per_ray_data.html +++ b/doc/html/struct_per_ray_data.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_photosynthetic_temperature_response_parameters.html b/doc/html/struct_photosynthetic_temperature_response_parameters.html index b8c4476e4..9bf61b4f6 100644 --- a/doc/html/struct_photosynthetic_temperature_response_parameters.html +++ b/doc/html/struct_photosynthetic_temperature_response_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_phytomer.html b/doc/html/struct_phytomer.html index ffc88a186..eb8318f9c 100644 --- a/doc/html/struct_phytomer.html +++ b/doc/html/struct_phytomer.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      @@ -360,7 +360,7 @@

      -

      Definition at line 1769 of file PlantArchitecture.cpp.

      +

      Definition at line 1770 of file PlantArchitecture.cpp.

      @@ -585,7 +585,7 @@

      -

      Definition at line 1765 of file PlantArchitecture.cpp.

      +

      Definition at line 1766 of file PlantArchitecture.cpp.

      @@ -604,7 +604,7 @@

      -

      Definition at line 1744 of file PlantArchitecture.cpp.

      +

      Definition at line 1745 of file PlantArchitecture.cpp.

      @@ -632,7 +632,7 @@

      -

      Definition at line 1485 of file PlantArchitecture.cpp.

      +

      Definition at line 1486 of file PlantArchitecture.cpp.

      @@ -659,7 +659,7 @@

      Definition at line 1586 of file PlantArchitecture.cpp.

      +

      Definition at line 1587 of file PlantArchitecture.cpp.

      @@ -678,7 +678,7 @@

      -

      Definition at line 1700 of file PlantArchitecture.cpp.

      +

      Definition at line 1701 of file PlantArchitecture.cpp.

      @@ -771,7 +771,7 @@

      -

      Definition at line 1725 of file PlantArchitecture.cpp.

      +

      Definition at line 1726 of file PlantArchitecture.cpp.

      @@ -794,7 +794,7 @@

      -

      Definition at line 1539 of file PlantArchitecture.cpp.

      +

      Definition at line 1540 of file PlantArchitecture.cpp.

      @@ -821,7 +821,7 @@

      Definition at line 1597 of file PlantArchitecture.cpp.

      +

      Definition at line 1598 of file PlantArchitecture.cpp.

      @@ -848,7 +848,7 @@

      Definition at line 1602 of file PlantArchitecture.cpp.

      +

      Definition at line 1603 of file PlantArchitecture.cpp.

      @@ -875,7 +875,7 @@

      Definition at line 1678 of file PlantArchitecture.cpp.

      +

      Definition at line 1679 of file PlantArchitecture.cpp.

      @@ -902,7 +902,7 @@

      Definition at line 1608 of file PlantArchitecture.cpp.

      +

      Definition at line 1609 of file PlantArchitecture.cpp.

      @@ -921,7 +921,7 @@

      -

      Definition at line 1450 of file PlantArchitecture.cpp.

      +

      Definition at line 1451 of file PlantArchitecture.cpp.

      diff --git a/doc/html/struct_phytomer_parameters.html b/doc/html/struct_phytomer_parameters.html index ddab06aa8..653d94b7d 100644 --- a/doc/html/struct_phytomer_parameters.html +++ b/doc/html/struct_phytomer_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_plant_instance.html b/doc/html/struct_plant_instance.html index b411e219f..b372f1e0e 100644 --- a/doc/html/struct_plant_instance.html +++ b/doc/html/struct_plant_instance.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_radiation_band.html b/doc/html/struct_radiation_band.html index 74e09d188..25c849657 100644 --- a/doc/html/struct_radiation_band.html +++ b/doc/html/struct_radiation_band.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_radiation_camera.html b/doc/html/struct_radiation_camera.html index a5c58538b..7a5d474e7 100644 --- a/doc/html/struct_radiation_camera.html +++ b/doc/html/struct_radiation_camera.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_radiation_source.html b/doc/html/struct_radiation_source.html index 0317cadb1..3fc06d3e5 100644 --- a/doc/html/struct_radiation_source.html +++ b/doc/html/struct_radiation_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_random_parameter__float.html b/doc/html/struct_random_parameter__float.html index 0a68a1b2c..24c4f2e86 100644 --- a/doc/html/struct_random_parameter__float.html +++ b/doc/html/struct_random_parameter__float.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_random_parameter__int.html b/doc/html/struct_random_parameter__int.html index 33736283d..c7e89d19a 100644 --- a/doc/html/struct_random_parameter__int.html +++ b/doc/html/struct_random_parameter__int.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_scan_metadata.html b/doc/html/struct_scan_metadata.html index 68384a7e0..351012832 100644 --- a/doc/html/struct_scan_metadata.html +++ b/doc/html/struct_scan_metadata.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_shader.html b/doc/html/struct_shader.html index 0514756ae..2fd724e7f 100644 --- a/doc/html/struct_shader.html +++ b/doc/html/struct_shader.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_shoot.html b/doc/html/struct_shoot.html index e87437303..a763b71b0 100644 --- a/doc/html/struct_shoot.html +++ b/doc/html/struct_shoot.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      @@ -284,7 +284,7 @@

      -

      Definition at line 1773 of file PlantArchitecture.cpp.

      +

      Definition at line 1774 of file PlantArchitecture.cpp.

      @@ -406,7 +406,7 @@

      -

      Definition at line 1788 of file PlantArchitecture.cpp.

      +

      Definition at line 1789 of file PlantArchitecture.cpp.

      @@ -510,7 +510,7 @@

      Returns
      false if the bud dies, true if the bud survives and will produce a new shoot.
      -

      Definition at line 1812 of file PlantArchitecture.cpp.

      +

      Definition at line 1813 of file PlantArchitecture.cpp.

      @@ -543,7 +543,7 @@

      Returns
      Number of epicormic shoots to be produced; position of the epicormic shoot as a fraction of the shoot's length
      -

      Definition at line 1854 of file PlantArchitecture.cpp.

      +

      Definition at line 1855 of file PlantArchitecture.cpp.

      diff --git a/doc/html/struct_shoot_parameters.html b/doc/html/struct_shoot_parameters.html index 90791186c..ef1e7e9d6 100644 --- a/doc/html/struct_shoot_parameters.html +++ b/doc/html/struct_shoot_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_shx.html b/doc/html/struct_shx.html index 44fa84e14..54ad16d3a 100644 --- a/doc/html/struct_shx.html +++ b/doc/html/struct_shx.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_sorghum_canopy_parameters.html b/doc/html/struct_sorghum_canopy_parameters.html index 020583a2f..3de67fde5 100644 --- a/doc/html/struct_sorghum_canopy_parameters.html +++ b/doc/html/struct_sorghum_canopy_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_spherical_crowns_canopy_parameters.html b/doc/html/struct_spherical_crowns_canopy_parameters.html index 62f907c4c..23afa69d4 100644 --- a/doc/html/struct_spherical_crowns_canopy_parameters.html +++ b/doc/html/struct_spherical_crowns_canopy_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_split_grapevine_parameters.html b/doc/html/struct_split_grapevine_parameters.html index df723dd17..3448c78fe 100644 --- a/doc/html/struct_split_grapevine_parameters.html +++ b/doc/html/struct_split_grapevine_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_strawberry_parameters.html b/doc/html/struct_strawberry_parameters.html index 03bc9a563..27794ae54 100644 --- a/doc/html/struct_strawberry_parameters.html +++ b/doc/html/struct_strawberry_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_tomato_parameters.html b/doc/html/struct_tomato_parameters.html index e9e865e0d..e9e42abe2 100644 --- a/doc/html/struct_tomato_parameters.html +++ b/doc/html/struct_tomato_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_triad.html b/doc/html/struct_triad.html index bb81a7045..1c7573103 100644 --- a/doc/html/struct_triad.html +++ b/doc/html/struct_triad.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_triangulation.html b/doc/html/struct_triangulation.html index a40908a18..df9d5089d 100644 --- a/doc/html/struct_triangulation.html +++ b/doc/html/struct_triangulation.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_unilateral_grapevine_parameters.html b/doc/html/struct_unilateral_grapevine_parameters.html index 8e060d5fd..c97566fcb 100644 --- a/doc/html/struct_unilateral_grapevine_parameters.html +++ b/doc/html/struct_unilateral_grapevine_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_v_s_p_grapevine_parameters.html b/doc/html/struct_v_s_p_grapevine_parameters.html index 430d81c59..95004e32c 100644 --- a/doc/html/struct_v_s_p_grapevine_parameters.html +++ b/doc/html/struct_v_s_p_grapevine_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_vegetative_bud.html b/doc/html/struct_vegetative_bud.html index 1dc2d43e9..b1a535512 100644 --- a/doc/html/struct_vegetative_bud.html +++ b/doc/html/struct_vegetative_bud.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_walnut_canopy_parameters.html b/doc/html/struct_walnut_canopy_parameters.html index 43f164754..a5ae52405 100644 --- a/doc/html/struct_walnut_canopy_parameters.html +++ b/doc/html/struct_walnut_canopy_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_weber_penn_tree_parameters.html b/doc/html/struct_weber_penn_tree_parameters.html index 7defcbbc8..43ca7cb63 100644 --- a/doc/html/struct_weber_penn_tree_parameters.html +++ b/doc/html/struct_weber_penn_tree_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/struct_white_spruce_canopy_parameters.html b/doc/html/struct_white_spruce_canopy_parameters.html index 8de533278..97bf15049 100644 --- a/doc/html/struct_white_spruce_canopy_parameters.html +++ b/doc/html/struct_white_spruce_canopy_parameters.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structhelios_1_1_date.html b/doc/html/structhelios_1_1_date.html index 733d079d7..070a6a36d 100644 --- a/doc/html/structhelios_1_1_date.html +++ b/doc/html/structhelios_1_1_date.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structhelios_1_1_global_data.html b/doc/html/structhelios_1_1_global_data.html index b6f8c9580..1ca86e370 100644 --- a/doc/html/structhelios_1_1_global_data.html +++ b/doc/html/structhelios_1_1_global_data.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structhelios_1_1_r_g_b_acolor.html b/doc/html/structhelios_1_1_r_g_b_acolor.html index e1282ebc2..550c7958c 100644 --- a/doc/html/structhelios_1_1_r_g_b_acolor.html +++ b/doc/html/structhelios_1_1_r_g_b_acolor.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structhelios_1_1_r_g_bcolor.html b/doc/html/structhelios_1_1_r_g_bcolor.html index 4547f6bd9..3a59a90da 100644 --- a/doc/html/structhelios_1_1_r_g_bcolor.html +++ b/doc/html/structhelios_1_1_r_g_bcolor.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structhelios_1_1_spherical_coord.html b/doc/html/structhelios_1_1_spherical_coord.html index bb3355d3f..0ccbaf43e 100644 --- a/doc/html/structhelios_1_1_spherical_coord.html +++ b/doc/html/structhelios_1_1_spherical_coord.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structhelios_1_1_time.html b/doc/html/structhelios_1_1_time.html index 259d597f7..ae3928ed5 100644 --- a/doc/html/structhelios_1_1_time.html +++ b/doc/html/structhelios_1_1_time.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structhelios_1_1_timer.html b/doc/html/structhelios_1_1_timer.html index 118b0ff97..87bf44088 100644 --- a/doc/html/structhelios_1_1_timer.html +++ b/doc/html/structhelios_1_1_timer.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structhelios_1_1int2.html b/doc/html/structhelios_1_1int2.html index f39c2375f..99facc68d 100644 --- a/doc/html/structhelios_1_1int2.html +++ b/doc/html/structhelios_1_1int2.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structhelios_1_1int3.html b/doc/html/structhelios_1_1int3.html index 4a3d4f784..f4e0c2325 100644 --- a/doc/html/structhelios_1_1int3.html +++ b/doc/html/structhelios_1_1int3.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structhelios_1_1int4.html b/doc/html/structhelios_1_1int4.html index 54d74e2ae..a0da65f68 100644 --- a/doc/html/structhelios_1_1int4.html +++ b/doc/html/structhelios_1_1int4.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structhelios_1_1vec2.html b/doc/html/structhelios_1_1vec2.html index 16afa665e..20715f42d 100644 --- a/doc/html/structhelios_1_1vec2.html +++ b/doc/html/structhelios_1_1vec2.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structhelios_1_1vec3.html b/doc/html/structhelios_1_1vec3.html index 1b545ae20..848586fb6 100644 --- a/doc/html/structhelios_1_1vec3.html +++ b/doc/html/structhelios_1_1vec3.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structhelios_1_1vec4.html b/doc/html/structhelios_1_1vec4.html index 6613fe0db..242f42a63 100644 --- a/doc/html/structhelios_1_1vec4.html +++ b/doc/html/structhelios_1_1vec4.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structjpg__error__mgr.html b/doc/html/structjpg__error__mgr.html index b32881063..bcb9e3ad4 100644 --- a/doc/html/structjpg__error__mgr.html +++ b/doc/html/structjpg__error__mgr.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/structmy__error__mgr.html b/doc/html/structmy__error__mgr.html index 3e7ca42ed..02a2a894d 100644 --- a/doc/html/structmy__error__mgr.html +++ b/doc/html/structmy__error__mgr.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/todo.html b/doc/html/todo.html index 4f28ff8ed..2c6fab409 100644 --- a/doc/html/todo.html +++ b/doc/html/todo.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/tomato_8cpp_source.html b/doc/html/tomato_8cpp_source.html index f4d9053a1..03a2fa774 100644 --- a/doc/html/tomato_8cpp_source.html +++ b/doc/html/tomato_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/usergroup0.html b/doc/html/usergroup0.html index 8e243f6d6..a856a37d0 100644 --- a/doc/html/usergroup0.html +++ b/doc/html/usergroup0.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/visualizer_basics.html b/doc/html/visualizer_basics.html index 8f7427fce..55c75d553 100644 --- a/doc/html/visualizer_basics.html +++ b/doc/html/visualizer_basics.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/visualizer_pdata.html b/doc/html/visualizer_pdata.html index 98d829502..b8c769451 100644 --- a/doc/html/visualizer_pdata.html +++ b/doc/html/visualizer_pdata.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/walnut_8cpp_source.html b/doc/html/walnut_8cpp_source.html index 254040b7f..3d17991b1 100644 --- a/doc/html/walnut_8cpp_source.html +++ b/doc/html/walnut_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/doc/html/whitespruce_8cpp_source.html b/doc/html/whitespruce_8cpp_source.html index 002f70c94..f28b92b91 100644 --- a/doc/html/whitespruce_8cpp_source.html +++ b/doc/html/whitespruce_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
       v1.3.20 +
       v1.3.21
      diff --git a/plugins/plantarchitecture/doc/PlantArchitecture.dox b/plugins/plantarchitecture/doc/PlantArchitecture.dox index 53a1bc027..49ebed94a 100755 --- a/plugins/plantarchitecture/doc/PlantArchitecture.dox +++ b/plugins/plantarchitecture/doc/PlantArchitecture.dox @@ -293,7 +293,7 @@ Parameters defining the geometry and growth of the shoot are given in the \ref S | --- **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. | +| internode_radius_max | RandomParameter_float | unlimited | meters | Maximum internode radius for girth growth expansion. | | 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. | | insertion_angle_decay_rate | RandomParameter_float | 0 | degrees/node | Rate of increase of the child insertion angle moving down the parent shoot. | | 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. | @@ -302,7 +302,7 @@ Parameters defining the geometry and growth of the shoot are given in the \ref S | 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. | +| tortuosity | RandomParameter_float | 0 | degrees/(meters)^0.5 | 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 | \htmlonlyuint\endhtmlonly | 1 | - | Number of leaves/phytomers to flush at a time. Flushes will occur at an interval of phyllochron*leaf_flush_count. | @@ -364,7 +364,7 @@ The tendency of shoots to grow toward vertical is given by the parameter \htmlon Random "wiggle" can be added to shoot growth using the \htmlonlytortuosity\endhtmlonly parameter. Each time a phytomer is added to the shoot, some constant amount of differential curvature is added according to the parameter \htmlonlygravitropic_curvature\endhtmlonly. To introduce random variation, an additional amount of noise is added to the curvature based on a Langevin-like equation (Brownian motion): \f[ - d\theta = \frac{1}{2}\left(C_g-\theta\right)dL + T\xi(dL) + d\theta = -\frac{1}{2}\left(\theta\right)dL + T\xi(dL) \f] where \f$d\theta\f$ is the change in curvature angle of the current phytomer internode relative to the previous internode, \f$\theta\f$ is the integrated curvature angle relative to the base of the shoot, \f$dL\f$ is the internode length, \f$T\f$ is the tortuosity, and \f$\xi (dL)\f$ is a Gaussian process with variance of \f$dL\f$. diff --git a/plugins/plantarchitecture/src/InputOutput.cpp b/plugins/plantarchitecture/src/InputOutput.cpp index a300a9df0..5453df120 100644 --- a/plugins/plantarchitecture/src/InputOutput.cpp +++ b/plugins/plantarchitecture/src/InputOutput.cpp @@ -441,7 +441,12 @@ void PlantArchitecture::writePlantStructureXML(uint plantID, const std::string & helios_runtime_error("ERROR (PlantArchitecture::writePlantStructureXML): Plant ID " + std::to_string(plantID) + " does not exist."); } - //\todo Check the extension of 'filename' and add .xml if needed + std::string output_file = filename; + if( !validateOutputPath(output_file,{".xml",".XML"}) ){ + helios_runtime_error("ERROR (PlantArchitecture::writePlantStructureXML): Could not open file " + filename + " for writing. Make sure the directory exists and is writable."); + }else if( getFileName(output_file).empty()){ + helios_runtime_error("ERROR (PlantArchitecture::writePlantStructureXML): The output file given was a directory. This argument should be the path to a file not to a directory."); + } std::ofstream output_xml(filename); diff --git a/plugins/plantarchitecture/src/PlantArchitecture.cpp b/plugins/plantarchitecture/src/PlantArchitecture.cpp index 1e539d156..db36703b4 100644 --- a/plugins/plantarchitecture/src/PlantArchitecture.cpp +++ b/plugins/plantarchitecture/src/PlantArchitecture.cpp @@ -948,7 +948,6 @@ Phytomer::Phytomer(const PhytomerParameters ¶ms, Shoot *parent_shoot, uint p } // create internode tube - float dt = 1.f / float(Ndiv_internode_length); for(int inode_segment=1; inode_segment <= Ndiv_internode_length; inode_segment++ ){ //apply curvature and tortuosity @@ -959,12 +958,14 @@ Phytomer::Phytomer(const PhytomerParameters ¶ms, Shoot *parent_shoot, uint p current_curvature_fact *= 2.f; } - parent_shoot->curvature_perturbation += - 0.5f*parent_shoot->curvature_perturbation*dt + 5*parent_shoot_parameters.tortuosity.val()*context_ptr->randn()*sqrt(dt); - float curvature_angle = deg2rad((parent_shoot->gravitropic_curvature*current_curvature_fact+parent_shoot->curvature_perturbation) * dr_internode_max); + float dt = dr_internode_max / float(Ndiv_internode_length); + + parent_shoot->curvature_perturbation += - 0.5f*parent_shoot->curvature_perturbation*dt + parent_shoot_parameters.tortuosity.val()*context_ptr->randn()*sqrt(dt); + float curvature_angle = deg2rad((parent_shoot->gravitropic_curvature*current_curvature_fact * dr_internode_max + parent_shoot->curvature_perturbation)); internode_axis = rotatePointAboutLine(internode_axis, nullorigin, shoot_bending_axis, curvature_angle); - parent_shoot->yaw_perturbation += - 0.5f*parent_shoot->yaw_perturbation*dt + 5*parent_shoot_parameters.tortuosity.val()*context_ptr->randn()*sqrt(dt); - float yaw_angle = deg2rad((parent_shoot->yaw_perturbation) * dr_internode_max); + parent_shoot->yaw_perturbation += - 0.5f*parent_shoot->yaw_perturbation*dt + parent_shoot_parameters.tortuosity.val()*context_ptr->randn()*sqrt(dt); + float yaw_angle = deg2rad((parent_shoot->yaw_perturbation)); internode_axis = rotatePointAboutLine(internode_axis, nullorigin, make_vec3(0,0,1), yaw_angle); } @@ -2729,7 +2730,7 @@ void PlantArchitecture::advanceTime( uint plantID, float dt ) { plant_instance.current_age += dt_max; if( plant_instance.current_age > plant_instance.dd_to_senescence ){ - std::cout << "Going dormant " << plant_instance.current_age << " " << plant_instance.dd_to_senescence << std::endl; + std::cout << "Going dormant" << std::endl; for (const auto& shoot : *shoot_tree) { shoot->makeDormant(); shoot->carbohydrate_pool_molC = 100; diff --git a/plugins/plantarchitecture/src/PlantLibrary.cpp b/plugins/plantarchitecture/src/PlantLibrary.cpp index 66b2c7896..cfdc44054 100644 --- a/plugins/plantarchitecture/src/PlantLibrary.cpp +++ b/plugins/plantarchitecture/src/PlantLibrary.cpp @@ -200,7 +200,7 @@ void PlantArchitecture::initializeAlmondTreeShoots(){ shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0; shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 24; shoot_parameters_trunk.max_nodes = 20; - shoot_parameters_trunk.girth_area_factor = 35.f; + shoot_parameters_trunk.girth_area_factor = 15.f; shoot_parameters_trunk.internode_radius_initial = 0.01; shoot_parameters_trunk.vegetative_bud_break_probability = 0; shoot_parameters_trunk.vegetative_bud_break_time = 0; @@ -218,7 +218,7 @@ void PlantArchitecture::initializeAlmondTreeShoots(){ shoot_parameters_proleptic.max_nodes = 40; shoot_parameters_proleptic.phyllochron = 0.9; shoot_parameters_proleptic.elongation_rate = 0.25; - shoot_parameters_proleptic.girth_area_factor = 35.f; + shoot_parameters_proleptic.girth_area_factor = 15.f; shoot_parameters_proleptic.vegetative_bud_break_probability = 0.15; shoot_parameters_proleptic.vegetative_bud_break_time = 0; shoot_parameters_proleptic.leaf_flush_count = 1; @@ -335,7 +335,7 @@ void PlantArchitecture::initializeAppleTreeShoots(){ phytomer_parameters_apple.internode.max_floral_buds_per_petiole = 1; phytomer_parameters_apple.petiole.petioles_per_internode = 1; - phytomer_parameters_apple.petiole.pitch.uniformDistribution(-25,-40); + phytomer_parameters_apple.petiole.pitch.uniformDistribution(-40,-25); phytomer_parameters_apple.petiole.taper = 0.1; phytomer_parameters_apple.petiole.curvature = 0; phytomer_parameters_apple.petiole.length = 0.04; @@ -372,11 +372,11 @@ void PlantArchitecture::initializeAppleTreeShoots(){ shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0; shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 24; shoot_parameters_trunk.max_nodes = 20; - shoot_parameters_trunk.girth_area_factor = 16.f; + shoot_parameters_trunk.girth_area_factor = 12.f; shoot_parameters_trunk.internode_radius_initial = 0.01; shoot_parameters_trunk.vegetative_bud_break_probability = 0; shoot_parameters_trunk.vegetative_bud_break_time = 0; - shoot_parameters_trunk.tortuosity = 6; + shoot_parameters_trunk.tortuosity = 4; shoot_parameters_trunk.internode_length_max = 0.05; shoot_parameters_trunk.internode_length_decay_rate = 0; shoot_parameters_trunk.defineChildShootTypes({"scaffold"},{1}); @@ -395,7 +395,7 @@ void PlantArchitecture::initializeAppleTreeShoots(){ shoot_parameters_proleptic.vegetative_bud_break_time = 0; shoot_parameters_proleptic.leaf_flush_count = 1; shoot_parameters_proleptic.gravitropic_curvature = 500; - shoot_parameters_proleptic.tortuosity = 20; + shoot_parameters_proleptic.tortuosity = 10; shoot_parameters_proleptic.internode_radius_initial = 0.006; shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 20, 25); shoot_parameters_proleptic.insertion_angle_decay_rate = 20; @@ -430,7 +430,7 @@ void PlantArchitecture::initializeAppleTreeShoots(){ shoot_parameters_scaffold.max_nodes = 40; shoot_parameters_scaffold.gravitropic_curvature = 400; shoot_parameters_scaffold.internode_length_max = 0.04; - shoot_parameters_scaffold.tortuosity = 10; + shoot_parameters_scaffold.tortuosity = 6; shoot_parameters_scaffold.defineChildShootTypes({"proleptic"},{1.0}); defineShootType("trunk", shoot_parameters_trunk); @@ -1089,9 +1089,9 @@ void PlantArchitecture::initializeGrapevineVSPShoots() { shoot_parameters_main.vegetative_bud_break_time = 1; shoot_parameters_main.phyllochron = 0.5; shoot_parameters_main.elongation_rate = 0.15; - shoot_parameters_main.girth_area_factor = 4.f; + shoot_parameters_main.girth_area_factor = 2.f; shoot_parameters_main.gravitropic_curvature = 300; - shoot_parameters_main.tortuosity = 20; + shoot_parameters_main.tortuosity = 10; shoot_parameters_main.internode_length_max.uniformDistribution(0.075,0.1); shoot_parameters_main.internode_length_decay_rate = 0; shoot_parameters_main.insertion_angle_tip = 45; @@ -1117,7 +1117,8 @@ void PlantArchitecture::initializeGrapevineVSPShoots() { shoot_parameters_cane.internode_radius_max = 0.1; shoot_parameters_cane.insertion_angle_tip.uniformDistribution(60, 120); shoot_parameters_cane.max_nodes = 9; - shoot_parameters_cane.tortuosity = 1.5; + shoot_parameters_cane.gravitropic_curvature.uniformDistribution(-20,20); + shoot_parameters_cane.tortuosity = 1; shoot_parameters_cane.gravitropic_curvature = 10; shoot_parameters_cane.vegetative_bud_break_probability = 1.0; shoot_parameters_cane.defineChildShootTypes({"grapevine_shoot"},{1.f}); @@ -1132,7 +1133,7 @@ void PlantArchitecture::initializeGrapevineVSPShoots() { shoot_parameters_trunk.phyllochron = 1.25; shoot_parameters_trunk.insertion_angle_tip = 90; shoot_parameters_trunk.max_nodes = 18; - shoot_parameters_trunk.tortuosity = 1; + shoot_parameters_trunk.tortuosity = 0; shoot_parameters_trunk.vegetative_bud_break_probability = 0; shoot_parameters_trunk.defineChildShootTypes({"grapevine_shoot"},{1.f}); @@ -1154,8 +1155,8 @@ uint PlantArchitecture::buildGrapevineVSP(const helios::vec3 &base_position) { uint uID_stem = addBaseStemShoot(plantID, 17, make_AxisRotation(context_ptr->randu(0,0.05*M_PI), 0, 0), 0.04, 0.05, 1, 1, 0.1, "grapevine_trunk"); //appendPhytomerToShoot( plantID, uID_stem, getCurrentShootParameters("grapevine_trunk").phytomer_parameters, 1e-3, 0.1, 1, 1 ); - uint uID_cane_L = appendShoot( plantID, uID_stem, 8, make_AxisRotation(context_ptr->randu(float(0.45f*M_PI),0.52f*M_PI),0,M_PI), 0.015, 0.15, 1, 1, 0.6, "grapevine_cane" ); - uint uID_cane_R = appendShoot( plantID, uID_stem, 8, make_AxisRotation(context_ptr->randu(float(0.45f*M_PI),0.52f*M_PI),M_PI,M_PI), 0.015, 0.15, 1, 1, 0.6, "grapevine_cane" ); + uint uID_cane_L = appendShoot( plantID, uID_stem, 8, make_AxisRotation(context_ptr->randu(float(0.45f*M_PI),0.52f*M_PI),0,M_PI), 0.005, 0.15, 1, 1, 0.5, "grapevine_cane" ); + uint uID_cane_R = appendShoot( plantID, uID_stem, 8, make_AxisRotation(context_ptr->randu(float(0.45f*M_PI),0.52f*M_PI),M_PI,M_PI), 0.005, 0.15, 1, 1, 0.5, "grapevine_cane" ); // makePlantDormant(plantID); @@ -1225,7 +1226,7 @@ void PlantArchitecture::initializeOliveTreeShoots(){ shoot_parameters_trunk.internode_radius_initial = 0.01; shoot_parameters_trunk.vegetative_bud_break_probability = 0; shoot_parameters_trunk.vegetative_bud_break_time = 0; - shoot_parameters_trunk.tortuosity = 6; + shoot_parameters_trunk.tortuosity = 1; shoot_parameters_trunk.internode_length_max = 0.05; shoot_parameters_trunk.internode_length_decay_rate = 0; shoot_parameters_trunk.defineChildShootTypes({"scaffold"},{1}); @@ -1243,7 +1244,7 @@ void PlantArchitecture::initializeOliveTreeShoots(){ shoot_parameters_proleptic.vegetative_bud_break_time = 0; shoot_parameters_proleptic.leaf_flush_count = 1; shoot_parameters_proleptic.gravitropic_curvature = 450; - shoot_parameters_proleptic.tortuosity = 25; + shoot_parameters_proleptic.tortuosity = 6; shoot_parameters_proleptic.internode_radius_initial = 0.002; shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 15, 25); shoot_parameters_proleptic.insertion_angle_decay_rate = 2; @@ -1264,7 +1265,7 @@ void PlantArchitecture::initializeOliveTreeShoots(){ shoot_parameters_scaffold.max_nodes = 12; shoot_parameters_scaffold.gravitropic_curvature = 700; shoot_parameters_scaffold.internode_length_max = 0.04; - shoot_parameters_scaffold.tortuosity = 10; + shoot_parameters_scaffold.tortuosity = 3; shoot_parameters_scaffold.defineChildShootTypes({"proleptic"},{1.0}); defineShootType("trunk", shoot_parameters_trunk); @@ -1323,7 +1324,7 @@ void PlantArchitecture::initializePistachioTreeShoots(){ phytomer_parameters_pistachio.internode.max_floral_buds_per_petiole = 3; phytomer_parameters_pistachio.petiole.petioles_per_internode = 2; - phytomer_parameters_pistachio.petiole.pitch.uniformDistribution(-45, -60); + phytomer_parameters_pistachio.petiole.pitch.uniformDistribution(-60, -45); phytomer_parameters_pistachio.petiole.taper = 0.1; phytomer_parameters_pistachio.petiole.curvature.uniformDistribution(-800,800); phytomer_parameters_pistachio.petiole.length = 0.075; @@ -1371,7 +1372,7 @@ void PlantArchitecture::initializePistachioTreeShoots(){ shoot_parameters_trunk.internode_radius_initial = 0.01; shoot_parameters_trunk.vegetative_bud_break_probability = 0; shoot_parameters_trunk.vegetative_bud_break_time = 0; - shoot_parameters_trunk.tortuosity = 5; + shoot_parameters_trunk.tortuosity = 2; shoot_parameters_trunk.internode_length_max = 0.05; shoot_parameters_trunk.internode_length_decay_rate = 0; shoot_parameters_trunk.defineChildShootTypes({"proleptic"},{1}); @@ -1389,7 +1390,7 @@ void PlantArchitecture::initializePistachioTreeShoots(){ shoot_parameters_proleptic.vegetative_bud_break_time = 0; shoot_parameters_proleptic.leaf_flush_count = 1; shoot_parameters_proleptic.gravitropic_curvature = 500; - shoot_parameters_proleptic.tortuosity = 15; + shoot_parameters_proleptic.tortuosity = 10; shoot_parameters_proleptic.internode_radius_initial = 0.002; shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 45, 55); shoot_parameters_proleptic.insertion_angle_decay_rate = 10; @@ -1609,9 +1610,9 @@ void PlantArchitecture::initializeEasternRedbudShoots() { shoot_parameters_main.vegetative_bud_break_time = 1; shoot_parameters_main.phyllochron = 1.5; shoot_parameters_main.elongation_rate = 0.17; - shoot_parameters_main.girth_area_factor = 3.f; + shoot_parameters_main.girth_area_factor = 5.f; shoot_parameters_main.gravitropic_curvature = 300; - shoot_parameters_main.tortuosity = 20; + shoot_parameters_main.tortuosity = 10; shoot_parameters_main.internode_length_max = 0.04; shoot_parameters_main.internode_length_decay_rate = 0.005; shoot_parameters_main.insertion_angle_tip = 75; @@ -1635,7 +1636,7 @@ void PlantArchitecture::initializeEasternRedbudShoots() { shoot_parameters_trunk.phyllochron = 1.25; shoot_parameters_trunk.insertion_angle_tip = 60; shoot_parameters_trunk.max_nodes = 45; - shoot_parameters_trunk.tortuosity = 5; + shoot_parameters_trunk.tortuosity = 0.5; shoot_parameters_trunk.defineChildShootTypes({"eastern_redbud_shoot"},{1.f}); defineShootType("eastern_redbud_trunk", shoot_parameters_trunk); diff --git a/plugins/radiation/include/RadiationModel.h b/plugins/radiation/include/RadiationModel.h index a05678ecc..085942390 100755 --- a/plugins/radiation/include/RadiationModel.h +++ b/plugins/radiation/include/RadiationModel.h @@ -1654,13 +1654,6 @@ class RadiationModel{ }; -//! Validates the file path for output file writing by 1) making sure the directory string has a trailing slash, 2) creating the output directory if it does not exist. -/** - * \param[inout] output_directory Path to the directory where output files will be written. If the directory does not exist, it will be created. - * \return True if the output directory is valid, false otherwise. -*/ -bool validateOutputPath(std::ostringstream &output_directory); - void sutilHandleError(RTcontext context, RTresult code, const char* file, int line); void sutilReportError(const char* message); diff --git a/plugins/radiation/src/RadiationModel.cpp b/plugins/radiation/src/RadiationModel.cpp index cd53306c1..da8cffc6b 100755 --- a/plugins/radiation/src/RadiationModel.cpp +++ b/plugins/radiation/src/RadiationModel.cpp @@ -1340,12 +1340,16 @@ void RadiationModel::writeCameraImage(const std::string &camera, const std::vect frame_str = std::to_string(frame); } - std::ostringstream outfile; - - if( !validateOutputPath(outfile) ){ - helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission."); + std::string output_path = image_path; + if( !image_path.empty() && !validateOutputPath(output_path) ){ + helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission."); + }else if( !getFileName(output_path).empty() ){ + helios_runtime_error("ERROR(RadiationModel::writeCameraImage): Image output directory contains a filename. This argument should be the path to a directory not a file."); } + std::ostringstream outfile; + outfile << output_path; + if( frame>=0 ) { outfile << camera << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".jpeg"; }else{ @@ -1447,12 +1451,16 @@ void RadiationModel::writeCameraImageData(const std::string &camera, const std:: frame_str = std::to_string(frame); } - std::ostringstream outfile; - - if( !validateOutputPath(outfile) ){ - helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission."); + std::string output_path = image_path; + if( !image_path.empty() && !validateOutputPath(output_path) ){ + helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission."); + }else if( !getFileName(output_path).empty() ){ + helios_runtime_error("ERROR(RadiationModel::writeCameraImage): Image output directory contains a filename. This argument should be the path to a directory not a file."); } + std::ostringstream outfile; + outfile << output_path; + if( frame>=0 ) { outfile << camera << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt"; }else{ @@ -5092,12 +5100,16 @@ void RadiationModel::writePrimitiveDataLabelMap(const std::string &cameralabel, frame_str = std::to_string(frame); } - std::ostringstream outfile; - - if( !validateOutputPath(outfile) ){ - helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission."); + std::string output_path = image_path; + if( !image_path.empty() && !validateOutputPath(output_path) ){ + helios_runtime_error("ERROR (RadiationModel::writePrimitiveDataLabelMap): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission."); + }else if( !getFileName(output_path).empty() ){ + helios_runtime_error("ERROR(RadiationModel::writePrimitiveDataLabelMap): Image output directory contains a filename. This argument should be the path to a directory not a file."); } + std::ostringstream outfile; + outfile << output_path; + if( frame>=0 ) { outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt"; }else{ @@ -5179,12 +5191,16 @@ void RadiationModel::writeObjectDataLabelMap(const std::string &cameralabel, con frame_str = std::to_string(frame); } - std::ostringstream outfile; - - if( !validateOutputPath(outfile) ){ - helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission."); + std::string output_path = image_path; + if( !image_path.empty() && !validateOutputPath(output_path) ){ + helios_runtime_error("ERROR (RadiationModel::writeObjectDataLabelMap): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission."); + }else if( !getFileName(output_path).empty() ){ + helios_runtime_error("ERROR(RadiationModel::writeObjectDataLabelMap): Image output directory contains a filename. This argument should be the path to a directory not a file."); } + std::ostringstream outfile; + outfile << output_path; + if( frame>=0 ) { outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt"; }else{ @@ -5268,12 +5284,16 @@ void RadiationModel::writeDepthImageData(const std::string &cameralabel, const s frame_str = std::to_string(frame); } - std::ostringstream outfile; - - if( !validateOutputPath(outfile) ){ - helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission."); + std::string output_path = image_path; + if( !image_path.empty() && !validateOutputPath(output_path) ){ + helios_runtime_error("ERROR (RadiationModel::writeDepthImageData): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission."); + }else if( !getFileName(output_path).empty() ){ + helios_runtime_error("ERROR(RadiationModel::writeDepthImageData): Image output directory contains a filename. This argument should be the path to a directory not a file."); } + std::ostringstream outfile; + outfile << output_path; + if( frame>=0 ) { outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt"; }else{ @@ -5320,12 +5340,16 @@ void RadiationModel::writeNormDepthImage(const std::string &cameralabel, const s frame_str = std::to_string(frame); } - std::ostringstream outfile; - - if( !validateOutputPath(outfile) ){ - helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission."); + std::string output_path = image_path; + if( !image_path.empty() && !validateOutputPath(output_path) ){ + helios_runtime_error("ERROR (RadiationModel::writeNormDepthImage): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission."); + }else if( !getFileName(output_path).empty() ){ + helios_runtime_error("ERROR(RadiationModel::writeNormDepthImage): Image output directory contains a filename. This argument should be the path to a directory not a file."); } + std::ostringstream outfile; + outfile << output_path; + if( frame>=0 ) { outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".jpeg"; }else{ @@ -5386,12 +5410,16 @@ void RadiationModel::writeImageBoundingBoxes(const std::string &cameralabel, con frame_str = std::to_string(frame); } - std::ostringstream outfile; - - if( !validateOutputPath(outfile) ){ - helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission."); + std::string output_path = image_path; + if( !image_path.empty() && !validateOutputPath(output_path) ){ + helios_runtime_error("ERROR (RadiationModel::writeImageBoundingBoxes): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission."); + }else if( !getFileName(output_path).empty() ){ + helios_runtime_error("ERROR(RadiationModel::writeImageBoundingBoxes): Image output directory contains a filename. This argument should be the path to a directory not a file."); } + std::ostringstream outfile; + outfile << output_path; + if( frame>=0 ) { outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt"; }else{ @@ -5491,12 +5519,16 @@ void RadiationModel::writeImageBoundingBoxes_ObjectData(const std::string &camer frame_str = std::to_string(frame); } - std::ostringstream outfile; - - if( !validateOutputPath(outfile) ){ - helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + outfile.str() + "'. Check that the path exists and that you have write permission."); + std::string output_path = image_path; + if( !image_path.empty() && !validateOutputPath(output_path) ){ + helios_runtime_error("ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission."); + }else if( !getFileName(output_path).empty() ){ + helios_runtime_error("ERROR(RadiationModel::writeImageBoundingBoxes_ObjectData): Image output directory contains a filename. This argument should be the path to a directory not a file."); } + std::ostringstream outfile; + outfile << output_path; + if( frame>=0 ) { outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt"; }else{ @@ -5724,24 +5756,6 @@ std::vector RadiationModel::generateGaussianCameraResponse(float F return cameraresponse; } -bool validateOutputPath(std::ostringstream &output_directory){ - - // Make sure directory has a trailing slash - if( output_directory.str().find_last_of('/')!=output_directory.str().length()-1 ) { - output_directory << "/"; - } - - // Create the output directory if it does not exist - if( !std::filesystem::exists(output_directory.str()) ){ - if( !std::filesystem::create_directory(output_directory.str()) ){ - return false; - } - } - - return true; - -} - void sutilHandleError(RTcontext context, RTresult code, const char* file, int line) { const char* message;