Skip to content

Commit 5d0ef4f

Browse files
committed
[1.3.39] 2025-07-09
- More minor documentation fixes. - Implemented some improvements for file path handling on Windows systems to improve robustness. - Added *= and /= operators for `helios::vec2`, `helios::vec3` and `helios::vec4` vector types. - Fixed 'haloing' around text. - Efficiency of changing the visualization type was improved (e.g., via `Visualizer::colorContextPrimitivesByData()` or `Visualizer::colorContextObjectsByData()`), whereby only the color data is changed rather than rebuilding the entire geometry. - Added `Visualizer::deleteGeometry()` method to delete a geometric element based on its ID. - The visualizer window can now be freely resized with arbitrary aspect ratio, including making the visualizer window full screen. - Console now auto-scrolls to the bottom when new text is added. - Disabled keyboard controls so that rotating the view via keyboard does not conflict. - There was an unhandled error when the combination of `leaves_per_petiole` and `leaflet_offset` are too large such that there is no more space along the petiole to place leaflets. There was a similar issue with flowers for the parameters `flowers_per_peduncle` and `flower_offset`, potentially resulting in too many flowers per peduncle. - Fixed a minor issue where the max leaf age was not properly enforced when the plant hits its maximum age and stops growing. - Changed how the camera image post-processing pipeline works. It now applies global histogram equalization, followed by an optional saturation, brightness, and contrast adjustment. - Added documentation page. - Added optional output primitive data to write stomatal conductance model parameters to primitive data.
1 parent c38ac3d commit 5d0ef4f

485 files changed

Lines changed: 27303 additions & 27265 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.clang-format

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ BreakConstructorInitializers: AfterColon
3030
BreakConstructorInitializersBeforeComma: false
3131
ColumnLimit: 250
3232
PenaltyBreakString: 1000
33+
BreakStringLiterals: false
3334
ConstructorInitializerAllOnOneLineOrOnePerLine: false
3435
ContinuationIndentWidth: 8
3536
IncludeCategories:

