Skip to content

Commit

Permalink
[1.3.21] 2024-10-24
Browse files Browse the repository at this point in the history
*Context*
- There was an error introduced in the previous version for writing OBJ files. If no output directory was explicitly specified, the write would fail.
- Added validateOutputPath() function to global.cpp to validate output files and directory paths.
- Replaced getFile*() functions in global.cpp with more robust std::filesystem functions.
- Added improved file validation to Context::writeXML().

*Radiation*
- There was an error introduced in the previous version for writing image output files. If no output directory was explicitly specified, the write would fail. Removed the validateOutputPath() function implemented in the previous version, and replaced it with a better version implemented in global.cpp.

*Plant Architecture*
- The 'tortuosity' shoot parameter was multiplied by a hard-coded factor of 5.0. This was removed, and all tortuosity values in the plant library were scaled by a factor of 5.
- There were some errors with the parameters of some plants introduced in the previous version.
- Added file validation to PlantArchitecture::writePlantStructureXML().

Note: Retroactively adding Heesup, Dario, and Amogh as co-authors based on prior contributions to the synthetic annotation plug-in that were not attributed

Co-authored-by: Heesup Yun <[email protected]>
Co-authored-by: Dario Guevara <[email protected]>
Co-authored-by: Amogh Joshi <[email protected]>
  • Loading branch information
4 people committed Oct 24, 2024
1 parent 9601e54 commit 4ed9ecd
Show file tree
Hide file tree
Showing 451 changed files with 11,383 additions and 11,059 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

For complete documentation of this software, please consult <a href="https://baileylab.ucdavis.edu/software/helios">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)
8 changes: 8 additions & 0 deletions core/include/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string> &allowable_file_extensions = {});

