Skip to content

Commit e9b075a

Browse files
bnbailey-pslaponcedeleon283ehfrehner
committed
[1.3.27] 2025-02-11
**Some experimental OpenMP parallelization has been added. This is not enabled by default yet, but can be turned on by setting the CMake option ENABLE_OPENMP to ON.** **Updates to core CMakeLists.txt to use more modern CMake features.** *Context* - Context::pruneTubeNodes() was added to allow for removal of part of a tube object. *Plant Architecture* - Added ground cherry weed model. - Minor fix in PlantArchitecture::getPlsantLeafInclinationAngleDistribution() to prevent rare out of range index. - Changed PlantArchitecture::getPlantLeafInclinationAngleDistribution() to area-weight the distribution, and removed the 'normalize' optional argument. - Added PlantArchitecture::prunBranch() method to remove all or part of a branch and its downstream branches. - Removed shoot parameter 'elongation_rate'. There is now an 'elongation_rate_max' shoot parameter that can be set by the user. The actual elongation rate can be reduced dynamically if the carbohydrate model is enabled. - Many updates to carbohydrate model. Credit to Ethan Frehner for these updates. *LiDAR* - Added exportTriangleAzimuthDistribution() to write the triangulated azimuthal angle distribution to a file. Credit to Alejandra Ponce de Leon for this addition. - The output distribution from exportTriangleInclinationDistribution() was not being normalized. *Radiation* - Added bindweed spectra to the default library. - There was an error in the writeObjectDataLabelMap() method that could cause undefined behavior if the UUID in the pixel label map did not exist in the Context. - There was an error in the writeObjectDataLabelMap() method where the primitive UUID was being used instead of the object ID. - There was an error in the model that could cause incorrect assignment of radiative properties if runBand() is called with fewer bands than a previous call to runBand(). - The previous version could cause unnecessary updating of radiative properties, resulting in a performance hit. This has been fixed. - Revised the radiation plug-in CMakeLists.txt to use a modern CMake approach for building CUDA source files. This update should also enable indexing of .cu source files in IDEs such as CLion. Co-authored-by: Alejandra Ponce de Leon <[email protected]> Co-authored-by: Ethan Frehner <[email protected]>
1 parent bd2104e commit e9b075a

File tree

956 files changed

+53288
-33359
lines changed

Some content is hidden

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

956 files changed

+53288
-33359
lines changed

core/CMakeLists.txt

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,43 @@ cmake_minimum_required(VERSION 3.15)
22

33
project(helios)
44

5-
include_directories(include)
6-
75
if(NOT DEFINED CMAKE_SUPPRESS_DEVELOPER_WARNINGS)
86
set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS 1 CACHE INTERNAL "No dev warnings")
97
endif()
108

11-
add_library( helios STATIC ${CMAKE_CURRENT_SOURCE_DIR}/src/Context.cpp;${CMAKE_CURRENT_SOURCE_DIR}/src/Context_fileIO.cpp;${CMAKE_CURRENT_SOURCE_DIR}/src/Context_data.cpp;${CMAKE_CURRENT_SOURCE_DIR}/src/global.cpp;${CMAKE_CURRENT_SOURCE_DIR}/src/selfTest.cpp;${CMAKE_CURRENT_SOURCE_DIR}/src/pugixml.cpp )
12-
9+
# Defining Helios Context source files to be built
10+
set(HELIOS_SOURCES
11+
src/Context.cpp
12+
src/Context_fileIO.cpp
13+
src/Context_data.cpp
14+
src/global.cpp
15+
src/selfTest.cpp
16+
src/pugixml.cpp
17+
)
18+
add_library(helios STATIC ${HELIOS_SOURCES})
19+
20+
# Defining Helios Context include files
21+
target_include_directories(helios
22+
PUBLIC
23+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
24+
$<INSTALL_INTERFACE:include>
25+
)
26+
27+
# External libraries
1328
include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/lib/zlib")
14-
add_subdirectory( "${CMAKE_CURRENT_SOURCE_DIR}/lib/zlib" "${CMAKE_BINARY_DIR}/lib/zlib" )
15-
target_link_libraries( zlibstatic )
29+
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/lib/zlib" "${CMAKE_BINARY_DIR}/lib/zlib")
1630

1731
include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/lib/libpng")
18-
add_subdirectory( "${CMAKE_CURRENT_SOURCE_DIR}/lib/libpng" "${CMAKE_BINARY_DIR}/lib/libpng" )
32+
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/lib/libpng" "${CMAKE_BINARY_DIR}/lib/libpng")
1933
add_dependencies( png_static zlibstatic )
2034