core/include/helios_vector_types.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,10 @@ namespace helios {
748748
inline vec2 &operator+=(const vec2 &a) noexcept;
749749
//! Decrement vec2 vector
750750
inline vec2 &operator-=(const vec2 &a) noexcept;
751+
//! Multiplication assignment operator for vec2 vector
752+
inline vec2 &operator*=(float a) noexcept;
753+
//! Division assignment operator for vec2 vector
754+
inline vec2 &operator/=(float a) noexcept;
751755
//! Difference of two vec2 vectors noexcept
752756
constexpr vec2 operator-(const vec2 &a) const noexcept;
753757
//! Multiply each element by scalar (scalar is multiplied on right: vec2*a)
@@ -814,6 +818,18 @@ namespace helios {
814818
return *this;
815819
}
816820

821+
inline vec2 &vec2::operator*=(float a) noexcept {
822+
x *= a;
823+
y *= a;
824+
return *this;
825+
}
826+
827+
inline vec2 &vec2::operator/=(float a) noexcept {
828+
x /= a;
829+
y /= a;
830+
return *this;
831+
}
832+
817833
constexpr vec2 vec2::operator+(const float a) const noexcept {
818834
return {a + x, a + y};
819835
}
@@ -924,6 +940,10 @@ namespace helios {
924940
inline vec3 &operator+=(const vec3 &a) noexcept;
925941
//! Decrement vec3 vector
926942
inline vec3 &operator-=(const vec3 &a) noexcept;
943+
//! Multiplication assignment operator for vec3 vector
944+
inline vec3 &operator*=(float a) noexcept;
945+
//! Division assignment operator for vec2 vector
946+
inline vec3 &operator/=(float a) noexcept;
927947
//! Difference of two vec3 vectors
928948
constexpr vec3 operator-(const vec3 &a) const noexcept;
929949
//! Multiply each element by scalar (scalar is multiplied on right: vec3*a)
@@ -997,6 +1017,20 @@ namespace helios {
9971017
return *this;
9981018
}
9991019

1020+
inline vec3 &vec3::operator*=(float a) noexcept {
1021+
x *= a;
1022+
y *= a;
1023+
z *= a;
1024+
return *this;
1025+
}
1026+
1027+
inline vec3 &vec3::operator/=(float a) noexcept {
1028+
x /= a;
1029+
y /= a;
1030+
z /= a;
1031+
return *this;
1032+
}
1033+
10001034
constexpr vec3 vec3::operator+(float a) const noexcept {
10011035
return {x + a, y + a, z + a};
10021036
}
@@ -1112,6 +1146,10 @@ namespace helios {
11121146
inline vec4 &operator+=(const vec4 &a) noexcept;
11131147
//! Decrement vec4 vector
11141148
inline vec4 &operator-=(const vec4 &a) noexcept;
1149+
//! Multiplication assignment operator for vec4 vector
1150+
inline vec4 &operator*=(float a) noexcept;
1151+
//! Division assignment operator for vec4 vector
1152+
inline vec4 &operator/=(float a) noexcept;
11151153
//! Difference of two vec4 vectors
11161154
constexpr vec4 operator-(const vec4 &a) const noexcept;
11171155
//! Multiply each element by scalar (scalar is multiplied on right: vec4*a)
@@ -1182,6 +1220,22 @@ namespace helios {
11821220
return *this;
11831221
}
11841222

1223+
inline vec4 &vec4::operator*=(float a) noexcept {
1224+
x *= a;
1225+
y *= a;
1226+
z *= a;
1227+
w *= a;
1228+
return *this;
1229+
}
1230+
1231+
inline vec4 &vec4::operator/=(float a) noexcept {
1232+
x /= a;
1233+
y /= a;
1234+
z /= a;
1235+
w /= a;
1236+
return *this;
1237+
}
1238+
11851239
constexpr vec4 vec4::operator+(float a) const noexcept {
11861240
return {x + a, y + a, z + a, w + a};
11871241
}

core/src/Context_fileIO.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3936,7 +3936,8 @@ void Context::writeOBJ(const std::string &filename, const std::vector<uint> &UUI
39363936
mtlfilename.append(".mtl");
39373937
} else {
39383938
if (!file_path.empty()) {
3939-
mtlfilename = file_path + "/" + file_stem + ".mtl";
3939+
std::filesystem::path mtl_path = std::filesystem::path(file_path) / (file_stem + ".mtl");
3940+
mtlfilename = mtl_path.string();
39403941
} else {
39413942
mtlfilename = file_stem + ".mtl";
39423943
}
@@ -4119,12 +4120,12 @@ void Context::writeOBJ(const std::string &filename, const std::vector<uint> &UUI
41194120
}
41204121

41214122
// copy material textures to new directory and edit old file paths
4122-
std::string texture_dir = std::string(file_path);
4123+
std::filesystem::path texture_dir = std::filesystem::path(file_path);
41234124
for (auto &material: materials) {
41244125
std::string texture = material.texture;
41254126
if (!texture.empty() && std::filesystem::exists(texture)) {
41264127
auto file = std::filesystem::path(texture).filename();
4127-
std::filesystem::copy_file(texture, texture_dir + file.string(), std::filesystem::copy_options::overwrite_existing);
4128+
std::filesystem::copy_file(texture, texture_dir / file, std::filesystem::copy_options::overwrite_existing);
41284129
material.texture = file.string();
41294130
}
41304131
}
@@ -4250,7 +4251,8 @@ void Context::writeOBJ(const std::string &filename, const std::vector<uint> &UUI
42504251

42514252

42524253
for (const std::string &label: primitive_dat_fields) {
4253-
std::string datfilename = file_path + file_stem + "_" + std::string(label) + ".dat";
4254+
std::filesystem::path dat_path = std::filesystem::path(file_path) / (file_stem + "_" + std::string(label) + ".dat");
4255+
std::string datfilename = dat_path.string();
42544256
std::ofstream datout(datfilename);
42554257

42564258
for (int mat = 0; mat < materials.size(); mat++) {

core/src/global.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2165,14 +2165,15 @@ std::string helios::getFileName(const std::string &filepath) {
21652165

21662166
std::string helios::getFilePath(const std::string &filepath, bool trailingslash) {
21672167
std::filesystem::path output_path_fs = filepath;
2168-
std::string output_path = output_path_fs.parent_path().string();
2169-
if (trailingslash) {
2170-
if (output_path.find_last_of('/') != output_path.length() - 1) {
2171-
output_path += "/";
2168+
std::filesystem::path output_path = output_path_fs.parent_path();
2169+
std::string out_str = output_path.make_preferred().string();
2170+
if (trailingslash && !out_str.empty()) {
2171+
char last = out_str.back();
2172+
if (last != '/' && last != '\\') {
2173+
out_str += std::filesystem::path::preferred_separator;
21722174
}
21732175
}
2174-
2175-
return output_path;
2176+
return out_str;
21762177
}
21772178

21782179
bool helios::validateOutputPath(std::string &output_path, const std::vector<std::string> &allowable_file_extensions) {

core/src/selfTest.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,24 +1171,38 @@ int Context::selfTest(){
11711171

11721172
std::string filename = "/path/to/.hidden/file/filename";
11731173

1174+
std::string expected_path;
1175+
#ifdef _WIN32
1176+
expected_path = "\\path\\to\\.hidden\\file\\";
1177+
#else
1178+
expected_path = "/path/to/.hidden/file/";
1179+
#endif
1180+
1181+
11741182
std::string ext = getFileExtension(filename);
11751183
std::string name = getFileName(filename);
11761184
std::string stem = getFileStem(filename);
11771185
std::string path = getFilePath(filename,true);
11781186

1179-
if( !ext.empty() || name!="filename" || stem!="filename" || path!="/path/to/.hidden/file/" ){
1187+
if( !ext.empty() || name!="filename" || stem!="filename" || path!=expected_path ){
11801188
std::cerr << "failed: file path parsing functions were not correct." << std::endl;
11811189
error_count++;
11821190
}
11831191

11841192
filename = ".hidden/path/to/file/filename.ext";
11851193

1194+
#ifdef _WIN32
1195+
expected_path = ".hidden\\path\\to\\file";
1196+
#else
1197+
expected_path = ".hidden/path/to/file";
1198+
#endif
1199+
11861200
ext = getFileExtension(filename);
11871201
name = getFileName(filename);
11881202
stem = getFileStem(filename);
11891203
path = getFilePath(filename,false);
11901204

1191-
if( ext!=".ext" || name!="filename.ext" || stem!="filename" || path!=".hidden/path/to/file" ){
1205+
if( ext!=".ext" || name!="filename.ext" || stem!="filename" || path!=expected_path ){
11921206
std::cerr << "failed: file path parsing functions were not correct." << std::endl;
11931207
error_count++;
11941208
}

doc/CHANGELOG.md

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2148,7 +2148,7 @@ The radiation model has been re-designed, with the following primary additions:
21482148
## Plant Architecture
21492149
- Added PlantArchitecture::isPlantDormant().
21502150
- Carbohydrate model updated to take a parameter structure rather than having hard-coded model parameters. Thanks to Ethan Frehner for these updates.
2151-
- Minor refactoring improvements throughtout plant architecture code.
2151+
- Minor refactoring improvements throughout plant architecture code.
21522152
- Error corrected that was causing plants to flower too quickly if starting with closed flowers.
21532153

21542154
## Visualizer
@@ -2209,9 +2209,6 @@ The radiation model has been re-designed, with the following primary additions:
22092209
## Radiation
22102210
- Added specular reflection in synthetic images for collimated and sun sphere sources (still need to implement disk, rectangle, and sphere sources).
22112211

2212-
Co-authored by: Ethan Frehner <ehfrehner@users.noreply.github.com>
2213-
Co-authored by: Sean Banks <smbanx@users.noreply.github.com>
2214-
22152212
# [1.3.33] 2025-06-08
22162213

22172214
## Context
@@ -2247,9 +2244,6 @@ Co-authored by: Sean Banks <smbanx@users.noreply.github.com>
22472244
## Project Builder
22482245
- Several updates including changing how canopies are handled, and improving the rig tab. Credit to Sean Banks for this update.
22492246

2250-
Co-authored by: Ethan Frehner <ehfrehner@users.noreply.github.com>
2251-
Co-authored by: Sean Banks <smbanx@users.noreply.github.com>
2252-
22532247
# [1.3.34] 2025-06-15
22542248

22552249
- Added .clang-format file for consistent code formatting across IDEs and agents.
@@ -2401,4 +2395,35 @@ Co-authored by: Sean Banks <smbanx@users.noreply.github.com>
24012395
- Added self-test to check `plantID` assignment.
24022396

24032397
## Radiation, Energy Balance, LiDAR, Aerial LiDAR
2404-
- CMake now uses consistent c++ standard for CUDA code based on the standard used for regular c++ code. It also now explicitly sets the c++ standard for Windows CUDA code.
2398+
- CMake now uses consistent c++ standard for CUDA code based on the standard used for regular c++ code. It also now explicitly sets the c++ standard for Windows CUDA code.
2399+
2400+
# [1.3.39] 2025-07-09
2401+
2402+
- More minor documentation fixes.
2403+
2404+
## Context
2405+
- Implemented some improvements for file path handling on Windows systems to improve robustness.
2406+
- Added *= and /= operators for `helios::vec2`, `helios::vec3` and `helios::vec4` vector types.
2407+
2408+
## Visualizer
2409+
- Fixed 'haloing' around text.
2410+
- Efficiency of changing the visualization type was improved (e.g., via `Visualizer::colorContextPrimitivesByData()` or `Visualizer::colorContextObjectsByData()`), whereby only the color data is changed rather than rebuilding the entire geometry.
2411+
- Added `Visualizer::deleteGeometry()` method to delete a geometric element based on its ID.
2412+
- The visualizer window can now be freely resized with arbitrary aspect ratio, including making the visualizer window full screen.
2413+
2414+
## Project Builder
2415+
- Console now auto-scrolls to the bottom when new text is added.
2416+
- Disabled keyboard controls so that rotating the view via keyboard does not conflict.
2417+
2418+
## Plant Architecture
2419+
- There was an unhandled error when the combination of `leaves_per_petiole` and `leaflet_offset` are too large such that there is no more space along the petiole to place leaflets. There was a similar issue with flowers for the parameters `flowers_per_peduncle` and `flower_offset`, potentially resulting in too many flowers per peduncle.
2420+
- Fixed a minor issue where the max leaf age was not properly enforced when the plant hits its maximum age and stops growing.
2421+
2422+
## Radiation
2423+
- Changed how the camera image post-processing pipeline works. It now applies global histogram equalization, followed by an optional saturation, brightness, and contrast adjustment.
2424+
2425+
## Leaf Optics
2426+
- Added documentation page.
2427+
2428+
## Stomatal Conductance
2429+
- Added optional output primitive data to write stomatal conductance model parameters to primitive data.

doc/Doxyfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ PROJECT_NAME = Helios
4848
# could be handy for archiving the generated documentation or if some version
4949
# control system is used.
5050

51-
PROJECT_NUMBER = v1.3.38
51+
PROJECT_NUMBER = v1.3.39
5252

5353
# Using the PROJECT_BRIEF tag one can provide an optional one line description
5454
# for a project that appears at the top of each page and should give viewer a
@@ -1302,7 +1302,8 @@ HTML_EXTRA_STYLESHEET = doc/assets/doxygen-awesome-sidebar-only-darkmode-toggle
13021302
HTML_EXTRA_FILES = doc/assets/doxygen-awesome-darkmode-toggle.js \
13031303
doc/assets/doxygen-awesome-tabs.js \
13041304
doc/assets/doxygen-awesome-interactive-toc.js \
1305-
doc/assets/doxygen-awesome-paragraph-link.js
1305+
doc/assets/doxygen-awesome-paragraph-link.js \
1306+
doc/assets/navsync-default.js
13061307

13071308
# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
13081309
# should be rendered with a dark or light theme.

doc/DoxygenLayout.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<tab type="user" visible="yes" url="@ref CanopyGeneratorDoc" title="Canopy Generator"/>
2424
<tab type="user" visible="yes" url="@ref WeberPennDoc" title="Weber-Penn Tree"/>
2525
<tab type="user" visible="yes" url="@ref PlantHydraulicsDoc" title="Plant Hydraulics Model"/>
26+
<tab type="user" visible="yes" url="@ref LeafOpticsDoc" title="Leaf Optics Model"/>
2627
<tab type="user" visible="yes" url="@ref ProjectBuilderDoc" title="Project Builder"/>
2728
</tab>
2829
<tab type="usergroup" visible="yes" url="@ref Tutorials" title="Tutorials" intro="">

doc/UserGuide.dox

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@
155155
- \subpage CanopyGeneratorDoc "Canopy Generator: Simple generation of different type of plant and canopy geometries."
156156
- \subpage PlantArchitectureDoc "Plant Architecture: Flexible procedural plant generation with dynamic growth and phenology."
157157
- \subpage PlantHydraulicsDoc "Plant Hydraulics: Models the water potentials, water contents, hydraulic conductances, and hydraulic capacitances."
158+
- \subpage LeafOpticsDoc "Leaf Optics: Implementation of the PROSPECT-PRO leaf optical model of leaf reflectance and transmittance spectra."
158159
- \subpage ProjectBuilderDoc "GUI and XML interface for creating and running Helios projects."
159160

160161
*/
@@ -1195,17 +1196,17 @@ This will first rotate the patch by 0.25\f$\pi\f$ rad about the x-axis such that
11951196

11961197
<table>
11971198
<tr><th>Data type</th><th>Enumeration (HeliosDataType)</th></tr>
1198-
<tr><td>\htmlonly<font face="courier" color="green">int</font>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_INT "HELIOS_TYPE_INT"</td></tr>
1199-
<tr><td>\htmlonly<font face="courier" color="green">uint</font>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_UINT "HELIOS_TYPE_UINT"</td></tr>
1200-
<tr><td>\htmlonly<font face="courier" color="green">float</font>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_FLOAT "HELIOS_TYPE_FLOAT"</td></tr>
1201-
<tr><td>\htmlonly<font face="courier" color="green">double</font>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_DOUBLE "HELIOS_TYPE_DOUBLE"</td></tr>
1202-
<tr><td>\htmlonly<font face="courier" color="green">vec2</font>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_VEC2 "HELIOS_TYPE_VEC2"</td></tr>
1203-
<tr><td>\htmlonly<font face="courier" color="green">vec3</font>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_VEC3 "HELIOS_TYPE_VEC3"</td></tr>
1204-
<tr><td>\htmlonly<font face="courier" color="green">vec4</font>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_VEC4 "HELIOS_TYPE_VEC4"</td></tr>
1205-
<tr><td>\htmlonly<font face="courier" color="green">int2</font>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_INT2 "HELIOS_TYPE_INT2"</td></tr>
1206-
<tr><td>\htmlonly<font face="courier" color="green">int3</font>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_INT3 "HELIOS_TYPE_INT3"</td></tr>
1207-
<tr><td>\htmlonly<font face="courier" color="green">int4</font>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_INT4 "HELIOS_TYPE_INT4"</td></tr>
1208-
<tr><td>\htmlonly<font face="courier" color="green">std::string</font>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_STRING "HELIOS_TYPE_STRING"</td></tr>
1199+
<tr><td>\htmlonly<span style="font-family: Courier, monospace; color: green;">int</span>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_INT "HELIOS_TYPE_INT"</td></tr>
1200+
<tr><td>\htmlonly<span style="font-family: Courier, monospace; color: green;">uint</span>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_UINT "HELIOS_TYPE_UINT"</td></tr>
1201+
<tr><td>\htmlonly<span style="font-family: Courier, monospace; color: green;">float</span>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_FLOAT "HELIOS_TYPE_FLOAT"</td></tr>
1202+
<tr><td>\htmlonly<span style="font-family: Courier, monospace; color: green;">double</span>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_DOUBLE "HELIOS_TYPE_DOUBLE"</td></tr>
1203+
<tr><td>\htmlonly<span style="font-family: Courier, monospace; color: green;">vec2</span>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_VEC2 "HELIOS_TYPE_VEC2"</td></tr>
1204+
<tr><td>\htmlonly<span style="font-family: Courier, monospace; color: green;">vec3</span>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_VEC3 "HELIOS_TYPE_VEC3"</td></tr>
1205+
<tr><td>\htmlonly<span style="font-family: Courier, monospace; color: green;">vec4</span>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_VEC4 "HELIOS_TYPE_VEC4"</td></tr>
1206+
<tr><td>\htmlonly<span style="font-family: Courier, monospace; color: green;">int2</span>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_INT2 "HELIOS_TYPE_INT2"</td></tr>
1207+
<tr><td>\htmlonly<span style="font-family: Courier, monospace; color: green;">int3</span>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_INT3 "HELIOS_TYPE_INT3"</td></tr>
1208+
<tr><td>\htmlonly<span style="font-family: Courier, monospace; color: green;">int4</span>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_INT4 "HELIOS_TYPE_INT4"</td></tr>
1209+
<tr><td>\htmlonly<span style="font-family: Courier, monospace; color: green;">std::string</span>\endhtmlonly</td><td>\ref helios::HELIOS_TYPE_STRING "HELIOS_TYPE_STRING"</td></tr>
12091210
</table>
12101211

12111212
<!--

doc/assets/navsync-default.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*!
2+
* Toggle the navtree sync button twice during page load.
3+
* This resets Doxygen's internal sync state so the
4+
* navigation pane stays synchronized and the icon shows
5+
* the correct status.
6+
*/
7+
window.addEventListener('load', function() {
8+
var navSync = document.getElementById('nav-sync');
9+
if (!navSync) return;
10+
try {
11+
navSync.click();
12+
} catch (e) {
13+
/* ignore */
14+
}
15+
});

0 commit comments

Comments
 (0)