//! Read values contained in a text file into a one-dimensional vector of floats
/**
* \param[in] filepath Path to text file
Expand Down
10 changes: 9 additions & 1 deletion core/src/Context_fileIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2676,6 +2676,14 @@ void Context::writeXML( const char* filename, const std::vector<uint> &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");
Expand Down Expand Up @@ -4160,7 +4168,7 @@ void Context::writeOBJ( const std::string &filename, const std::vector<uint> &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;
Expand Down
113 changes: 59 additions & 54 deletions core/src/global.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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('.')<filepath.size() ){
ext = filepath.substr(filepath.find_last_of('.'));
}else { // does not contain any .'s
return "";
}
std::filesystem::path output_path_fs = filepath;
return output_path_fs.extension().string();
}

//edge case when filepath starts with '.' and there is no file extension (e.g., './myfile')
if( filepath.find_last_of('.')==0 ){
ext = "";
std::string helios::getFileStem( const std::string &filepath ){
std::filesystem::path output_path_fs = filepath;
return output_path_fs.stem().string();
}

//edge case when file is in a hidden directory AND there is no file extension (return empty string)
}else if( filepath.find_last_of('/')<filepath.size() && filepath.at(filepath.find_last_of('.')-1)=='/' ){
ext = "";
}
std::string helios::getFileName( const std::string &filepath ){
std::filesystem::path output_path_fs = filepath;
return output_path_fs.filename().string();
}

//edge case when file is in a hidden directory AND there is no file extension AND file path starts with '.' (return empty string)
if( filepath.find_last_of('.')==0 ){
ext = "";
}
std::string helios::getFilePath( const std::string &filepath, bool trailingslash ){
std::filesystem::path output_path_fs = filepath;
std::string output_path = output_path_fs.parent_path().string();
if( trailingslash ) {
if (output_path.find_last_of('/') != output_path.length() - 1) {
output_path += "/";
}
}

return ext;
return output_path;
}

std::string helios::getFileStem( const std::string &filepath ){
std::string fn = filepath;
if( filepath.find('/')<filepath.size() ) {
fn = filepath.substr(filepath.find_last_of('/') + 1);
}else if( filepath.find('\\')<filepath.size() ){
fn = filepath.substr(filepath.find_last_of('\\') + 1);
}
bool helios::validateOutputPath(std::string &output_path, const std::vector<std::string> &allowable_file_extensions){

if( fn.find('.')<fn.size() ) {
fn = fn.substr( 0, fn.find_last_of('.') );
}
if( output_path.empty() ){ //path was empty
return false;
}

return fn;
}
std::filesystem::path output_path_fs = output_path;

std::string helios::getFileName( const std::string &filepath ){
if( filepath.find('/')<filepath.size() ) {
return filepath.substr(filepath.find_last_of('/') + 1);
}else if( filepath.find('\\')==filepath.size() ) {
return filepath.substr(filepath.find_last_of('\\') + 1);
}else{
return filepath;
}
std::string output_file = output_path_fs.filename().string();
std::string output_file_ext = output_path_fs.extension().string();
std::string output_dir = output_path_fs.parent_path().string();

}
if( output_file.empty() ) { //path was a directory without a file

// Make sure directory has a trailing slash
if (output_dir.find_last_of('/') != output_dir.length() - 1) {
output_path += "/";
}

std::string helios::getFilePath( const std::string &filepath, bool trailingslash ){
if( filepath.find('/')==filepath.size() ){
if( trailingslash ){
std::string str = "/";
return str;
}else {
std::string str;
return str;
}
}else{
if( trailingslash ) {
return filepath.substr(0, filepath.find_last_of('/') + 1);
}else{
return filepath.substr(0, filepath.find_last_of('/'));

// Create the output directory if it does not exist
if ( !output_dir.empty() && !std::filesystem::exists(output_dir)) {
if (!std::filesystem::create_directory(output_dir)) {
return false;
}
}
}

if( !output_file.empty() && !allowable_file_extensions.empty() ){

//validate file extension
bool valid_extension = false;
for( const auto &ext : allowable_file_extensions ){
if( output_file_ext == ext ){
valid_extension = true;
break;
}
}
if( !valid_extension ){
return false;
}

}

return true;

}

std::vector<float> helios::importVectorFromFile(const std::string &filepath){
Expand Down
18 changes: 17 additions & 1 deletion doc/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -1890,4 +1890,20 @@ The radiation model has been re-designed, with the following primary additions:
- Addition of variable range parameters for grapevine canopies
- Addition of parameters to create dead plants or to have missing plants (holes) in grapevine canopies
- Addition of parameters to set the cordon length independently from the plant spacing for grapevine canopies. Until now, the plant spacing was used so that there was no discontinuity between neighbor vine stocks. These new parameters allow to potentially have gaps between vine stocks, or even have them overlap with each other (if the cordon length is greater than the plant spacing).
- Addition of a sample project to demonstrate how one could build realistic vineyards based on CanopyGenerator XML configuration.
- Addition of a sample project to demonstrate how one could build realistic vineyards based on CanopyGenerator XML configuration.

[1.3.21] 2024-10-24

*Context*
- There was an error introduced in the previous version for writing OBJ files. If no output directory was explicitly specified, the write would fail.
- Added validateOutputPath() function to global.cpp to validate output files and directory paths.
- Replaced getFile*() functions in global.cpp with more robust std::filesystem functions.
- Added improved file validation to Context::writeXML().

*Radiation*
- There was an error introduced in the previous version for writing image output files. If no output directory was explicitly specified, the write would fail. Removed the validateOutputPath() function implemented in the previous version, and replaced it with a better version implemented in global.cpp.

*Plant Architecture*
- The 'tortuosity' shoot parameter was multiplied by a hard-coded factor of 5.0. This was removed, and all tortuosity values in the plant library were scaled by a factor of 5.
- There were some errors with the parameters of some plants introduced in the previous version.
- Added file validation to PlantArchitecture::writePlantStructureXML().
Loading

0 comments on commit 4ed9ecd

Please sign in to comment.