21-
target_link_libraries( helios png_static )
22-
2335
include_directories("${CMAKE_BINARY_DIR}/lib/libjpeg-9a;${CMAKE_CURRENT_SOURCE_DIR}/lib/libjpeg-9a")
24-
add_subdirectory("lib/libjpeg-9a" "${CMAKE_BINARY_DIR}/lib/libjpeg-9a" )
25-
target_link_libraries( helios jpeg )
36+
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/lib/libjpeg-9a" "${CMAKE_BINARY_DIR}/lib/libjpeg-9a")
37+
38+
target_link_libraries( helios PRIVATE png_static jpeg ) #note that zlib is already linked by libpng
2639

2740
file( COPY "${CMAKE_CURRENT_SOURCE_DIR}/lib/images" DESTINATION "${CMAKE_BINARY_DIR}/lib/" )
2841
file( COPY "${CMAKE_CURRENT_SOURCE_DIR}/lib/models" DESTINATION "${CMAKE_BINARY_DIR}/lib/" )
2942
file( COPY "${CMAKE_CURRENT_SOURCE_DIR}/lib/testdata" DESTINATION "${CMAKE_BINARY_DIR}/lib/" )
3043

31-
set( PLUGIN_INCLUDE_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include; PARENT_SCOPE )
44+
set( PLUGIN_INCLUDE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/include;" PARENT_SCOPE )

core/CMake_project.txt

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
option(ENABLE_OPENMP "Enable building with OpenMP" OFF)
2+
3+
set(CMAKE_CXX_STANDARD 17)
4+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
5+
set(CMAKE_CXX_EXTENSIONS OFF)
6+
17
if ( WIN32 )
28
SET(CMAKE_C_COMPILER_ID "MSVC")
39
SET(CMAKE_CXX_COMPILER_ID "MSVC")
@@ -13,15 +19,7 @@ if ( WIN32 )
1319
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_BINARY_DIR}" )
1420
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_BINARY_DIR}/lib" )
1521
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_BINARY_DIR}/lib" )
16-
endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES )
17-
else()
18-
SET(CMAKE_C_COMPILER_ID "GNU")
19-
SET(CMAKE_CXX_COMPILER_ID "GNU")
20-
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
21-
if( CMAKE_BUILD_TYPE STREQUAL Debug )
22-
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g" )
23-
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
24-
endif()
22+
endforeach(OUTPUTCONFIG)
2523
endif()
2624
if( CMAKE_BUILD_TYPE STREQUAL Debug )
2725
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHELIOS_DEBUG" )
@@ -49,9 +47,31 @@ foreach(PLUGIN ${PLUGINS})
4947
endif()
5048
add_subdirectory( "${BASE_DIRECTORY}/plugins/${PLUGIN}" "${PROJECT_BINARY_DIR}/plugins/${PLUGIN}" )
5149
target_link_libraries( ${EXECUTABLE_NAME} ${PLUGIN} )
52-
target_link_libraries( ${PLUGIN} helios )
50+
if( NOT APPLE )
51+
target_link_libraries( ${PLUGIN} helios )
52+
endif()
5353
endforeach(PLUGIN)
5454
include_directories( "${PLUGIN_INCLUDE_PATHS};${CMAKE_CURRENT_SOURCE_DIRECTORY}" )
5555

56+
if( ENABLE_OPENMP )
57+
find_package(OpenMP)
58+
if (OpenMP_CXX_FOUND)
59+
message( "-- Enabling experimental OpenMP support" )
60+
target_link_libraries(${EXECUTABLE_NAME} OpenMP::OpenMP_CXX)
61+
target_compile_definitions(${EXECUTABLE_NAME} PRIVATE USE_OPENMP)
62+
if ( WIN32 )
63+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp")
64+
else()
65+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
66+
endif()
67+
else()
68+
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
69+
message(WARNING "You are using Apple Clang compiler, which does not support OpenMP. The program will compile without OpenMP support.")
70+
else()
71+
message(WARNING "OpenMP not found! The program will compile without OpenMP support.")
72+
endif()
73+
endif()
74+
endif()
75+
5676
enable_testing()
57-
add_test(Test0,"${EXECUTABLE_NAME}" "0")
77+
add_test(NAME Test0 COMMAND ${EXECUTABLE_NAME} 0)

core/include/Context.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,12 @@ class Tube : public CompoundObject {
735735
*/
736736
void setTubeNodes( const std::vector<helios::vec3> &node_xyz );
737737

738+
//! Remove a portion of the tube downstream of a specified node
739+
/**
740+
* \param[in] node_index Index of the tube segment node beyond which will be removed
741+
*/
742+
void pruneTubeNodes( uint node_index );
743+
738744
protected:
739745

740746
std::vector<helios::vec3> nodes;
@@ -4793,6 +4799,13 @@ class Context{
47934799
*/
47944800
void scaleTubeLength( uint ObjID, float scale_factor );
47954801

4802+
//! Remove a portion of the tube downstream of a specified node
4803+
/**
4804+
* \param[in] ObjID object ID of the Tube object
4805+
* \param[in] node_index Index of the tube segment node beyond which will be removed
4806+
*/
4807+
void pruneTubeNodes( uint ObjID, uint node_index );
4808+
47964809
//! Set tube vertex coordinates at each segment node
47974810
/**
47984811
* \param[in] ObjID object ID of the Tube object

core/include/global.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ constexpr float PI_F = 3.14159265358979323846f;
5353
#include <iomanip>
5454
#include <filesystem>
5555

56+
#ifdef USE_OPENMP
57+
#include <omp.h>
58+
#endif
59+
5660
typedef unsigned int uint;
5761

5862
#include "helios_vector_types.h"

core/src/Context.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3913,6 +3913,33 @@ void Tube::setTubeNodes( const std::vector<helios::vec3> &node_xyz ){
39133913

39143914
}
39153915

3916+
void Tube::pruneTubeNodes( uint node_index ){
3917+
3918+
if( node_index >= nodes.size() ){
3919+
helios_runtime_error("ERROR (Tube::pruneTubeNodes): Node index of " + std::to_string(node_index) + " is out of bounds.");
3920+
}
3921+
3922+
if( node_index == 0 ){
3923+
context->deleteObject(this->OID);
3924+
return;
3925+
}
3926+
3927+
nodes.erase( nodes.begin() + node_index, nodes.end() );
3928+
triangle_vertices.erase( triangle_vertices.begin() + node_index, triangle_vertices.end() );
3929+
radius.erase( radius.begin() + node_index, radius.end() );
3930+
colors.erase( colors.begin() + node_index, colors.end() );
3931+
3932+
int ii=0;
3933+
for (int i = node_index; i < nodes.size() - 1; i++) {
3934+
for(int j=0; j < subdiv; j++ ) {
3935+
context->deletePrimitive(UUIDs.at(ii));
3936+
context->deletePrimitive(UUIDs.at(ii+1));
3937+
ii += 2;
3938+
}
3939+
}
3940+
3941+
}
3942+
39163943
void Tube::updateTriangleVertices(){
39173944

39183945
vec3 v0, v1, v2;
@@ -8212,6 +8239,13 @@ void Context::scaleTubeLength( uint ObjID, float scale_factor ){
82128239
dynamic_cast<Tube*>(objects.at(ObjID))->scaleTubeLength(scale_factor);
82138240
}
82148241

8242+
void Context::pruneTubeNodes( uint ObjID, uint node_index ){
8243+
if( objects.find(ObjID) == objects.end() ) {
8244+
helios_runtime_error("ERROR (Context::pruneTubeNodes): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
8245+
}
8246+
dynamic_cast<Tube*>(objects.at(ObjID))->pruneTubeNodes(node_index);
8247+
}
8248+
82158249
void Context::setTubeNodes( uint ObjID, const std::vector<helios::vec3> &node_xyz ){
82168250
if( objects.find(ObjID) == objects.end() ) {
82178251
helios_runtime_error("ERROR (Context::setTubeNodes): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");

core/src/Context_fileIO.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4142,10 +4142,10 @@ void Context::writeOBJ( const std::string &filename, const std::vector<uint> &UU
41424142
// - it would make more sense to write patches as quads rather than two triangles
41434143

41444144
if( UUIDs.empty() ){
4145-
std::cout << "WARNING (Context::writeOBJ): No primitives found to write - OBJ file will not be written." << std::endl;
4145+
std::cout << "WARNING (Context::writeOBJ): No primitives found to write - OBJ file " << filename << " will not be written." << std::endl;
41464146
return;
41474147
}else if( filename.empty() ){
4148-
std::cout << "WARNING (Context::writeOBJ): Filename was empty - OBJ file will not be written." << std::endl;
4148+
std::cout << "WARNING (Context::writeOBJ): Filename was empty - OBJ file " << filename << " will not be written." << std::endl;
41494149
return;
41504150
}
41514151

doc/CHANGELOG

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2023,4 +2023,32 @@ The radiation model has been re-designed, with the following primary additions:
20232023
- Added mouse-based camera controls in the interactive visualizer. Credit to Sean Banks for this update.
20242024

20252025
*Plant Architecture*
2026-
- Added methods for querying bulk properties of a plant (total leaf count, stem height, plant height, leaf angle distribution) and write plant mesh vertices to file.
2026+
- Added methods for querying bulk properties of a plant (total leaf count, stem height, plant height, leaf angle distribution) and write plant mesh vertices to file.
2027+
2028+
[1.3.27] 2025-02-11
2029+
2030+
**Some experimental OpenMP parallelization has been added. This is not enabled by default yet, but can be turned on by setting the CMake option ENABLE_OPENMP to ON.**
2031+
**Updates to core CMakeLists.txt to use more modern CMake features.**
2032+
2033+
*Context*
2034+
- Context::pruneTubeNodes() was added to allow for removal of part of a tube object.
2035+
2036+
*Plant Architecture*
2037+
- Added ground cherry weed model.
2038+
- Minor fix in PlantArchitecture::getPlsantLeafInclinationAngleDistribution() to prevent rare out of range index.
2039+
- Changed PlantArchitecture::getPlantLeafInclinationAngleDistribution() to area-weight the distribution, and removed the 'normalize' optional argument.
2040+
- Added PlantArchitecture::prunBranch() method to remove all or part of a branch and its downstream branches.
2041+
- Removed shoot parameter 'elongation_rate'. There is now an 'elongation_rate_max' shoot parameter that can be set by the user. The actual elongation rate can be reduced dynamically if the carbohydrate model is enabled.
2042+
- Many updates to carbohydrate model. Credit to Ethan Frehner for these updates.
2043+
2044+
*LiDAR*
2045+
- Added exportTriangleAzimuthDistribution() to write the triangulated azimuthal angle distribution to a file. Credit to Alejandra Ponce de Leon for this addition.
2046+
- The output distribution from exportTriangleInclinationDistribution() was not being normalized.
2047+
2048+
*Radiation*
2049+
- Added bindweed spectra to the default library.
2050+
- There was an error in the writeObjectDataLabelMap() method that could cause undefined behavior if the UUID in the pixel label map did not exist in the Context.
2051+
- There was an error in the writeObjectDataLabelMap() method where the primitive UUID was being used instead of the object ID.
2052+
- There was an error in the model that could cause incorrect assignment of radiative properties if runBand() is called with fewer bands than a previous call to runBand().
2053+
- The previous version could cause unnecessary updating of radiative properties, resulting in a performance hit. This has been fixed.
2054+
- Revised the radiation plug-in CMakeLists.txt to use a modern CMake approach for building CUDA source files. This update should also enable indexing of .cu source files in IDEs such as CLion.

doc/Doxyfile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,7 +1298,7 @@ HTML_EXTRA_STYLESHEET =
12981298
# files will be copied as-is; there are no commands or markers available.
12991299
# This tag requires that the tag GENERATE_HTML is set to YES.
13001300

1301-
HTML_EXTRA_FILES =
1301+
HTML_EXTRA_FILES = /Users/bnbailey/Dropbox/Helios/doc/assets/doxygen-awesome-darkmode-toggle.js
13021302

13031303
# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
13041304
# should be rendered with a dark or light theme.
@@ -1611,7 +1611,7 @@ DISABLE_INDEX = NO
16111611
# The default value is: NO.
16121612
# This tag requires that the tag GENERATE_HTML is set to YES.
16131613

1614-
GENERATE_TREEVIEW = NO
1614+
GENERATE_TREEVIEW = YES
16151615

16161616
# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
16171617
# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
@@ -1623,7 +1623,7 @@ GENERATE_TREEVIEW = NO
16231623
# The default value is: NO.
16241624
# This tag requires that the tag GENERATE_HTML is set to YES.
16251625

1626-
FULL_SIDEBAR = NO
1626+
FULL_SIDEBAR = YES
16271627

16281628
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
16291629
# doxygen will group on one line in the generated HTML documentation.
@@ -1702,7 +1702,7 @@ USE_MATHJAX = NO
17021702
# The default value is: MathJax_2.
17031703
# This tag requires that the tag USE_MATHJAX is set to YES.
17041704

1705-
MATHJAX_VERSION = MathJax_2
1705+
MATHJAX_VERSION = MathJax_3
17061706

17071707
# When MathJax is enabled you can set the default output format to be used for
17081708
# the MathJax output. For more details about the output format see MathJax

doc/UserGuide.dox

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*! \mainpage Helios Documentation v1.3.26
1+
/*! \mainpage Helios Documentation
22

33
<p> <br> </p>
44

@@ -40,15 +40,19 @@ $ git pull
4040
$ git log
4141
~~~~~~
4242

43-
<p> <br><br><br><br> </p>
43+
<p> <br><br><br><br> </p>
4444

45-
\image html doc/images/PSL_logo_compact.png
45+
<div align="center">
46+
\image html doc/images/PSL_logo_compact.png
47+
</div>
4648

49+
<!--
4750
<p> <br><br> </p>
4851

4952
Financial support provided by:
5053

5154
\image html doc/images/sponsors.jpg
55+
-->
5256

5357
<p> <br><br> </p>
5458

@@ -348,7 +352,7 @@ $ git pull
348352

349353
Projects that use the Helios API are typically built using the CMake package a CMakeLists.txt file. Helios requires CMake version 3.15+. A prototypical CMakeLists.txt file used for building Helios samples and projects is given in the code sample below. Inputs for the specific case are entered in the top block of code by setting variables (see the CMake 'set' command reference). The user sets the location of the Helios base directory, the name of the executable file, any source or header files, and a list of plug-ins to use (the example below uses the 'visualizer' plug-in). The last line in the file references another file in the core/ directory that contains additional code for setting up the project.
350354

351-
~~~~~~
355+
```
352356
# Helios standard CMakeLists.txt file version 1.9
353357
cmake_minimum_required(VERSION 3.15)
354358
project(helios)
@@ -369,21 +373,21 @@ $ git pull
369373

370374
#-------- DO NOT MODIFY ---------#
371375
include( "${BASE_DIRECTORY}/core/CMake_project.txt" )
372-
~~~~~~
376+
```
373377

374378
The easiest way to compile the code is by using an IDE such as CLion, which is described in detail on the page \ref CLionIDE "Using the CLion IDE with Helios".
375379

376380
To build the code from the command line based on the CMakeLists.txt file, which creates a makefile, simply run the command 'cmake', followed by the path to the CMakeLists.txt file. If, as in the examples above, you are currently in the build directory and your CMakeLists.txt file is located one directory up, the CMake build is accomplished through:
377381

378-
~~~~~~
382+
```
379383
$ cmake ..
380-
~~~~~~
384+
```
381385

382386
By default, this will build Helios in "debug" mode. This is useful for debugging and testing because it will generate debug symbols and output more detailed error messages to the command line. However, this will make the code run much slower because it disables compiler optimizations (usually 3x slower on Linux and 4-5x slower on PC). For 'production' runs, it is recommended to build in 'release' mode in order to enable compiler optimizations. This is accomplished by passing an additional command-line argument to CMake:
383387

384-
~~~~~~
388+
```
385389
$ cmake -DCMAKE_BUILD_TYPE='Release' ..
386-
~~~~~~
390+
```
387391

388392
The code can then be compiled by issuing the 'make' command from the build directory, which will produce an executable in the build directory.
389393

@@ -459,20 +463,20 @@ $ git pull
459463

460464
In order to use the Context, the following header must be included:
461465

462-
~~~~~~{.cpp}
466+
~~~
463467
#include "Context.h"
464-
~~~~~~
468+
~~~
465469

466470
The context is typically created within the main function:
467471

468-
~~~~~~{.cpp}
472+
~~~
469473
#include "Context.h"
470474
using namespace helios;
471475

472476
int main(){
473477
Context context;
474478
}
475-
~~~~~~
479+
~~~
476480

477481
The Context is usually passed to plugins (see \ref Plugins), which gives them access to geometry and data.
478482

@@ -1621,7 +1625,7 @@ $ git pull
16211625

16221626
\section XMLread Reading XML Files
16231627

1624-
XML files can be read by the Context via the function \ref loadXML(). This function parses the XML file and adds all specified structures (see above) to the Context. Below is an example of how to load an XML file into the Context.
1628+
XML files can be read by the Context via the function \ref Context::loadXML(). This function parses the XML file and adds all specified structures (see above) to the Context. Below is an example of how to load an XML file into the Context.
16251629
~~~~~~{.cpp}
16261630
#include "Context.h"
16271631
using namespace helios;
@@ -1752,7 +1756,7 @@ $ git pull
17521756

17531757
\section Export Exporting Project to XML File Format
17541758

1755-
All geometry and global/primitive data loaded into the Context can be written to an XML file using the \ref writeXML() function, which can be later read back in using the \ref 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.
1759+
All geometry and global/primitive data loaded into the Context can be written to an XML file using the \ref Context::writeXML() function, which can be later read back in using the \ref Context::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.
17561760

17571761
An XML file can be written as follows:
17581762

0 commit comments

Comments
 (0)